mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
[JAEGER] Merge from tracemonkey.
This commit is contained in:
commit
dd9c55abdd
@ -45,7 +45,7 @@
|
||||
interface nsIAccessible;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(035c0c0e-41e3-4985-8ad9-d9f14cdc667a)]
|
||||
[scriptable, uuid(cb0bf7b9-117e-40e2-9e46-189c3d43ce4a)]
|
||||
interface nsIAccessibleTable : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -104,6 +104,17 @@ interface nsIAccessibleTable : nsISupports
|
||||
*/
|
||||
long getRowIndexAt(in long cellIndex);
|
||||
|
||||
/**
|
||||
* Translate the given cell index into the corresponding row and column
|
||||
* indices.
|
||||
*
|
||||
* @param cellIndex [in] cell index to return row and column indices for
|
||||
* @param rowIndex [out] row index at the given cell index
|
||||
* @param columnIndex [out] column index at the given cell index
|
||||
*/
|
||||
void getRowAndColumnIndicesAt(in long cellIndex,
|
||||
out long rowIndex, out long columnIndex);
|
||||
|
||||
/**
|
||||
* Return the number of columns occupied by the accessible cell at
|
||||
* the specified row and column in the table. The result differs from 1 if
|
||||
|
169
accessible/src/base/AccGroupInfo.cpp
Normal file
169
accessible/src/base/AccGroupInfo.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/* ***** 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) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* 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 ***** */
|
||||
|
||||
#include "AccGroupInfo.h"
|
||||
|
||||
AccGroupInfo::AccGroupInfo(nsAccessible* aItem, PRUint32 aRole) :
|
||||
mPosInSet(0), mSetSize(0), mParent(nsnull)
|
||||
{
|
||||
nsAccessible* parent = aItem->GetParent();
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
PRInt32 indexInParent = aItem->GetIndexInParent();
|
||||
PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(aItem);
|
||||
|
||||
// Compute position in set.
|
||||
mPosInSet = 1;
|
||||
for (PRInt32 idx = indexInParent - 1; idx >=0 ; idx--) {
|
||||
nsAccessible* sibling = parent->GetChildAt(idx);
|
||||
PRUint32 siblingRole = nsAccUtils::Role(sibling);
|
||||
|
||||
// If the sibling is separator then the group is ended.
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
||||
break;
|
||||
|
||||
// If sibling is not visible and hasn't the same base role.
|
||||
if (BaseRole(siblingRole) != aRole ||
|
||||
nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)
|
||||
continue;
|
||||
|
||||
// Check if it's hierarchical flatten structure, i.e. if the sibling
|
||||
// level is lesser than this one then group is ended, if the sibling level
|
||||
// is greater than this one then the group is split by some child elements
|
||||
// (group will be continued).
|
||||
PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
|
||||
if (siblingLevel < level) {
|
||||
mParent = sibling;
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip subset.
|
||||
if (siblingLevel > level)
|
||||
continue;
|
||||
|
||||
// If the previous item in the group has calculated group information then
|
||||
// build group information for this item based on found one.
|
||||
if (sibling->mGroupInfo) {
|
||||
mPosInSet += sibling->mGroupInfo->mPosInSet;
|
||||
mParent = sibling->mGroupInfo->mParent;
|
||||
mSetSize = sibling->mGroupInfo->mSetSize;
|
||||
return;
|
||||
}
|
||||
|
||||
mPosInSet++;
|
||||
}
|
||||
|
||||
// Compute set size.
|
||||
mSetSize = mPosInSet;
|
||||
|
||||
PRInt32 siblingCount = parent->GetChildCount();
|
||||
for (PRInt32 idx = indexInParent + 1; idx < siblingCount; idx++) {
|
||||
nsAccessible* sibling = parent->GetChildAt(idx);
|
||||
|
||||
PRUint32 siblingRole = nsAccUtils::Role(sibling);
|
||||
|
||||
// If the sibling is separator then the group is ended.
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
||||
break;
|
||||
|
||||
// If sibling is visible and has the same base role
|
||||
if (BaseRole(siblingRole) != aRole ||
|
||||
nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)
|
||||
continue;
|
||||
|
||||
// and check if it's hierarchical flatten structure.
|
||||
PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
|
||||
if (siblingLevel < level)
|
||||
break;
|
||||
|
||||
// Skip subset.
|
||||
if (siblingLevel > level)
|
||||
continue;
|
||||
|
||||
// If the next item in the group has calculated group information then
|
||||
// build group information for this item based on found one.
|
||||
if (sibling->mGroupInfo) {
|
||||
mParent = sibling->mGroupInfo->mParent;
|
||||
mSetSize = sibling->mGroupInfo->mSetSize;
|
||||
return;
|
||||
}
|
||||
|
||||
mSetSize++;
|
||||
}
|
||||
|
||||
if (mParent)
|
||||
return;
|
||||
|
||||
// Compute parent.
|
||||
PRUint32 parentRole = nsAccUtils::Role(parent);
|
||||
|
||||
// In the case of ARIA row in treegrid, return treegrid since ARIA
|
||||
// groups aren't used to organize levels in ARIA treegrids.
|
||||
if (aRole == nsIAccessibleRole::ROLE_ROW &&
|
||||
parentRole == nsIAccessibleRole::ROLE_TREE_TABLE) {
|
||||
mParent = parent;
|
||||
return;
|
||||
}
|
||||
|
||||
// In the case of ARIA tree, a tree can be arranged by using ARIA groups
|
||||
// to organize levels. In this case the parent of the tree item will be
|
||||
// a group and the previous treeitem of that should be the tree item
|
||||
// parent. Or, if the parent is something other than a tree we will
|
||||
// return that.
|
||||
|
||||
if (parentRole != nsIAccessibleRole::ROLE_GROUPING) {
|
||||
mParent = parent;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAccessible* parentPrevSibling = parent->GetSiblingAtOffset(-1);
|
||||
PRUint32 parentPrevSiblingRole = nsAccUtils::Role(parentPrevSibling);
|
||||
if (parentPrevSiblingRole == nsIAccessibleRole::ROLE_TEXT_LEAF) {
|
||||
// XXX Sometimes an empty text accessible is in the hierarchy here,
|
||||
// although the text does not appear to be rendered, GetRenderedText()
|
||||
// says that it is so we need to skip past it to find the true
|
||||
// previous sibling.
|
||||
parentPrevSibling = parentPrevSibling->GetSiblingAtOffset(-1);
|
||||
parentPrevSiblingRole = nsAccUtils::Role(parentPrevSibling);
|
||||
}
|
||||
|
||||
// Previous sibling of parent group is a tree item, this is the
|
||||
// conceptual tree item parent.
|
||||
if (parentPrevSiblingRole == nsIAccessibleRole::ROLE_OUTLINEITEM)
|
||||
mParent = parentPrevSibling;
|
||||
}
|
96
accessible/src/base/AccGroupInfo.h
Normal file
96
accessible/src/base/AccGroupInfo.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* ***** 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) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef AccGroupInfo_h_
|
||||
#define AccGroupInfo_h_
|
||||
|
||||
#include "nsAccessible.h"
|
||||
#include "nsAccUtils.h"
|
||||
|
||||
/**
|
||||
* Calculate and store group information.
|
||||
*/
|
||||
class AccGroupInfo
|
||||
{
|
||||
public:
|
||||
AccGroupInfo(nsAccessible* aItem, PRUint32 aRole);
|
||||
~AccGroupInfo() { }
|
||||
|
||||
PRInt32 PosInSet() const { return mPosInSet; }
|
||||
PRUint32 SetSize() const { return mSetSize; }
|
||||
nsAccessible* GetConceptualParent() const { return mParent; }
|
||||
|
||||
/**
|
||||
* Create group info.
|
||||
*/
|
||||
static AccGroupInfo* CreateGroupInfo(nsAccessible* aAccessible)
|
||||
{
|
||||
PRUint32 role = nsAccUtils::Role(aAccessible);
|
||||
if (role != nsIAccessibleRole::ROLE_ROW &&
|
||||
role != nsIAccessibleRole::ROLE_GRID_CELL &&
|
||||
role != nsIAccessibleRole::ROLE_OUTLINEITEM &&
|
||||
role != nsIAccessibleRole::ROLE_OPTION &&
|
||||
role != nsIAccessibleRole::ROLE_LISTITEM &&
|
||||
role != nsIAccessibleRole::ROLE_MENUITEM &&
|
||||
role != nsIAccessibleRole::ROLE_CHECK_MENU_ITEM &&
|
||||
role != nsIAccessibleRole::ROLE_RADIO_MENU_ITEM &&
|
||||
role != nsIAccessibleRole::ROLE_RADIOBUTTON &&
|
||||
role != nsIAccessibleRole::ROLE_PAGETAB)
|
||||
return nsnull;
|
||||
|
||||
AccGroupInfo* info = new AccGroupInfo(aAccessible, BaseRole(role));
|
||||
return info;
|
||||
}
|
||||
|
||||
private:
|
||||
AccGroupInfo(const AccGroupInfo&);
|
||||
AccGroupInfo& operator =(const AccGroupInfo&);
|
||||
|
||||
static PRUint32 BaseRole(PRUint32 aRole)
|
||||
{
|
||||
if (aRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
|
||||
aRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
|
||||
return nsIAccessibleRole::ROLE_MENUITEM;
|
||||
return aRole;
|
||||
}
|
||||
|
||||
PRUint32 mPosInSet;
|
||||
PRUint32 mSetSize;
|
||||
nsAccessible* mParent;
|
||||
};
|
||||
|
||||
#endif
|
@ -49,6 +49,7 @@ LIBXUL_LIBRARY = 1
|
||||
|
||||
CPPSRCS = \
|
||||
AccCollector.cpp \
|
||||
AccGroupInfo.cpp \
|
||||
AccIterator.cpp \
|
||||
filters.cpp \
|
||||
nsAccDocManager.cpp \
|
||||
|
@ -221,6 +221,34 @@ nsARIAGridAccessible::GetRowIndexAt(PRInt32 aCellIndex, PRInt32 *aRowIndex)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsARIAGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
||||
PRInt32* aRowIndex,
|
||||
PRInt32* aColumnIndex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRowIndex);
|
||||
*aRowIndex = -1;
|
||||
NS_ENSURE_ARG_POINTER(aColumnIndex);
|
||||
*aColumnIndex = -1;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG(aCellIndex >= 0);
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
GetRowCount(&rowCount);
|
||||
|
||||
PRInt32 colsCount = 0;
|
||||
GetColumnCount(&colsCount);
|
||||
|
||||
NS_ENSURE_ARG(aCellIndex < rowCount * colsCount);
|
||||
|
||||
*aColumnIndex = aCellIndex % colsCount;
|
||||
*aRowIndex = aCellIndex / colsCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsARIAGridAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn,
|
||||
PRInt32 *aExtentCount)
|
||||
|
@ -39,11 +39,10 @@
|
||||
#ifndef _nsAccCache_H_
|
||||
#define _nsAccCache_H_
|
||||
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIAccessible;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible cache utils
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -367,106 +367,6 @@ nsAccUtils::GetAncestorWithRole(nsAccessible *aDescendant, PRUint32 aRole)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
||||
nsIContent *aStartContent,
|
||||
nsIAccessible **aTreeItemParentResult)
|
||||
{
|
||||
*aTreeItemParentResult = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessible> parentAccessible;
|
||||
aStartTreeItem->GetParent(getter_AddRefs(parentAccessible));
|
||||
if (!parentAccessible)
|
||||
return;
|
||||
|
||||
PRUint32 startTreeItemRole = nsAccUtils::Role(aStartTreeItem);
|
||||
|
||||
// Calculate tree grid row parent only if the row inside of ARIA treegrid.
|
||||
if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) {
|
||||
PRUint32 role = nsAccUtils::Role(parentAccessible);
|
||||
if (role != nsIAccessibleRole::ROLE_TREE_TABLE)
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a tree or treegrid that uses aria-level to define levels, so find
|
||||
// the first previous sibling accessible where level is defined to be less
|
||||
// than the current level.
|
||||
nsAutoString levelStr;
|
||||
if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) &&
|
||||
aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) {
|
||||
|
||||
PRInt32 success;
|
||||
PRInt32 level = levelStr.ToInteger(&success);
|
||||
if (level > 1 && NS_SUCCEEDED(success)) {
|
||||
nsCOMPtr<nsIAccessible> currentAccessible = aStartTreeItem, prevAccessible;
|
||||
while (PR_TRUE) {
|
||||
currentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
|
||||
currentAccessible.swap(prevAccessible);
|
||||
nsCOMPtr<nsIAccessNode> accessNode = do_QueryInterface(currentAccessible);
|
||||
if (!accessNode) {
|
||||
break; // Reached top of tree, no higher level found
|
||||
}
|
||||
PRUint32 role = nsAccUtils::Role(currentAccessible);
|
||||
if (role != startTreeItemRole)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> treeItemNode;
|
||||
accessNode->GetDOMNode(getter_AddRefs(treeItemNode));
|
||||
nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode);
|
||||
if (treeItemContent &&
|
||||
nsAccUtils::HasDefinedARIAToken(treeItemContent,
|
||||
nsAccessibilityAtoms::aria_level) &&
|
||||
treeItemContent->GetAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::aria_level, levelStr)) {
|
||||
if (levelStr.ToInteger(&success) < level && NS_SUCCEEDED(success)) {
|
||||
NS_ADDREF(*aTreeItemParentResult = currentAccessible);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the case of ARIA treegrid, return its parent since ARIA group isn't
|
||||
// used to organize levels in ARIA treegrids.
|
||||
|
||||
if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) {
|
||||
NS_ADDREF(*aTreeItemParentResult = parentAccessible);
|
||||
return; // The container for the tree grid rows
|
||||
}
|
||||
|
||||
// In the case of ARIA tree, a tree can be arranged by using role="group" to
|
||||
// organize levels. In this case the parent of the tree item will be a group
|
||||
// and the previous sibling of that should be the tree item parent. Or, if
|
||||
// the parent is something other than a tree we will return that.
|
||||
|
||||
PRUint32 role = nsAccUtils::Role(parentAccessible);
|
||||
if (role != nsIAccessibleRole::ROLE_GROUPING) {
|
||||
NS_ADDREF(*aTreeItemParentResult = parentAccessible);
|
||||
return; // The container for the tree items
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> prevAccessible;
|
||||
parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
|
||||
if (!prevAccessible)
|
||||
return;
|
||||
role = nsAccUtils::Role(prevAccessible);
|
||||
if (role == nsIAccessibleRole::ROLE_TEXT_LEAF) {
|
||||
// XXX Sometimes an empty text accessible is in the hierarchy here,
|
||||
// although the text does not appear to be rendered, GetRenderedText() says that it is
|
||||
// so we need to skip past it to find the true previous sibling
|
||||
nsCOMPtr<nsIAccessible> tempAccessible = prevAccessible;
|
||||
tempAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
|
||||
if (!prevAccessible)
|
||||
return;
|
||||
role = nsAccUtils::Role(prevAccessible);
|
||||
}
|
||||
if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
|
||||
// Previous sibling of parent group is a tree item -- this is the conceptual tree item parent
|
||||
NS_ADDREF(*aTreeItemParentResult = prevAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
nsAccessible *
|
||||
nsAccUtils::GetSelectableContainer(nsAccessible *aAccessible, PRUint32 aState)
|
||||
{
|
||||
|
@ -198,19 +198,6 @@ public:
|
||||
static nsAccessible * GetAncestorWithRole(nsAccessible *aDescendant,
|
||||
PRUint32 aRole);
|
||||
|
||||
/**
|
||||
* For an ARIA tree item , get the accessible that represents its conceptual parent.
|
||||
* This method will use the correct method for the given way the tree is constructed.
|
||||
* The conceptual parent is what the user sees as the parent, not the DOM or accessible parent.
|
||||
* @param aStartTreeItem The tree item to get the parent for
|
||||
* @param aStartTreeItemContent The content node for the tree item
|
||||
* @param The tree item's parent, or null if none
|
||||
*/
|
||||
static void
|
||||
GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
||||
nsIContent *aStartTreeItemContent,
|
||||
nsIAccessible **aTreeItemParent);
|
||||
|
||||
/**
|
||||
* Return single or multi selectable container for the given item.
|
||||
*
|
||||
|
@ -131,7 +131,7 @@ void nsAccessNode::LastRelease()
|
||||
NS_ASSERTION(!mWeakShell, "A Shutdown() impl forgot to call its parent's Shutdown?");
|
||||
}
|
||||
// ... then die.
|
||||
NS_DELETEXPCOM(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "nsIXBLAccessible.h"
|
||||
|
||||
#include "AccGroupInfo.h"
|
||||
#include "AccIterator.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
@ -2125,11 +2126,12 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
(mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
|
||||
mRoleMapEntry->role == nsIAccessibleRole::ROLE_ROW)) {
|
||||
|
||||
nsCOMPtr<nsIAccessible> accTarget;
|
||||
nsAccUtils::GetARIATreeItemParent(this, mContent,
|
||||
getter_AddRefs(accTarget));
|
||||
AccGroupInfo* groupInfo = GetGroupInfo();
|
||||
if (!groupInfo)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget);
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation,
|
||||
groupInfo->GetConceptualParent());
|
||||
}
|
||||
|
||||
// If accessible is in its own Window, or is the root of a document,
|
||||
@ -3091,98 +3093,24 @@ nsAccessible::GetActionRule(PRUint32 aStates)
|
||||
return eNoAction;
|
||||
}
|
||||
|
||||
AccGroupInfo*
|
||||
nsAccessible::GetGroupInfo()
|
||||
{
|
||||
if (mGroupInfo)
|
||||
return mGroupInfo;
|
||||
|
||||
mGroupInfo = AccGroupInfo::CreateGroupInfo(this);
|
||||
return mGroupInfo;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet, PRInt32 *aSetSize)
|
||||
{
|
||||
PRUint32 role = nsAccUtils::Role(this);
|
||||
if (role != nsIAccessibleRole::ROLE_LISTITEM &&
|
||||
role != nsIAccessibleRole::ROLE_MENUITEM &&
|
||||
role != nsIAccessibleRole::ROLE_CHECK_MENU_ITEM &&
|
||||
role != nsIAccessibleRole::ROLE_RADIO_MENU_ITEM &&
|
||||
role != nsIAccessibleRole::ROLE_RADIOBUTTON &&
|
||||
role != nsIAccessibleRole::ROLE_PAGETAB &&
|
||||
role != nsIAccessibleRole::ROLE_OPTION &&
|
||||
role != nsIAccessibleRole::ROLE_OUTLINEITEM &&
|
||||
role != nsIAccessibleRole::ROLE_ROW &&
|
||||
role != nsIAccessibleRole::ROLE_GRID_CELL)
|
||||
return;
|
||||
|
||||
PRUint32 baseRole = role;
|
||||
if (role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
|
||||
role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
|
||||
baseRole = nsIAccessibleRole::ROLE_MENUITEM;
|
||||
|
||||
nsAccessible* parent = GetParent();
|
||||
NS_ENSURE_TRUE(parent,);
|
||||
|
||||
PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(this);
|
||||
|
||||
// Compute 'posinset'.
|
||||
PRInt32 positionInGroup = 1;
|
||||
for (PRInt32 idx = mIndexInParent - 1; idx >= 0; idx--) {
|
||||
nsAccessible* sibling = parent->GetChildAt(idx);
|
||||
|
||||
PRUint32 siblingRole = nsAccUtils::Role(sibling);
|
||||
|
||||
// If the sibling is separator then the group is ended.
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
||||
break;
|
||||
|
||||
PRUint32 siblingBaseRole = siblingRole;
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
|
||||
siblingRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
|
||||
siblingBaseRole = nsIAccessibleRole::ROLE_MENUITEM;
|
||||
|
||||
// If sibling is visible and has the same base role
|
||||
if (siblingBaseRole == baseRole &&
|
||||
!(nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)) {
|
||||
|
||||
// and check if it's hierarchical flatten structure, i.e. if the sibling
|
||||
// level is lesser than this one then group is ended, if the sibling level
|
||||
// is greater than this one then the group is splited by some child
|
||||
// elements (group will be continued).
|
||||
PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
|
||||
if (siblingLevel < level)
|
||||
break;
|
||||
else if (level == siblingLevel)
|
||||
++ positionInGroup;
|
||||
}
|
||||
AccGroupInfo* groupInfo = GetGroupInfo();
|
||||
if (groupInfo) {
|
||||
*aPosInSet = groupInfo->PosInSet();
|
||||
*aSetSize = groupInfo->SetSize();
|
||||
}
|
||||
|
||||
// Compute 'setsize'.
|
||||
PRInt32 setSize = positionInGroup;
|
||||
|
||||
PRInt32 siblingCount = parent->GetChildCount();
|
||||
for (PRInt32 idx = mIndexInParent + 1; idx < siblingCount; idx++) {
|
||||
nsAccessible* sibling = parent->GetChildAt(idx);
|
||||
NS_ENSURE_TRUE(sibling,);
|
||||
|
||||
PRUint32 siblingRole = nsAccUtils::Role(sibling);
|
||||
|
||||
// If the sibling is separator then the group is ended.
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
||||
break;
|
||||
|
||||
PRUint32 siblingBaseRole = siblingRole;
|
||||
if (siblingRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
|
||||
siblingRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
|
||||
siblingBaseRole = nsIAccessibleRole::ROLE_MENUITEM;
|
||||
|
||||
// If sibling is visible and has the same base role
|
||||
if (siblingBaseRole == baseRole &&
|
||||
!(nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)) {
|
||||
|
||||
// and check if it's hierarchical flatten structure.
|
||||
PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
|
||||
if (siblingLevel < level)
|
||||
break;
|
||||
else if (level == siblingLevel)
|
||||
++ setSize;
|
||||
}
|
||||
}
|
||||
|
||||
*aPosInSet = positionInGroup;
|
||||
*aSetSize = setSize;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
class AccGroupInfo;
|
||||
class nsAccessible;
|
||||
class nsAccEvent;
|
||||
struct nsRoleMapEntry;
|
||||
@ -324,7 +325,12 @@ protected:
|
||||
* Set accessible parent and index in parent.
|
||||
*/
|
||||
void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
|
||||
void UnbindFromParent() { mParent = nsnull; mIndexInParent = -1; }
|
||||
void UnbindFromParent()
|
||||
{
|
||||
mParent = nsnull;
|
||||
mIndexInParent = -1;
|
||||
mGroupInfo = nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sibling accessible at the given offset.
|
||||
@ -424,6 +430,11 @@ protected:
|
||||
*/
|
||||
PRUint32 GetActionRule(PRUint32 aStates);
|
||||
|
||||
/**
|
||||
* Return group info.
|
||||
*/
|
||||
AccGroupInfo* GetGroupInfo();
|
||||
|
||||
/**
|
||||
* Fires platform accessible event. It's notification method only. It does
|
||||
* change nothing on Gecko side. Don't use it until you're sure what you do
|
||||
@ -440,6 +451,9 @@ protected:
|
||||
PRBool mAreChildrenInitialized;
|
||||
PRInt32 mIndexInParent;
|
||||
|
||||
nsAutoPtr<AccGroupInfo> mGroupInfo;
|
||||
friend class AccGroupInfo;
|
||||
|
||||
nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
|
||||
};
|
||||
|
||||
|
@ -953,6 +953,26 @@ nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
|
||||
return (*aRow == -1 || column == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTableAccessible::GetRowAndColumnIndicesAt(PRInt32 aIndex,
|
||||
PRInt32* aRowIdx,
|
||||
PRInt32* aColumnIdx)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRowIdx);
|
||||
*aRowIdx = -1;
|
||||
NS_ENSURE_ARG_POINTER(aColumnIdx);
|
||||
*aColumnIdx = -1;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsITableLayout* tableLayout = GetTableLayout();
|
||||
if (tableLayout)
|
||||
tableLayout->GetRowAndColumnByIndex(aIndex, aRowIdx, aColumnIdx);
|
||||
|
||||
return (*aRowIdx == -1 || *aColumnIdx == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
|
||||
PRInt32 aColumnIndex,
|
||||
|
@ -666,33 +666,28 @@ __try {
|
||||
if (!tableAcc)
|
||||
return E_FAIL;
|
||||
|
||||
PRInt32 row = -1;
|
||||
nsresult rv = tableAcc->GetRowIndexAt(aIndex, &row);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRInt32 column = -1;
|
||||
rv = tableAcc->GetColumnIndexAt(aIndex, &column);
|
||||
PRInt32 rowIdx = -1, columnIdx = -1;
|
||||
nsresult rv = tableAcc->GetRowAndColumnIndicesAt(aIndex, &rowIdx, &columnIdx);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRInt32 rowExtents = 0;
|
||||
rv = tableAcc->GetRowExtentAt(row, column, &rowExtents);
|
||||
rv = tableAcc->GetRowExtentAt(rowIdx, columnIdx, &rowExtents);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRInt32 columnExtents = 0;
|
||||
rv = tableAcc->GetColumnExtentAt(row, column, &columnExtents);
|
||||
rv = tableAcc->GetColumnExtentAt(rowIdx, columnIdx, &columnExtents);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRBool isSelected = PR_FALSE;
|
||||
rv = tableAcc->IsCellSelected(row, column, &isSelected);
|
||||
rv = tableAcc->IsCellSelected(rowIdx, columnIdx, &isSelected);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*aRow = row;
|
||||
*aColumn = column;
|
||||
*aRow = rowIdx;
|
||||
*aColumn = columnIdx;
|
||||
*aRowExtents = rowExtents;
|
||||
*aColumnExtents = columnExtents;
|
||||
*aIsSelected = isSelected;
|
||||
|
@ -412,6 +412,28 @@ nsXULListboxAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULListboxAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
||||
PRInt32* aRowIndex,
|
||||
PRInt32* aColumnIndex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRowIndex);
|
||||
*aRowIndex = -1;
|
||||
NS_ENSURE_ARG_POINTER(aColumnIndex);
|
||||
*aColumnIndex = -1;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 columnCount = 0;
|
||||
nsresult rv = GetColumnCount(&columnCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aColumnIndex = aCellIndex % columnCount;
|
||||
*aRowIndex = aCellIndex / columnCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULListboxAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn,
|
||||
PRInt32 *aCellSpans)
|
||||
|
@ -411,6 +411,28 @@ nsXULTreeGridAccessible::GetRowIndexAt(PRInt32 aCellIndex, PRInt32 *aRowIndex)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
|
||||
PRInt32* aRowIndex,
|
||||
PRInt32* aColumnIndex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRowIndex);
|
||||
*aRowIndex = -1;
|
||||
NS_ENSURE_ARG_POINTER(aColumnIndex);
|
||||
*aColumnIndex = -1;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 columnCount = 0;
|
||||
nsresult rv = GetColumnCount(&columnCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aColumnIndex = aCellIndex % columnCount;
|
||||
*aRowIndex = aCellIndex / columnCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
|
||||
PRInt32 aColumnIndex,
|
||||
|
@ -224,7 +224,7 @@ function testTableIndexes(aIdentifier, aIdxes)
|
||||
|
||||
if (idx != - 1) {
|
||||
|
||||
// getRowAtIndex
|
||||
// getRowIndexAt
|
||||
var origRowIdx = rowIdx;
|
||||
while (origRowIdx > 0 &&
|
||||
aIdxes[rowIdx][colIdx] == aIdxes[origRowIdx - 1][colIdx])
|
||||
@ -237,9 +237,9 @@ function testTableIndexes(aIdentifier, aIdxes)
|
||||
}
|
||||
|
||||
is(obtainedRowIdx, origRowIdx,
|
||||
id + ": row for index " + idx +" is not correct");
|
||||
id + ": row for index " + idx + " is not correct (getRowIndexAt)");
|
||||
|
||||
// getColumnAtIndex
|
||||
// getColumnIndexAt
|
||||
var origColIdx = colIdx;
|
||||
while (origColIdx > 0 &&
|
||||
aIdxes[rowIdx][colIdx] == aIdxes[rowIdx][origColIdx - 1])
|
||||
@ -252,7 +252,21 @@ function testTableIndexes(aIdentifier, aIdxes)
|
||||
}
|
||||
|
||||
is(obtainedColIdx, origColIdx,
|
||||
id + ": column for index " + idx +" is not correct");
|
||||
id + ": column for index " + idx + " is not correct (getColumnIndexAt)");
|
||||
|
||||
// getRowAndColumnIndicesAt
|
||||
var obtainedRowIdxObj = { }, obtainedColIdxObj = { };
|
||||
try {
|
||||
tableAcc.getRowAndColumnIndicesAt(idx, obtainedRowIdxObj,
|
||||
obtainedColIdxObj);
|
||||
} catch (e) {
|
||||
ok(false, id + ": can't get row and column indices for cell index " + idx + "," + e);
|
||||
}
|
||||
|
||||
is(obtainedRowIdxObj.value, origRowIdx,
|
||||
id + ": row for index " + idx + " is not correct (getRowAndColumnIndicesAt)");
|
||||
is(obtainedColIdxObj.value, origColIdx,
|
||||
id + ": column for index " + idx + " is not correct (getRowAndColumnIndicesAt)");
|
||||
|
||||
if (cellAcc) {
|
||||
|
||||
|
@ -134,5 +134,7 @@
|
||||
<true/>
|
||||
<key>CGDisableCoalescedUpdates</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.5</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -320,8 +320,6 @@ pref("browser.tabs.loadInBackground", true);
|
||||
pref("browser.tabs.opentabfor.middleclick", true);
|
||||
pref("browser.tabs.loadDivertedInBackground", false);
|
||||
pref("browser.tabs.loadBookmarksInBackground", false);
|
||||
pref("browser.tabs.tabMinWidth", 100);
|
||||
pref("browser.tabs.tabMaxWidth", 250);
|
||||
pref("browser.tabs.tabClipWidth", 140);
|
||||
|
||||
// Where to show tab close buttons:
|
||||
|
@ -130,7 +130,7 @@ var FullZoom = {
|
||||
|
||||
this._siteSpecificPref =
|
||||
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
||||
this.updateBackgroundTabs =
|
||||
this.updateBackgroundTabs =
|
||||
gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
|
||||
// Listen for changes to the browser.zoom branch so we can enable/disable
|
||||
// updating background tabs and per-site saving and restoring of zoom levels.
|
||||
|
@ -22,12 +22,18 @@ tabbrowser {
|
||||
|
||||
.tabbrowser-tab {
|
||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not([pinned]) {
|
||||
-moz-box-flex: 100;
|
||||
max-width: 250px;
|
||||
min-width: 100px;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not([fadein]) {
|
||||
max-width: 1px !important;
|
||||
min-width: 1px !important;
|
||||
max-width: 1px;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[fadein]:not([pinned]) {
|
||||
@ -48,9 +54,6 @@ tabbrowser {
|
||||
|
||||
.tabbrowser-tab[pinned] {
|
||||
position: fixed;
|
||||
-moz-box-flex: 0;
|
||||
min-width: 0 !important;
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[pinned] > .tab-text {
|
||||
@ -81,6 +84,12 @@ toolbar[printpreview="true"] {
|
||||
-moz-box-ordinal-group: 10;
|
||||
}
|
||||
|
||||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
#main-window[inFullscreen] > #appmenu-button-container {
|
||||
display: none;
|
||||
}
|
||||
%endif
|
||||
|
||||
toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
|
||||
display: none;
|
||||
}
|
||||
|
@ -4014,7 +4014,7 @@ var XULBrowserWindow = {
|
||||
}
|
||||
},
|
||||
|
||||
onLinkIconAvailable: function (aBrowser, aIconURL) {
|
||||
onLinkIconAvailable: function (aIconURL) {
|
||||
if (gProxyFavIcon && gBrowser.userTypedValue === null)
|
||||
PageProxySetIcon(aIconURL); // update the favicon in the URL bar
|
||||
},
|
||||
@ -4490,21 +4490,16 @@ var CombinedStopReload = {
|
||||
};
|
||||
|
||||
var TabsProgressListener = {
|
||||
onProgressChange: function (aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aRequest instanceof Ci.nsIChannel &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
|
||||
gCrashReporter.enabled) {
|
||||
gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
|
||||
onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
|
||||
// Filter out any sub-frame loads
|
||||
@ -4512,9 +4507,6 @@ var TabsProgressListener = {
|
||||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
},
|
||||
|
||||
onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
|
||||
},
|
||||
|
||||
onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
|
||||
if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
@ -4561,9 +4553,6 @@ var TabsProgressListener = {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -4727,12 +4716,12 @@ var TabsOnTop = {
|
||||
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
function updateAppButtonDisplay() {
|
||||
var menubarHidden =
|
||||
var displayAppButton = window.menubar.visible &&
|
||||
document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
|
||||
|
||||
document.getElementById("appmenu-button-container").hidden = !menubarHidden;
|
||||
document.getElementById("appmenu-button-container").hidden = !displayAppButton;
|
||||
|
||||
if (menubarHidden)
|
||||
if (displayAppButton)
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
else
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
@ -7772,6 +7761,10 @@ var TabContextMenu = {
|
||||
Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore).
|
||||
getClosedTabCount(window) == 0;
|
||||
|
||||
// Only one of pin/unpin should be visible
|
||||
document.getElementById("context_pinTab").hidden = this.contextTab.pinned;
|
||||
document.getElementById("context_unpinTab").hidden = !this.contextTab.pinned;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -126,6 +126,12 @@
|
||||
accesskey="&openTabInNewWindow.accesskey;"
|
||||
tbattr="tabbrowser-multiple"
|
||||
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
|
||||
<menuitem id="context_pinTab" label="&pinTab.label;"
|
||||
accesskey="&pinTab.accesskey;"
|
||||
oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
|
||||
<menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
|
||||
accesskey="&unpinTab.accesskey;"
|
||||
oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context_bookmarkTab"
|
||||
label="&bookmarkThisTab.label;"
|
||||
|
@ -122,6 +122,12 @@ Sanitizer.prototype = {
|
||||
// facility for timespan-based eviction. Wipe it.
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
} catch(er) {}
|
||||
|
||||
var imageCache = Cc["@mozilla.org/image/cache;1"].
|
||||
getService(Ci.imgICache);
|
||||
try {
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
} catch(er) {}
|
||||
},
|
||||
|
||||
get canClear()
|
||||
|
@ -263,6 +263,53 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_callProgressListeners">
|
||||
<parameter name="aBrowser"/>
|
||||
<parameter name="aMethod"/>
|
||||
<parameter name="aArguments"/>
|
||||
<parameter name="aCallGlobalListeners"/>
|
||||
<parameter name="aCallTabsListeners"/>
|
||||
<body><![CDATA[
|
||||
var rv = true;
|
||||
|
||||
if (!aBrowser)
|
||||
aBrowser = this.mCurrentBrowser;
|
||||
|
||||
if (aCallGlobalListeners != false &&
|
||||
aBrowser == this.mCurrentBrowser) {
|
||||
this.mProgressListeners.forEach(function (p) {
|
||||
if (aMethod in p) {
|
||||
try {
|
||||
if (!p[aMethod].apply(p, aArguments))
|
||||
rv = false;
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (aCallTabsListeners != false) {
|
||||
aArguments.unshift(aBrowser);
|
||||
|
||||
this.mTabsProgressListeners.forEach(function (p) {
|
||||
if (aMethod in p) {
|
||||
try {
|
||||
if (!p[aMethod].apply(p, aArguments))
|
||||
rv = false;
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return rv;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- A web progress listener object definition for a given tab. -->
|
||||
<method name="mTabProgressListener">
|
||||
<parameter name="aTab"/>
|
||||
@ -293,10 +340,14 @@
|
||||
delete this.mTabBrowser;
|
||||
},
|
||||
|
||||
onProgressChange : function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress)
|
||||
{
|
||||
_callProgressListeners: function () {
|
||||
Array.unshift(arguments, this.mBrowser);
|
||||
return this.mTabBrowser._callProgressListeners.apply(this.mTabBrowser, arguments);
|
||||
},
|
||||
|
||||
onProgressChange: function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
|
||||
|
||||
if (this.mBlank)
|
||||
@ -312,46 +363,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onProgressChange(aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onProgressChange(this.mBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners("onProgressChange",
|
||||
[aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress]);
|
||||
},
|
||||
|
||||
onProgressChange64 : function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress)
|
||||
{
|
||||
onProgressChange64: function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
return this.onProgressChange(aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress,
|
||||
aMaxTotalProgress);
|
||||
},
|
||||
|
||||
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
|
||||
{
|
||||
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (!aRequest)
|
||||
return;
|
||||
|
||||
@ -436,33 +462,19 @@
|
||||
this.mTabBrowser.mIsBusy = false;
|
||||
}
|
||||
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
if (!oldBlank)
|
||||
p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
|
||||
// make sure that the visible status of new blank tabs is correctly set
|
||||
else if ("onUpdateCurrentBrowser" in p)
|
||||
p.onUpdateCurrentBrowser(aStateFlags, aStatus, "", 0);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
if (oldBlank) {
|
||||
this._callProgressListeners("onUpdateCurrentBrowser",
|
||||
[aStateFlags, aStatus, "", 0],
|
||||
true, false);
|
||||
} else {
|
||||
this._callProgressListeners("onStateChange",
|
||||
[aWebProgress, aRequest, aStateFlags, aStatus],
|
||||
true, false);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onStateChange(this.mBrowser, aWebProgress, aRequest, aStateFlags, aStatus);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners("onStateChange",
|
||||
[aWebProgress, aRequest, aStateFlags, aStatus],
|
||||
false);
|
||||
|
||||
if (aStateFlags & (nsIWebProgressListener.STATE_START |
|
||||
nsIWebProgressListener.STATE_STOP)) {
|
||||
@ -474,8 +486,7 @@
|
||||
this.mStatus = aStatus;
|
||||
},
|
||||
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation)
|
||||
{
|
||||
onLocationChange: function (aWebProgress, aRequest, aLocation) {
|
||||
// The document loaded correctly, clear the value if we should
|
||||
if (this.mBrowser.userTypedClear > 0)
|
||||
this.mBrowser.userTypedValue = null;
|
||||
@ -497,129 +508,35 @@
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
|
||||
if (!this.mBlank) {
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onLocationChange(aWebProgress, aRequest, aLocation);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onLocationChange(this.mBrowser, aWebProgress, aRequest, aLocation);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners("onLocationChange",
|
||||
[aWebProgress, aRequest, aLocation]);
|
||||
}
|
||||
|
||||
this.mBrowser.lastURI = aLocation;
|
||||
|
||||
},
|
||||
|
||||
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
|
||||
{
|
||||
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
|
||||
if (this.mBlank)
|
||||
return;
|
||||
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onStatusChange(aWebProgress, aRequest, aStatus, aMessage);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onStatusChange(this.mBrowser, aWebProgress, aRequest, aStatus, aMessage);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners("onStatusChange",
|
||||
[aWebProgress, aRequest, aStatus, aMessage]);
|
||||
|
||||
this.mMessage = aMessage;
|
||||
},
|
||||
|
||||
onSecurityChange : function(aWebProgress, aRequest, aState)
|
||||
{
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onSecurityChange(aWebProgress, aRequest, aState);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onSecurityChange(this.mBrowser, aWebProgress, aRequest, aState);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
onSecurityChange: function (aWebProgress, aRequest, aState) {
|
||||
this._callProgressListeners("onSecurityChange",
|
||||
[aWebProgress, aRequest, aState]);
|
||||
},
|
||||
|
||||
onRefreshAttempted : function(aWebProgress, aURI, aDelay, aSameURI)
|
||||
{
|
||||
var allowRefresh = true;
|
||||
if (this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mProgressListeners[i];
|
||||
if (p && "onRefreshAttempted" in p) {
|
||||
try {
|
||||
if (!p.onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI))
|
||||
allowRefresh = false;
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabBrowser.mTabsProgressListeners[i];
|
||||
if (p && "onRefreshAttempted" in p) {
|
||||
try {
|
||||
if (!p.onRefreshAttempted(this.mBrowser, aWebProgress, aURI, aDelay, aSameURI))
|
||||
allowRefresh = false;
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowRefresh;
|
||||
onRefreshAttempted: function (aWebProgress, aURI, aDelay, aSameURI) {
|
||||
return this._callProgressListeners("onRefreshAttempted",
|
||||
[aWebProgress, aURI, aDelay, aSameURI]);
|
||||
},
|
||||
|
||||
QueryInterface : function(aIID)
|
||||
{
|
||||
QueryInterface: function (aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsIWebProgressListener2) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
@ -663,29 +580,7 @@
|
||||
|
||||
this.updateIcon(aTab);
|
||||
|
||||
if (browser == this.mCurrentBrowser) {
|
||||
for (let i = 0; i < this.mProgressListeners.length; i++) {
|
||||
let p = this.mProgressListeners[i];
|
||||
if ('onLinkIconAvailable' in p)
|
||||
try {
|
||||
p.onLinkIconAvailable(browser, browser.mIconURL);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.mTabsProgressListeners.length; i++) {
|
||||
let p = this.mTabsProgressListeners[i];
|
||||
if ('onLinkIconAvailable' in p)
|
||||
try {
|
||||
p.onLinkIconAvailable(browser, browser.mIconURL);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -864,26 +759,20 @@
|
||||
var webProgress = this.mCurrentBrowser.webProgress;
|
||||
var securityUI = this.mCurrentBrowser.securityUI;
|
||||
|
||||
var i, p;
|
||||
for (i = 0; i < this.mProgressListeners.length; i++) {
|
||||
p = this.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onLocationChange(webProgress, null, loc);
|
||||
if (securityUI)
|
||||
p.onSecurityChange(webProgress, null, securityUI.state);
|
||||
this._callProgressListeners(null, "onLocationChange",
|
||||
[webProgress, null, loc], true, false);
|
||||
|
||||
// make sure that all status indicators are properly updated
|
||||
if ("onUpdateCurrentBrowser" in p) {
|
||||
let listener = this.mTabListeners[this.tabContainer.selectedIndex] || null;
|
||||
if (listener && listener.mStateFlags)
|
||||
p.onUpdateCurrentBrowser(listener.mStateFlags, listener.mStatus,
|
||||
listener.mMessage, listener.mTotalProgress);
|
||||
}
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners or following code
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
if (securityUI) {
|
||||
this._callProgressListeners(null, "onSecurityChange",
|
||||
[webProgress, null, securityUI.state], true, false);
|
||||
}
|
||||
|
||||
var listener = this.mTabListeners[this.tabContainer.selectedIndex] || null;
|
||||
if (listener && listener.mStateFlags) {
|
||||
this._callProgressListeners(null, "onUpdateCurrentBrowser",
|
||||
[listener.mStateFlags, listener.mStatus,
|
||||
listener.mMessage, listener.mTotalProgress],
|
||||
true, false);
|
||||
}
|
||||
|
||||
// Don't switch the fast find or update the titlebar (bug 540248) - this tab switch is temporary
|
||||
@ -898,32 +787,22 @@
|
||||
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
|
||||
if (this.mCurrentTab.hasAttribute("busy") && !this.mIsBusy) {
|
||||
this.mIsBusy = true;
|
||||
for (i = 0; i < this.mProgressListeners.length; i++) {
|
||||
p = this.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onStateChange(webProgress, null, nsIWebProgressListener.STATE_START | nsIWebProgressListener.STATE_IS_NETWORK, 0);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners or following code
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners(null, "onStateChange",
|
||||
[webProgress, null,
|
||||
nsIWebProgressListener.STATE_START |
|
||||
nsIWebProgressListener.STATE_IS_NETWORK, 0],
|
||||
true, false);
|
||||
}
|
||||
|
||||
// If the new tab is not busy, and our current state is busy, then
|
||||
// we need to fire a stop to all progress listeners.
|
||||
if (!this.mCurrentTab.hasAttribute("busy") && this.mIsBusy) {
|
||||
this.mIsBusy = false;
|
||||
for (i = 0; i < this.mProgressListeners.length; i++) {
|
||||
p = this.mProgressListeners[i];
|
||||
if (p)
|
||||
try {
|
||||
p.onStateChange(webProgress, null, nsIWebProgressListener.STATE_STOP | nsIWebProgressListener.STATE_IS_NETWORK, 0);
|
||||
} catch (e) {
|
||||
// don't inhibit other listeners or following code
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
this._callProgressListeners(null, "onStateChange",
|
||||
[webProgress, null,
|
||||
nsIWebProgressListener.STATE_STOP |
|
||||
nsIWebProgressListener.STATE_IS_NETWORK, 0],
|
||||
true, false);
|
||||
}
|
||||
|
||||
// TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
|
||||
@ -1054,11 +933,7 @@
|
||||
}
|
||||
|
||||
// Remove all our progress listeners from the active browser's filter.
|
||||
for (var i = 0; i < this.mProgressListeners.length; i++) {
|
||||
var p = this.mProgressListeners[i];
|
||||
if (p)
|
||||
filter.removeProgressListener(p);
|
||||
}
|
||||
this.mProgressListeners.forEach(filter.removeProgressListener, filter);
|
||||
|
||||
// Wire up a progress listener to our filter.
|
||||
const listener = this.mTabProgressListener(this.mCurrentTab,
|
||||
@ -1210,9 +1085,6 @@
|
||||
t.setAttribute("label", aURI);
|
||||
|
||||
t.setAttribute("crop", "end");
|
||||
t.style.maxWidth = this.tabContainer.mTabMaxWidth + "px";
|
||||
t.style.minWidth = this.tabContainer.mTabMinWidth + "px";
|
||||
t.width = 0;
|
||||
t.setAttribute("validate", "never");
|
||||
t.setAttribute("onerror", "this.removeAttribute('image');");
|
||||
t.className = "tabbrowser-tab";
|
||||
@ -1766,12 +1638,8 @@
|
||||
<parameter name="aListener"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
for (var i = 0; i < this.mProgressListeners.length; i++) {
|
||||
if (this.mProgressListeners[i] == aListener) {
|
||||
this.mProgressListeners.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.mProgressListeners =
|
||||
this.mProgressListeners.filter(function (l) l != aListener);
|
||||
|
||||
if (!this.mTabbedMode)
|
||||
// Don't forget to remove it from the filter we hooked it up to
|
||||
@ -1792,9 +1660,8 @@
|
||||
<parameter name="aListener"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var pos = this.mTabsProgressListeners.indexOf(aListener);
|
||||
if (pos >= 0)
|
||||
this.mTabsProgressListeners.splice(pos, 1);
|
||||
this.mTabsProgressListeners =
|
||||
this.mTabsProgressListeners.filter(function (l) l != aListener);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -2505,8 +2372,6 @@
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this.mTabMinWidth = Services.prefs.getIntPref("browser.tabs.tabMinWidth");
|
||||
this.mTabMaxWidth = Services.prefs.getIntPref("browser.tabs.tabMaxWidth");
|
||||
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
|
||||
this.mCloseButtons = Services.prefs.getIntPref("browser.tabs.closeButtons");
|
||||
this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
|
||||
@ -2514,9 +2379,6 @@
|
||||
var tab = this.firstChild;
|
||||
tab.setAttribute("label",
|
||||
this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle"));
|
||||
tab.style.minWidth = this.mTabMinWidth + "px";
|
||||
tab.style.maxWidth = this.mTabMaxWidth + "px";
|
||||
tab.width = 0;
|
||||
tab.setAttribute("crop", "end");
|
||||
tab.setAttribute("validate", "never");
|
||||
tab.setAttribute("onerror", "this.removeAttribute('image');");
|
||||
|
@ -125,6 +125,7 @@ _BROWSER_FILES = \
|
||||
browser_bug491431.js \
|
||||
browser_bug495058.js \
|
||||
browser_bug517902.js \
|
||||
browser_bug519216.js \
|
||||
browser_bug520538.js \
|
||||
browser_bug521216.js \
|
||||
browser_bug537474.js \
|
||||
|
@ -38,11 +38,6 @@ var gFrontProgressListener = {
|
||||
}
|
||||
|
||||
var gAllProgressListener = {
|
||||
onProgressChange: function (aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
var state = "onStateChange";
|
||||
info("AllProgress: " + state + " 0x" + aStateFlags.toString(16));
|
||||
|
@ -57,12 +57,7 @@ var gProgressListener = {
|
||||
ok(gBrowser.tabs.length == kURIs.length, "Correctly opened all expected tabs");
|
||||
finishTest();
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function () {},
|
||||
onLocationChange: function () {},
|
||||
onStatusChange: function () {},
|
||||
onSecurityChange: function () {}
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
48
browser/base/content/test/browser_bug519216.js
Normal file
48
browser/base/content/test/browser_bug519216.js
Normal file
@ -0,0 +1,48 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
gBrowser.stop();
|
||||
gBrowser.addProgressListener(progressListener1);
|
||||
gBrowser.addProgressListener(progressListener2);
|
||||
gBrowser.addProgressListener(progressListener3);
|
||||
gBrowser.loadURI("data:text/plain,bug519216");
|
||||
}
|
||||
|
||||
var calledListener1 = false;
|
||||
var progressListener1 = {
|
||||
onLocationChange: function onLocationChange() {
|
||||
calledListener1 = true;
|
||||
gBrowser.removeProgressListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
var calledListener2 = false;
|
||||
var progressListener2 = {
|
||||
onLocationChange: function onLocationChange() {
|
||||
ok(calledListener1, "called progressListener1 before progressListener2");
|
||||
calledListener2 = true;
|
||||
gBrowser.removeProgressListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
var progressListener3 = {
|
||||
onLocationChange: function onLocationChange() {
|
||||
ok(calledListener2, "called progressListener2 before progressListener3");
|
||||
gBrowser.removeProgressListener(this);
|
||||
gBrowser.addProgressListener(progressListener4);
|
||||
executeSoon(function () {
|
||||
expectListener4 = true;
|
||||
gBrowser.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var expectListener4 = false;
|
||||
var progressListener4 = {
|
||||
onLocationChange: function onLocationChange() {
|
||||
ok(expectListener4, "didn't call progressListener4 for the first location change");
|
||||
gBrowser.removeProgressListener(this);
|
||||
gBrowser.addTab();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
};
|
@ -35,13 +35,10 @@ var progressListener = {
|
||||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function onStateChange(aBrowser) {
|
||||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
},
|
||||
onStatusChange: function () {},
|
||||
onLinkIconAvailable: function onLinkIconAvailable(aBrowser) {
|
||||
if (aBrowser == tab.linkedBrowser)
|
||||
record(arguments.callee.name);
|
||||
|
@ -25,7 +25,7 @@ function test() {
|
||||
function doTest() {
|
||||
tabstrip.smoothScroll = false;
|
||||
|
||||
var tabMinWidth = gPrefService.getIntPref("browser.tabs.tabMinWidth");
|
||||
var tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
|
||||
var tabCountForOverflow = Math.ceil(width(tabstrip) / tabMinWidth * 3);
|
||||
while (tabContainer.childNodes.length < tabCountForOverflow)
|
||||
gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
|
@ -55,7 +55,7 @@ var SubscribeHandler = {
|
||||
this._feedWriter.close();
|
||||
},
|
||||
|
||||
subscribe: function FH_subscribe() {
|
||||
subscribe: function SH_subscribe() {
|
||||
this._feedWriter.subscribe();
|
||||
}
|
||||
};
|
||||
|
@ -95,21 +95,6 @@ var gTabsListener = {
|
||||
// Test finished. This will move to the next one.
|
||||
waitForFocus(gCurrentTest.finish, gBrowser.ownerDocument.defaultView);
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
onStateChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aStateFlags, aStatus) {
|
||||
},
|
||||
onStatusChange: function(aBrowser, aWebProgress, aRequest,
|
||||
aStatus, aMessage) {
|
||||
},
|
||||
onSecurityChange: function(aBrowser, aWebProgress, aRequest, aState) {
|
||||
},
|
||||
noLinkIconAvailable: function(aBrowser) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,6 @@
|
||||
label="&button.close.label;" accesskey="&button.close.accesskey;"/>
|
||||
#endif
|
||||
</hbox>
|
||||
<resizer dir="bottomend"/>
|
||||
<resizer type="window" dir="bottomend"/>
|
||||
</hbox>
|
||||
</window>
|
||||
|
@ -111,6 +111,6 @@
|
||||
label="&button.close.label;" accesskey="&button.close.accesskey;"/>
|
||||
#endif
|
||||
</hbox>
|
||||
<resizer dir="bottomend"/>
|
||||
<resizer type="window" dir="bottomend"/>
|
||||
</hbox>
|
||||
</window>
|
||||
|
@ -571,6 +571,17 @@ PrivateBrowsingService.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// Image Cache
|
||||
let (imageCache = Cc["@mozilla.org/image/cache;1"].
|
||||
getService(Ci.imgICache)) {
|
||||
try {
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
} catch (ex) {
|
||||
Cu.reportError("Exception thrown while clearing the image cache: " +
|
||||
ex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Cookies
|
||||
let (cm = Cc["@mozilla.org/cookiemanager;1"].
|
||||
getService(Ci.nsICookieManager2)) {
|
||||
|
@ -92,11 +92,6 @@ function test() {
|
||||
Services.ww.registerNotification(observer);
|
||||
|
||||
gBrowser.addTabsProgressListener({
|
||||
onLocationChange: function() {},
|
||||
onProgressChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onRefreshAttempted: function() {},
|
||||
onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
|
||||
Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {
|
||||
|
@ -83,8 +83,7 @@ function test() {
|
||||
let numTests = 4;
|
||||
let completedTests = 0;
|
||||
|
||||
// access the pref service just once
|
||||
let tabMinWidth = gPrefService.getIntPref("browser.tabs.tabMinWidth");
|
||||
let tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
|
||||
|
||||
function runTest(testNum, totalTabs, selectedTab, shownTabs, order) {
|
||||
let test = {
|
||||
|
@ -62,11 +62,7 @@ function test() {
|
||||
gBrowser.removeTabsProgressListener(this);
|
||||
executeSoon(aSetStateCallback);
|
||||
}
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function () {},
|
||||
onStatusChange: function () {}
|
||||
}
|
||||
});
|
||||
ss.setBrowserState(JSON.stringify(aState));
|
||||
}
|
||||
@ -211,11 +207,7 @@ function test() {
|
||||
gBrowser.removeTabsProgressListener(this);
|
||||
firstLocationChange();
|
||||
}
|
||||
},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStateChange: function () {},
|
||||
onStatusChange: function () {}
|
||||
}
|
||||
});
|
||||
|
||||
function firstLocationChange() {
|
||||
|
@ -530,16 +530,6 @@ TabWindow.prototype = {
|
||||
},
|
||||
|
||||
//// Browser progress listener
|
||||
onLocationChange: function () {
|
||||
},
|
||||
onProgressChange: function () {
|
||||
},
|
||||
onSecurityChange: function () {
|
||||
},
|
||||
onStateChange: function () {
|
||||
},
|
||||
onStatusChange: function () {
|
||||
},
|
||||
onLinkIconAvailable: function (aBrowser, aIconURL) {
|
||||
let self = this;
|
||||
getFaviconAsImage(aIconURL, function (img) {
|
||||
|
@ -22,6 +22,10 @@
|
||||
<!ENTITY closeOtherTabs.accesskey "o">
|
||||
<!ENTITY openTabInNewWindow.label "Open in a New Window">
|
||||
<!ENTITY openTabInNewWindow.accesskey "W">
|
||||
<!ENTITY pinTab.label "Make into App Tab">
|
||||
<!ENTITY pinTab.accesskey "p">
|
||||
<!ENTITY unpinTab.label "Make into Normal Tab">
|
||||
<!ENTITY unpinTab.accesskey "k">
|
||||
<!ENTITY bookmarkThisTab.label "Bookmark This Tab">
|
||||
<!ENTITY bookmarkThisTab.accesskey "B">
|
||||
<!ENTITY bookmarkAllTabs.label "Bookmark All Tabs…">
|
||||
|
@ -52,7 +52,7 @@ addonInstallManage.accesskey=O
|
||||
addonError-1=The add-on could not be downloaded because of a connection failure on #2.
|
||||
addonError-2=The add-on from #2 could not be installed because it does not match the add-on #3 expected.
|
||||
addonError-3=The add-on downloaded from #2 could not be installed because it appears to be corrupt.
|
||||
addonError-4=#1 could not be installed because Firefox cannot modify the needed file.
|
||||
addonError-4=#1 could not be installed because #3 cannot modify the needed file.
|
||||
addonErrorIncompatible=#1 could not be installed because it is not compatible with #3 #4.
|
||||
addonErrorBlocklisted=#1 could not be installed because it has a high risk of causing stability or security problems.
|
||||
|
||||
|
@ -51,7 +51,6 @@ browser/components/migration/Makefile
|
||||
browser/components/migration/public/Makefile
|
||||
browser/components/migration/src/Makefile
|
||||
browser/components/places/Makefile
|
||||
browser/components/places/public/Makefile
|
||||
browser/components/places/src/Makefile
|
||||
browser/components/preferences/Makefile
|
||||
browser/components/privatebrowsing/Makefile
|
||||
|
@ -181,7 +181,7 @@ statusbarpanel#statusbar-display {
|
||||
position: relative !important;
|
||||
background-color: -moz-dialog !important;
|
||||
}
|
||||
#navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] ~ #TabsToolbar {
|
||||
#navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] ~ #TabsToolbar:not([inFullscreen]) {
|
||||
-moz-padding-start: 10em !important;
|
||||
}
|
||||
%ifdef WINSTRIPE_AERO
|
||||
|
@ -40,12 +40,28 @@
|
||||
@import "chrome://global/skin/";
|
||||
|
||||
/* View buttons */
|
||||
#viewGroup {
|
||||
-moz-padding-start: 10px;
|
||||
}
|
||||
|
||||
#viewGroup > radio {
|
||||
list-style-image: url("chrome://browser/skin/pageInfo.png");
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
-moz-appearance: none;
|
||||
padding: 5px 3px 1px 3px;
|
||||
margin: 0 1px;
|
||||
min-width: 4.5em;
|
||||
}
|
||||
|
||||
#viewGroup > radio:hover {
|
||||
background-color: #E0E8F6;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#viewGroup > radio[selected="true"] {
|
||||
background-color: #C1D2EE;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#topBar {
|
||||
|
@ -1,2 +1,2 @@
|
||||
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
|
||||
node: 3476582628db128ad061c30cab1a74a0c5d14b9b
|
||||
node: 7ae0b4af32617677698f9de3ab76bcb154bbf085
|
||||
|
@ -1402,7 +1402,7 @@ class Makefile(object):
|
||||
Inform the makefile of a target which is a candidate for being the default target,
|
||||
if there isn't already a default target.
|
||||
"""
|
||||
if self.defaulttarget is None:
|
||||
if self.defaulttarget is None and t != '.PHONY':
|
||||
self.defaulttarget = t
|
||||
|
||||
def getpatternvariables(self, pattern):
|
||||
|
@ -284,7 +284,7 @@ def ifeq(d, offset):
|
||||
if token == '(':
|
||||
arg1, t, offset = parsemakesyntax(d, offset, (',',), itermakefilechars)
|
||||
if t is None:
|
||||
raise SyntaxError("Expected two arguments in conditional", d.getloc(offset))
|
||||
raise SyntaxError("Expected two arguments in conditional", d.getloc(d.lend))
|
||||
|
||||
arg1.rstrip()
|
||||
|
||||
@ -604,6 +604,9 @@ class ParseStackFrame(object):
|
||||
self.function = function
|
||||
self.loc = loc
|
||||
|
||||
def __str__(self):
|
||||
return "<state=%i expansion=%s tokenlist=%s openbrace=%s closebrace=%s>" % (self.parsestate, self.expansion, self.tokenlist, self.openbrace, self.closebrace)
|
||||
|
||||
_matchingbrace = {
|
||||
'(': ')',
|
||||
'{': '}',
|
||||
@ -689,7 +692,7 @@ def parsemakesyntax(d, offset, stopon, iterfunc):
|
||||
stacktop.expansion.appendstr(token)
|
||||
stacktop = ParseStackFrame(_PARSESTATE_PARENMATCH, stacktop,
|
||||
stacktop.expansion,
|
||||
(token, stacktop.closebrace),
|
||||
(token, stacktop.closebrace, '$'),
|
||||
openbrace=token, closebrace=stacktop.closebrace, loc=d.getloc(tokenoffset))
|
||||
elif parsestate == _PARSESTATE_PARENMATCH:
|
||||
assert token == stacktop.closebrace
|
||||
|
@ -3,6 +3,8 @@ test: VAR = value
|
||||
%.do:
|
||||
@echo TEST-FAIL: ran target "$@", should have run "all"
|
||||
|
||||
.PHONY: test
|
||||
|
||||
all:
|
||||
@echo TEST-PASS: the default target is all
|
||||
|
||||
|
6
build/pymake/tests/if-syntaxerr.mk
Normal file
6
build/pymake/tests/if-syntaxerr.mk
Normal file
@ -0,0 +1,6 @@
|
||||
#T returncode: 2
|
||||
|
||||
ifeq ($(FOO,VAR))
|
||||
all:
|
||||
@echo TEST_FAIL
|
||||
endif
|
@ -1,5 +1,5 @@
|
||||
$(shell \
|
||||
if test ! -f include-dynamic.inc; then \
|
||||
if ! test -f include-dynamic.inc; then \
|
||||
echo "TESTVAR = oldval" > include-dynamic.inc; \
|
||||
sleep 2; \
|
||||
echo "TESTVAR = newval" > include-dynamic.inc.in; \
|
||||
|
9
build/pymake/tests/path-length.mk
Normal file
9
build/pymake/tests/path-length.mk
Normal file
File diff suppressed because one or more lines are too long
@ -78,7 +78,7 @@ nsNullPrincipal::Release()
|
||||
nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
|
||||
NS_LOG_RELEASE(this, count, "nsNullPrincipal");
|
||||
if (count == 0) {
|
||||
NS_DELETEXPCOM(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -166,7 +166,7 @@ nsPrincipal::Release()
|
||||
nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
|
||||
NS_LOG_RELEASE(this, count, "nsPrincipal");
|
||||
if (count == 0) {
|
||||
NS_DELETEXPCOM(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -75,7 +75,7 @@ nsSystemPrincipal::Release()
|
||||
nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount);
|
||||
NS_LOG_RELEASE(this, count, "nsSystemPrincipal");
|
||||
if (count == 0) {
|
||||
NS_DELETEXPCOM(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -46,6 +46,7 @@ MODULE = chrome
|
||||
LIBRARY_NAME = chrome_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/chrome
|
||||
|
||||
|
@ -51,10 +51,12 @@ function do_run_test()
|
||||
let cr = Cc["@mozilla.org/chrome/chrome-registry;1"].
|
||||
getService(Ci.nsIChromeRegistry);
|
||||
|
||||
var runtime = Components.classes["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Components.interfaces.nsIXULRuntime);
|
||||
if (runtime.processType ==
|
||||
Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
|
||||
// If we don't have libxul or e10s then we don't have process separation, so
|
||||
// we don't need to worry about checking for new chrome.
|
||||
var appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
||||
if (!appInfo ||
|
||||
(appInfo.getService(Ci.nsIXULRuntime).processType ==
|
||||
Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT)) {
|
||||
cr.checkForNewChrome();
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#line 2 "nsStaticComponents.cpp.in"
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
@ -40,21 +41,16 @@
|
||||
|
||||
#define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsStaticComponents.h"
|
||||
|
||||
/**
|
||||
* Construct a unique NSGetModule entry point for a generic module.
|
||||
*/
|
||||
#define NSGETMODULE(_name) _name##_NSGetModule
|
||||
|
||||
/**
|
||||
* Declare an NSGetModule() routine for a generic module.
|
||||
*/
|
||||
#define MODULE(_name) \
|
||||
NSGETMODULE_ENTRY_POINT(_name) (nsIComponentManager*, nsIFile*, nsIModule**);
|
||||
NSMODULE_DECL(_name);
|
||||
|
||||
%MODULE_LIST%
|
||||
#line 57 "nsStaticComponents.cpp.in"
|
||||
@ -62,15 +58,16 @@ NSGETMODULE_ENTRY_POINT(_name) (nsIComponentManager*, nsIFile*, nsIModule**);
|
||||
#undef MODULE
|
||||
|
||||
|
||||
#define MODULE(_name) { #_name, NSGETMODULE(_name) },
|
||||
#define MODULE(_name) \
|
||||
NSMODULE_NAME(_name),
|
||||
|
||||
/**
|
||||
* The nsStaticModuleInfo
|
||||
*/
|
||||
static nsStaticModuleInfo const gStaticModuleInfo[] = {
|
||||
static const mozilla::Module *const kStaticModules[] = {
|
||||
%MODULE_LIST%
|
||||
#line 69 "nsStaticComponents.cpp.in"
|
||||
#line 70 "nsStaticComponents.cpp.in"
|
||||
NULL
|
||||
};
|
||||
|
||||
nsStaticModuleInfo const *const kPStaticModules = gStaticModuleInfo;
|
||||
PRUint32 const kStaticModuleCount = NS_ARRAY_LENGTH(gStaticModuleInfo);
|
||||
mozilla::Module const *const *const kPStaticModules = kStaticModules;
|
||||
|
@ -47,7 +47,7 @@
|
||||
$found = 1;
|
||||
|
||||
# GLOBALS
|
||||
$SEP = 0; # the paltform independent path separator
|
||||
$SEP = 0; # the platform independent path separator
|
||||
$CFG = 0; # the value of the -cfg flag
|
||||
|
||||
# determine the path separator
|
||||
|
@ -168,6 +168,7 @@ xpcshell-tests:
|
||||
-I$(topsrcdir)/build \
|
||||
$(testxpcsrcdir)/runxpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
$(DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
|
||||
|
||||
@ -193,6 +194,8 @@ check-one:
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--test-path=$(SOLO_FILE) \
|
||||
--profile-name=$(MOZ_APP_NAME) \
|
||||
--verbose \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
$(DIST)/bin/xpcshell \
|
||||
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
|
||||
|
||||
@ -2291,3 +2294,6 @@ CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
|
||||
|
||||
libs export libs::
|
||||
$(CHECK_FROZEN_VARIABLES)
|
||||
|
||||
default::
|
||||
if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi
|
||||
|
40
configure.in
40
configure.in
@ -1538,7 +1538,7 @@ x86_64 | ia64)
|
||||
CPU_ARCH="$OS_TEST"
|
||||
;;
|
||||
|
||||
arm)
|
||||
arm*)
|
||||
CPU_ARCH=arm
|
||||
;;
|
||||
esac
|
||||
@ -1567,8 +1567,8 @@ if test "$GNU_CC"; then
|
||||
ASFLAGS="$ASFLAGS -fPIC"
|
||||
_MOZ_RTTI_FLAGS_ON=${_COMPILER_PREFIX}-frtti
|
||||
_MOZ_RTTI_FLAGS_OFF=${_COMPILER_PREFIX}-fno-rtti
|
||||
_MOZ_EXCEPTIONS_FLAGS_ON='-fhandle-exceptions'
|
||||
_MOZ_EXCEPTIONS_FLAGS_OFF='-fno-handle-exceptions'
|
||||
_MOZ_EXCEPTIONS_FLAGS_ON='-fexceptions'
|
||||
_MOZ_EXCEPTIONS_FLAGS_OFF='-fno-exceptions'
|
||||
|
||||
# Turn on GNU specific features
|
||||
# -Wall - turn on all warnings
|
||||
@ -2539,8 +2539,8 @@ ia64*-hpux*)
|
||||
USE_PTHREADS=1
|
||||
_PEDANTIC=
|
||||
LIBS="$LIBS -lsocket -lstdc++"
|
||||
_DEFINES_CFLAGS='-Wp,-include -Wp,$(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT -D_POSIX_C_SOURCE=199506'
|
||||
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -Wp,-include -Wp,$(DEPTH)/mozilla-config.h -D_POSIX_C_SOURCE=199506'
|
||||
_DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT -D_POSIX_C_SOURCE=199506'
|
||||
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h -D_POSIX_C_SOURCE=199506'
|
||||
if test "$with_x" != "yes"
|
||||
then
|
||||
_PLATFORM_DEFAULT_TOOLKIT="photon"
|
||||
@ -4024,32 +4024,6 @@ EOF
|
||||
esac
|
||||
|
||||
dnl ===================================================================
|
||||
dnl ========================================================
|
||||
dnl By default, turn rtti and exceptions off on g++/egcs
|
||||
dnl ========================================================
|
||||
if test "$GNU_CXX"; then
|
||||
|
||||
AC_MSG_CHECKING(for C++ exceptions flag)
|
||||
|
||||
dnl They changed -f[no-]handle-exceptions to -f[no-]exceptions in g++ 2.8
|
||||
AC_CACHE_VAL(ac_cv_cxx_exceptions_flags,
|
||||
[echo "int main() { return 0; }" | cat > conftest.C
|
||||
|
||||
${CXX-g++} ${CXXFLAGS} -c -fno-handle-exceptions conftest.C > conftest.out 2>&1
|
||||
|
||||
if egrep "warning.*renamed" conftest.out >/dev/null; then
|
||||
ac_cv_cxx_exceptions_flags=${_COMPILER_PREFIX}-fno-exceptions
|
||||
else
|
||||
ac_cv_cxx_exceptions_flags=${_COMPILER_PREFIX}-fno-handle-exceptions
|
||||
fi
|
||||
|
||||
rm -f conftest*])
|
||||
|
||||
AC_MSG_RESULT($ac_cv_cxx_exceptions_flags)
|
||||
_MOZ_EXCEPTIONS_FLAGS_OFF=$ac_cv_cxx_exceptions_flags
|
||||
_MOZ_EXCEPTIONS_FLAGS_ON=`echo $ac_cv_cxx_exceptions_flags | sed 's|no-||'`
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Put your C++ language/feature checks below
|
||||
dnl ========================================================
|
||||
@ -6005,7 +5979,7 @@ if test -n "$MOZ_SYDNEYAUDIO"; then
|
||||
linux*)
|
||||
PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
|
||||
[echo "$MOZ_ALSA_PKG_ERRORS"
|
||||
AC_MSG_ERROR([Need alsa for Ogg or Wave decoding on Linux. Disable with --disable-ogg --disable-wave. (On Ubuntu, you might try installing the package libasound2-dev.)])])
|
||||
AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux. Disable with --disable-ogg --disable-wave --disable-webm. (On Ubuntu, you might try installing the package libasound2-dev.)])])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
@ -7977,7 +7951,7 @@ if test "$_cpp_md_flag"; then
|
||||
if test "$OS_ARCH" = "OpenVMS"; then
|
||||
_DEPEND_CFLAGS='$(subst =, ,$(filter-out %/.pp,-MM=-MD=-MF=$(MDDEPDIR)/$(basename $(@F)).pp))'
|
||||
else
|
||||
_DEPEND_CFLAGS='$(filter-out %/.pp,-Wp,-MD,$(MDDEPDIR)/$(basename $(@F)).pp)'
|
||||
_DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(basename $(@F)).pp)'
|
||||
fi
|
||||
dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
|
||||
if test "$SOLARIS_SUNPRO_CC"; then
|
||||
|
@ -130,6 +130,7 @@ class nsIMIMEHeaderParam;
|
||||
class nsIObserver;
|
||||
class nsPresContext;
|
||||
class nsIChannel;
|
||||
struct nsIntMargin;
|
||||
|
||||
#ifndef have_PrefChangedFunc_typedef
|
||||
typedef int (*PR_CALLBACK PrefChangedFunc)(const char *, void *);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define nsCopySupport_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsINode.h"
|
||||
|
||||
class nsISelection;
|
||||
class nsIDocument;
|
||||
@ -47,7 +48,6 @@ class nsIContent;
|
||||
class nsITransferable;
|
||||
class nsACString;
|
||||
class nsAString;
|
||||
class nsIDOMNode;
|
||||
class nsIPresShell;
|
||||
|
||||
class nsCopySupport
|
||||
@ -69,10 +69,14 @@ class nsCopySupport
|
||||
|
||||
// Get the selection as a transferable. Similar to HTMLCopy except does
|
||||
// not deal with the clipboard.
|
||||
static nsresult GetTransferableForSelection(nsISelection * aSelection,
|
||||
nsIDocument * aDocument,
|
||||
nsITransferable ** aTransferable);
|
||||
static nsresult GetTransferableForSelection(nsISelection* aSelection,
|
||||
nsIDocument* aDocument,
|
||||
nsITransferable** aTransferable);
|
||||
|
||||
// Same as GetTransferableForSelection, but doesn't skip invisible content.
|
||||
static nsresult GetTransferableForNode(nsINode* aNode,
|
||||
nsIDocument* aDoc,
|
||||
nsITransferable** aTransferable);
|
||||
/**
|
||||
* Retrieve the selection for the given document. If the current focus
|
||||
* within the document has its own selection, aSelection will be set to it
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "nsChannelProperties.h"
|
||||
|
||||
/* Keeps track of whether or not CSP is enabled */
|
||||
static PRBool gCSPEnabled = PR_TRUE;
|
||||
PRBool CSPService::sCSPEnabled = PR_TRUE;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gCspPRLog;
|
||||
@ -63,7 +63,7 @@ static PRLogModuleInfo* gCspPRLog;
|
||||
|
||||
CSPService::CSPService()
|
||||
{
|
||||
nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
|
||||
nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &sCSPEnabled);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gCspPRLog)
|
||||
@ -102,7 +102,7 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
|
||||
// No need to continue processing if CSP is disabled
|
||||
if (!gCSPEnabled)
|
||||
if (!sCSPEnabled)
|
||||
return NS_OK;
|
||||
|
||||
// find the principal of the document that initiated this request and see
|
||||
@ -160,7 +160,7 @@ CSPService::ShouldProcess(PRUint32 aContentType,
|
||||
*aDecision = nsIContentPolicy::ACCEPT;
|
||||
|
||||
// No need to continue processing if CSP is disabled
|
||||
if (!gCSPEnabled)
|
||||
if (!sCSPEnabled)
|
||||
return NS_OK;
|
||||
|
||||
// find the nsDocument that initiated this request and see if it has a
|
||||
|
@ -52,7 +52,8 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPOLICY
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
|
||||
CSPService();
|
||||
virtual ~CSPService();
|
||||
static PRBool sCSPEnabled;
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "nsChannelPolicy.h"
|
||||
|
||||
nsChannelPolicy::nsChannelPolicy()
|
||||
: mLoadType(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,6 @@
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -92,9 +91,7 @@
|
||||
#define kHTMLContext "text/_moz_htmlcontext"
|
||||
#define kHTMLInfo "text/_moz_htmlinfo"
|
||||
|
||||
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
|
||||
|
||||
// if inNode is null, use the selection from the window
|
||||
// if aNode is null, use the selection from the window
|
||||
static nsresult
|
||||
GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow,
|
||||
nsIContent* aNode,
|
||||
@ -108,25 +105,15 @@ GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow,
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
|
||||
if (node) {
|
||||
// Make a temporary selection with this node in a single range.
|
||||
rv = NS_NewDomSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
rv = NS_NewRange(getter_AddRefs(range));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = range->SelectNode(node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = selection->AddRange(range);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aNode) {
|
||||
rv = nsCopySupport::GetTransferableForNode(aNode, doc, aTransferable);
|
||||
} else {
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
aWindow->GetSelection(getter_AddRefs(selection));
|
||||
rv = nsCopySupport::GetTransferableForSelection(selection, doc,
|
||||
aTransferable);
|
||||
}
|
||||
|
||||
rv = nsCopySupport::GetTransferableForSelection(selection, doc,
|
||||
aTransferable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return rv;
|
||||
}
|
||||
@ -424,7 +411,6 @@ DragDataProducer::GetNodeString(nsIContent* inNode,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
PRBool* aCanDrag,
|
||||
|
@ -2415,7 +2415,8 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
|
||||
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
|
||||
NS_PRECONDITION(aRequest, "Null out param");
|
||||
|
||||
if (!sImgLoader) {
|
||||
imgILoader* imgLoader = GetImgLoader();
|
||||
if (!imgLoader) {
|
||||
// nothing we can do here
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2444,17 +2445,17 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
|
||||
|
||||
// XXXbz using "documentURI" for the initialDocumentURI is not quite
|
||||
// right, but the best we can do here...
|
||||
return sImgLoader->LoadImage(aURI, /* uri to load */
|
||||
documentURI, /* initialDocumentURI */
|
||||
aReferrer, /* referrer */
|
||||
loadGroup, /* loadgroup */
|
||||
aObserver, /* imgIDecoderObserver */
|
||||
aLoadingDocument, /* uniquification key */
|
||||
aLoadFlags, /* load flags */
|
||||
nsnull, /* cache key */
|
||||
nsnull, /* existing request*/
|
||||
channelPolicy, /* CSP info */
|
||||
aRequest);
|
||||
return imgLoader->LoadImage(aURI, /* uri to load */
|
||||
documentURI, /* initialDocumentURI */
|
||||
aReferrer, /* referrer */
|
||||
loadGroup, /* loadgroup */
|
||||
aObserver, /* imgIDecoderObserver */
|
||||
aLoadingDocument, /* uniquification key */
|
||||
aLoadFlags, /* load flags */
|
||||
nsnull, /* cache key */
|
||||
nsnull, /* existing request*/
|
||||
channelPolicy, /* CSP info */
|
||||
aRequest);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsRange.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsFocusManager.h"
|
||||
@ -78,6 +79,8 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsContentCID.h"
|
||||
|
||||
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
|
||||
|
||||
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
|
||||
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
|
||||
@ -100,7 +103,7 @@ static nsresult AppendDOMNode(nsITransferable *aTransferable,
|
||||
static nsresult
|
||||
SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
PRBool doPutOnClipboard, PRInt16 aClipboardID,
|
||||
nsITransferable ** aTransferable)
|
||||
PRUint32 aFlags, nsITransferable ** aTransferable)
|
||||
{
|
||||
// Clear the output parameter for the transferable, if provided.
|
||||
if (aTransferable) {
|
||||
@ -135,9 +138,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
// we want preformatted for the case where the selection is inside input/textarea
|
||||
// and we don't want pretty printing for others cases, to not have additionnal
|
||||
// line breaks which are then converted into spaces by the htmlConverter (see bug #524975)
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted
|
||||
| nsIDocumentEncoder::OutputRaw
|
||||
| nsIDocumentEncoder::SkipInvisibleContent;
|
||||
PRUint32 flags = aFlags | nsIDocumentEncoder::OutputPreformatted
|
||||
| nsIDocumentEncoder::OutputRaw;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
|
||||
NS_ASSERTION(domDoc, "Need a document");
|
||||
@ -178,7 +180,7 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
|
||||
mimeType.AssignLiteral(kHTMLMime);
|
||||
|
||||
flags = nsIDocumentEncoder::SkipInvisibleContent;
|
||||
flags = aFlags;
|
||||
|
||||
rv = docEncoder->Init(domDoc, mimeType, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -279,17 +281,47 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID)
|
||||
nsresult
|
||||
nsCopySupport::HTMLCopy(nsISelection* aSel, nsIDocument* aDoc,
|
||||
PRInt16 aClipboardID)
|
||||
{
|
||||
return SelectionCopyHelper(aSel, aDoc, PR_TRUE, aClipboardID, nsnull);
|
||||
return SelectionCopyHelper(aSel, aDoc, PR_TRUE, aClipboardID,
|
||||
nsIDocumentEncoder::SkipInvisibleContent,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCopySupport::GetTransferableForSelection(nsISelection * aSel,
|
||||
nsIDocument * aDoc,
|
||||
nsITransferable ** aTransferable)
|
||||
nsCopySupport::GetTransferableForSelection(nsISelection* aSel,
|
||||
nsIDocument* aDoc,
|
||||
nsITransferable** aTransferable)
|
||||
{
|
||||
return SelectionCopyHelper(aSel, aDoc, PR_FALSE, 0, aTransferable);
|
||||
return SelectionCopyHelper(aSel, aDoc, PR_FALSE, 0,
|
||||
nsIDocumentEncoder::SkipInvisibleContent,
|
||||
aTransferable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCopySupport::GetTransferableForNode(nsINode* aNode,
|
||||
nsIDocument* aDoc,
|
||||
nsITransferable** aTransferable)
|
||||
{
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
// Make a temporary selection with aNode in a single range.
|
||||
nsresult rv = NS_NewDomSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
rv = NS_NewRange(getter_AddRefs(range));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
|
||||
rv = range->SelectNode(node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = selection->AddRange(range);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// It's not the primary selection - so don't skip invisible content.
|
||||
PRUint32 flags = 0;
|
||||
return SelectionCopyHelper(selection, aDoc, PR_FALSE, 0, flags,
|
||||
aTransferable);
|
||||
}
|
||||
|
||||
nsresult nsCopySupport::DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
|
||||
|
@ -195,6 +195,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
|
||||
// FOR CSP (autogenerated by xpidl)
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsCSPService.h"
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
#include "nsHTMLCSSStyleSheet.h"
|
||||
|
||||
@ -202,9 +203,6 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
||||
/* Keeps track of whether or not CSP is enabled */
|
||||
static PRBool gCSPEnabled = PR_TRUE;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gDocumentLeakPRLog;
|
||||
static PRLogModuleInfo* gCspPRLog;
|
||||
@ -1409,8 +1407,6 @@ nsDocument::nsDocument(const char* aContentType)
|
||||
gCspPRLog = PR_NewLogModule("CSP");
|
||||
#endif
|
||||
|
||||
nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
|
||||
|
||||
// Start out mLastStyleSheetSet as null, per spec
|
||||
SetDOMStringToNull(mLastStyleSheetSet);
|
||||
}
|
||||
@ -2175,7 +2171,7 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||
nsresult
|
||||
nsDocument::InitCSP()
|
||||
{
|
||||
if (gCSPEnabled) {
|
||||
if (CSPService::sCSPEnabled) {
|
||||
nsAutoString cspHeaderValue;
|
||||
nsAutoString cspROHeaderValue;
|
||||
|
||||
|
@ -61,7 +61,7 @@ bool SendSyncMessageToParent(void* aCallbackData,
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
|
||||
asyncMessages.SwapElements(tabChild->mASyncMessages);
|
||||
PRUint32 len = asyncMessages.Length();
|
||||
for (PRInt32 i = 0; i < len; ++i) {
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIRunnable> async = asyncMessages[i];
|
||||
async->Run();
|
||||
}
|
||||
@ -286,8 +286,9 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
|
||||
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
|
||||
NS_GET_IID(nsISupports), flags,
|
||||
getter_AddRefs(mGlobal));
|
||||
NS_GET_IID(nsISupports),
|
||||
GetPrincipal(), EmptyCString(),
|
||||
flags, getter_AddRefs(mGlobal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
JSObject* global = nsnull;
|
||||
|
@ -1360,8 +1360,7 @@ nsXMLHttpRequest::GetAllResponseHeaders(char **_retval)
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
|
||||
|
||||
if (httpChannel) {
|
||||
nsHeaderVisitor *visitor = nsnull;
|
||||
NS_NEWXPCOM(visitor, nsHeaderVisitor);
|
||||
nsHeaderVisitor *visitor = new nsHeaderVisitor();
|
||||
if (!visitor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(visitor);
|
||||
|
@ -402,6 +402,7 @@ _TEST_FILES2 = \
|
||||
test_websocket.html \
|
||||
file_websocket_wsh.py \
|
||||
file_websocket_http_resource.txt \
|
||||
test_bug574596.html \
|
||||
$(NULL)
|
||||
|
||||
# This test fails on the Mac for some reason
|
||||
|
86
content/base/test/test_bug574596.html
Normal file
86
content/base/test/test_bug574596.html
Normal file
@ -0,0 +1,86 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=574596
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 574596</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=574596">Mozilla Bug 574596</a>
|
||||
<style type="text/css">
|
||||
#link1 a { -moz-user-select:none; }
|
||||
</style>
|
||||
<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>
|
||||
<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 574596 **/
|
||||
|
||||
function ignoreFunc(actualData, expectedData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var dragLinkText = [[
|
||||
{ type:"text/x-moz-url", data:"", eqTest:ignoreFunc },
|
||||
{ type:"text/x-moz-url-data", data:"http://www.mozilla.org/" },
|
||||
{ type:"text/x-moz-url-desc", data:"link1" },
|
||||
{ type:"text/uri-list", data:"http://www.mozilla.org/" },
|
||||
{ type:"text/_moz_htmlcontext", data:"", eqTest:ignoreFunc },
|
||||
{ type:"text/_moz_htmlinfo", data:"", eqTest:ignoreFunc },
|
||||
{ type:"text/html", data:'<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>' },
|
||||
{ type:"text/plain", data:"http://www.mozilla.org/" }
|
||||
]];
|
||||
|
||||
|
||||
function dumpTransfer(dataTransfer,expect) {
|
||||
dtData = dataTransfer.mozItemCount + "items:\n";
|
||||
for (var i = 0; i < dataTransfer.mozItemCount; i++) {
|
||||
var dtTypes = dataTransfer.mozTypesAt(i);
|
||||
for (var j = 0; j < dtTypes.length; j++) {
|
||||
var actualData = dataTransfer.mozGetDataAt(dtTypes[j],i)
|
||||
if (expect && expect[i] && expect[i][j]) {
|
||||
if (expect[i][j].eqTest)
|
||||
dtData += expect[i][j].eqTest(actualData,expect[i][j].data) ? "ok" : "fail";
|
||||
else
|
||||
dtData += (actualData == expect[i][j].data) ? "ok" : "fail";
|
||||
}
|
||||
dtData += "["+i+"]" + "["+j+"]: " + '"' + dtTypes[j] + '" "' + actualData + '"\n';
|
||||
}
|
||||
}
|
||||
alert(dtData);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var result = synthesizeDragStart($('link1'), dragLinkText, window);
|
||||
is(result, null, "Drag -moz-user-select:none link (#link1)");
|
||||
// if (result) dumpTransfer(result,dragLinkText);
|
||||
|
||||
dragLinkText[0][2].data = "link2";
|
||||
dragLinkText[0][6].data = '<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>'
|
||||
var result = synthesizeDragStart($('link2'), dragLinkText, window);
|
||||
is(result, null, "Drag link (#link2)");
|
||||
// if (result) dumpTransfer(result,dragLinkText);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTest);
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -262,7 +262,7 @@ try {
|
||||
} catch(ex) {
|
||||
didThrow = true;
|
||||
}
|
||||
// Once this test passes, we shoud test that onerror gets called and
|
||||
// Once this test passes, we should test that onerror gets called and
|
||||
// that the FileReader object is in the right state during that call.
|
||||
todo(!didThrow, "shouldn't throw when opening nonexistent file, should fire error instead");
|
||||
|
||||
|
@ -63,7 +63,21 @@ function shouldNotOpen(e)
|
||||
function shouldNotReceiveCloseEvent(e)
|
||||
{
|
||||
var ws = e.target;
|
||||
ok(false, "onclose shouldn't be called on test " + ws._testNumber + "!");
|
||||
var extendedErrorInfo = "";
|
||||
if (!ws._testNumber) {
|
||||
extendedErrorInfo += "\nws members:\n";
|
||||
for (var i in ws) {
|
||||
extendedErrorInfo += (i + ": " + ws[i] + "\n");
|
||||
}
|
||||
|
||||
extendedErrorInfo += "\ne members:\n";
|
||||
for (var i in e) {
|
||||
extendedErrorInfo += (i + ": " + e[i] + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: see bug 578276. This should be a test failure, but it's too flaky on the tbox.
|
||||
ok(true, "onclose shouldn't be called on test " + ws._testNumber + "!" + extendedErrorInfo);
|
||||
}
|
||||
|
||||
function shouldCloseCleanly(e)
|
||||
@ -89,12 +103,15 @@ function CreateTestWS(ws_location, ws_protocol)
|
||||
ws = new WebSocket(ws_location, ws_protocol);
|
||||
}
|
||||
|
||||
|
||||
ws._testNumber = current_test;
|
||||
ws._receivedCloseEvent = false;
|
||||
ok(true, "added testNumber: " + ws._testNumber +"\n");
|
||||
|
||||
ws.onerror = function(e)
|
||||
{
|
||||
ok(false, "onerror called on test " + e.target._testNumber + "!");
|
||||
};
|
||||
ws._testNumber = current_test;
|
||||
ws._receivedCloseEvent = false;
|
||||
ws.addEventListener("close", function(e)
|
||||
{
|
||||
ws._receivedCloseEvent = true;
|
||||
@ -419,6 +436,7 @@ var status_test17 = "not started";
|
||||
window._test17 = function()
|
||||
{
|
||||
var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 17");
|
||||
local_ws._testNumber = "local17";
|
||||
current_test++;
|
||||
|
||||
status_test17 = "started";
|
||||
@ -491,6 +509,7 @@ function test19()
|
||||
window._test20 = function()
|
||||
{
|
||||
var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 20");
|
||||
local_ws._testNumber = "local20";
|
||||
current_test++;
|
||||
|
||||
local_ws.onerror = function()
|
||||
|
@ -138,8 +138,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
// If incrementing the generation would cause overflow,
|
||||
// don't allow it. Allowing this would allow us to use
|
||||
// resource handles created from older context generations.
|
||||
if (mGeneration + 1 == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!(mGeneration+1).valid())
|
||||
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
|
||||
|
||||
if (mWidth == width && mHeight == height)
|
||||
return NS_OK;
|
||||
@ -181,7 +181,7 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
mHeight = height;
|
||||
|
||||
// increment the generation number
|
||||
mGeneration++;
|
||||
++mGeneration;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
|
@ -60,6 +60,8 @@
|
||||
#include "GLContext.h"
|
||||
#include "Layers.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#define UNPACK_FLIP_Y_WEBGL 0x9240
|
||||
#define UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
|
||||
#define CONTEXT_LOST_WEBGL 0x9242
|
||||
@ -307,7 +309,7 @@ public:
|
||||
|
||||
// a number that increments every time we have an event that causes
|
||||
// all context resources to be lost.
|
||||
PRUint32 Generation() { return mGeneration; }
|
||||
PRUint32 Generation() { return mGeneration.value(); }
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
|
||||
nsHTMLCanvasElement *HTMLCanvasElement() {
|
||||
@ -317,7 +319,7 @@ protected:
|
||||
nsRefPtr<gl::GLContext> gl;
|
||||
|
||||
PRInt32 mWidth, mHeight;
|
||||
PRUint32 mGeneration;
|
||||
CheckedUint32 mGeneration;
|
||||
|
||||
PRBool mInvalidated;
|
||||
|
||||
@ -335,6 +337,7 @@ protected:
|
||||
PRBool ValidateComparisonEnum(WebGLenum target, const char *info);
|
||||
PRBool ValidateStencilOpEnum(WebGLenum action, const char *info);
|
||||
PRBool ValidateFaceEnum(WebGLenum target, const char *info);
|
||||
PRBool ValidateBufferUsageEnum(WebGLenum target, const char *info);
|
||||
PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
|
||||
PRUint32 *texelSize, const char *info);
|
||||
|
||||
@ -705,7 +708,7 @@ public:
|
||||
WebGLuint GLName() { return mName; }
|
||||
const nsTArray<WebGLShader*>& AttachedShaders() const { return mAttachedShaders; }
|
||||
PRBool LinkStatus() { return mLinkStatus; }
|
||||
GLuint Generation() const { return mGeneration; }
|
||||
PRUint32 Generation() const { return mGeneration.value(); }
|
||||
void SetLinkStatus(PRBool val) { mLinkStatus = val; }
|
||||
|
||||
PRBool ContainsShader(WebGLShader *shader) {
|
||||
@ -742,10 +745,9 @@ public:
|
||||
|
||||
PRBool NextGeneration()
|
||||
{
|
||||
GLuint nextGeneration = mGeneration + 1;
|
||||
if (nextGeneration == 0)
|
||||
if (!(mGeneration+1).valid())
|
||||
return PR_FALSE; // must exit without changing mGeneration
|
||||
mGeneration = nextGeneration;
|
||||
++mGeneration;
|
||||
mMapUniformLocations.Clear();
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -770,7 +772,7 @@ protected:
|
||||
PRPackedBool mLinkStatus;
|
||||
nsTArray<WebGLShader*> mAttachedShaders;
|
||||
nsRefPtrHashtable<nsUint32HashKey, WebGLUniformLocation> mMapUniformLocations;
|
||||
GLuint mGeneration;
|
||||
CheckedUint32 mGeneration;
|
||||
GLint mUniformMaxNameLength;
|
||||
GLint mAttribMaxNameLength;
|
||||
GLint mUniformCount;
|
||||
@ -864,7 +866,7 @@ public:
|
||||
|
||||
WebGLProgram *Program() const { return mProgram; }
|
||||
GLint Location() const { return mLocation; }
|
||||
GLuint ProgramGeneration() const { return mProgramGeneration; }
|
||||
PRUint32 ProgramGeneration() const { return mProgramGeneration; }
|
||||
|
||||
// needed for our generic helpers to check nsIxxx parameters, see GetConcreteObject.
|
||||
PRBool Deleted() { return PR_FALSE; }
|
||||
@ -873,7 +875,7 @@ public:
|
||||
NS_DECL_NSIWEBGLUNIFORMLOCATION
|
||||
protected:
|
||||
WebGLObjectRefPtr<WebGLProgram> mProgram;
|
||||
GLuint mProgramGeneration;
|
||||
PRUint32 mProgramGeneration;
|
||||
GLint mLocation;
|
||||
};
|
||||
|
||||
|
@ -125,21 +125,6 @@ WebGLContext::Present()
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* long sizeInBytes (in GLenum type); */
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::SizeInBytes(WebGLenum type, PRInt32 *retval)
|
||||
{
|
||||
if (type == LOCAL_GL_FLOAT) *retval = sizeof(float);
|
||||
if (type == LOCAL_GL_SHORT) *retval = sizeof(short);
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT) *retval = sizeof(unsigned short);
|
||||
if (type == LOCAL_GL_BYTE) *retval = 1;
|
||||
if (type == LOCAL_GL_UNSIGNED_BYTE) *retval = 1;
|
||||
if (type == LOCAL_GL_INT) *retval = sizeof(int);
|
||||
if (type == LOCAL_GL_UNSIGNED_INT) *retval = sizeof(unsigned int);
|
||||
if (type == LOCAL_GL_DOUBLE) *retval = sizeof(double);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void GlActiveTexture (in GLenum texture); */
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::ActiveTexture(WebGLenum texture)
|
||||
@ -292,7 +277,7 @@ WebGLContext::BindTexture(WebGLenum target, nsIWebGLTexture *tobj)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_4(BlendColor, BlendColor, float, float, float, float)
|
||||
GL_SAME_METHOD_4(BlendColor, BlendColor, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
|
||||
|
||||
NS_IMETHODIMP WebGLContext::BlendEquation(WebGLenum mode)
|
||||
{
|
||||
@ -362,6 +347,12 @@ WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage
|
||||
return ErrorInvalidEnum("BufferData: invalid target");
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
return ErrorInvalidValue("bufferData: negative size");
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return NS_OK;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
@ -388,6 +379,9 @@ WebGLContext::BufferData_buf(WebGLenum target, js::ArrayBuffer *wb, WebGLenum us
|
||||
return ErrorInvalidEnum("BufferData: invalid target");
|
||||
}
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return NS_OK;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
@ -414,6 +408,9 @@ WebGLContext::BufferData_array(WebGLenum target, js::TypedArray *wa, WebGLenum u
|
||||
return ErrorInvalidEnum("BufferData: invalid target");
|
||||
}
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return NS_OK;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
@ -449,8 +446,11 @@ WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, js::ArrayB
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
// XXX check for overflow
|
||||
if (byteOffset + wb->byteLength > boundBuffer->ByteLength())
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + wb->byteLength;
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
|
||||
byteOffset, wb->byteLength, boundBuffer->ByteLength());
|
||||
|
||||
@ -479,8 +479,11 @@ WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, js::T
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
// XXX check for overflow
|
||||
if (byteOffset + wa->byteLength > boundBuffer->ByteLength())
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + wa->byteLength;
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
|
||||
byteOffset, wa->byteLength, boundBuffer->ByteLength());
|
||||
|
||||
@ -512,15 +515,15 @@ WebGLContext::Clear(PRUint32 mask)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_4(ClearColor, ClearColor, float, float, float, float)
|
||||
GL_SAME_METHOD_4(ClearColor, ClearColor, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
|
||||
|
||||
#ifdef USE_GLES2
|
||||
GL_SAME_METHOD_1(ClearDepthf, ClearDepth, float)
|
||||
GL_SAME_METHOD_1(ClearDepthf, ClearDepth, WebGLfloat)
|
||||
#else
|
||||
GL_SAME_METHOD_1(ClearDepth, ClearDepth, float)
|
||||
GL_SAME_METHOD_1(ClearDepth, ClearDepth, WebGLfloat)
|
||||
#endif
|
||||
|
||||
GL_SAME_METHOD_1(ClearStencil, ClearStencil, PRInt32)
|
||||
GL_SAME_METHOD_1(ClearStencil, ClearStencil, WebGLint)
|
||||
|
||||
GL_SAME_METHOD_4(ColorMask, ColorMask, WebGLboolean, WebGLboolean, WebGLboolean, WebGLboolean)
|
||||
|
||||
@ -640,7 +643,16 @@ WebGLContext::CreateShader(WebGLenum type, nsIWebGLShader **retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_1(CullFace, CullFace, WebGLenum)
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::CullFace(WebGLenum face)
|
||||
{
|
||||
if (!ValidateFaceEnum(face, "cullFace"))
|
||||
return NS_OK;
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fCullFace(face);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::DeleteBuffer(nsIWebGLBuffer *bobj)
|
||||
@ -816,9 +828,9 @@ WebGLContext::DepthFunc(WebGLenum func)
|
||||
GL_SAME_METHOD_1(DepthMask, DepthMask, WebGLboolean)
|
||||
|
||||
#ifdef USE_GLES2
|
||||
GL_SAME_METHOD_2(DepthRangef, DepthRange, float, float)
|
||||
GL_SAME_METHOD_2(DepthRangef, DepthRange, WebGLfloat, WebGLfloat)
|
||||
#else
|
||||
GL_SAME_METHOD_2(DepthRange, DepthRange, float, float)
|
||||
GL_SAME_METHOD_2(DepthRange, DepthRange, WebGLfloat, WebGLfloat)
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -863,10 +875,12 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
if (!mCurrentProgram)
|
||||
return NS_OK;
|
||||
|
||||
if (first+count < first || first+count < count)
|
||||
return ErrorInvalidOperation("DrawArrays: overflow in first+count");
|
||||
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
|
||||
|
||||
if (!ValidateBuffers(first+count))
|
||||
if (!checked_firstPlusCount.valid())
|
||||
return ErrorInvalidOperation("drawArrays: overflow in first+count");
|
||||
|
||||
if (!ValidateBuffers(checked_firstPlusCount.value()))
|
||||
return ErrorInvalidOperation("DrawArrays: bound vertex attribute buffers do not have sufficient data for given first and count");
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -897,20 +911,21 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
if (count < 0 || byteOffset < 0)
|
||||
return ErrorInvalidValue("DrawElements: negative count or offset");
|
||||
|
||||
WebGLuint byteCount;
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT) {
|
||||
byteCount = WebGLuint(count) << 1;
|
||||
if (byteCount >> 1 != WebGLuint(count))
|
||||
return ErrorInvalidValue("DrawElements: overflow in byteCount");
|
||||
CheckedUint32 checked_byteCount;
|
||||
|
||||
if (type == LOCAL_GL_UNSIGNED_SHORT) {
|
||||
checked_byteCount = 2 * CheckedUint32(count);
|
||||
if (byteOffset % 2 != 0)
|
||||
return ErrorInvalidValue("DrawElements: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)");
|
||||
} else if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||
byteCount = count;
|
||||
checked_byteCount = count;
|
||||
} else {
|
||||
return ErrorInvalidEnum("DrawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE");
|
||||
}
|
||||
|
||||
if (!checked_byteCount.valid())
|
||||
return ErrorInvalidValue("DrawElements: overflow in byteCount");
|
||||
|
||||
// If count is 0, there's nothing to do.
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
@ -923,10 +938,12 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
if (!mBoundElementArrayBuffer)
|
||||
return ErrorInvalidOperation("DrawElements: must have element array buffer binding");
|
||||
|
||||
if (byteOffset+byteCount < WebGLuint(byteOffset) || byteOffset+byteCount < byteCount)
|
||||
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
|
||||
|
||||
if (!checked_neededByteCount.valid())
|
||||
return ErrorInvalidOperation("DrawElements: overflow in byteOffset+byteCount");
|
||||
|
||||
if (byteOffset + byteCount > mBoundElementArrayBuffer->ByteLength())
|
||||
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
|
||||
return ErrorInvalidOperation("DrawElements: bound element array buffer is too small for given count and offset");
|
||||
|
||||
WebGLuint maxIndex = 0;
|
||||
@ -936,8 +953,13 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
maxIndex = mBoundElementArrayBuffer->FindMaximum<GLubyte>(count, byteOffset);
|
||||
}
|
||||
|
||||
// maxIndex+1 because ValidateBuffers expects the number of elements needed
|
||||
if (!ValidateBuffers(maxIndex+1)) {
|
||||
// maxIndex+1 because ValidateBuffers expects the number of elements needed.
|
||||
// it is very important here to check tha maxIndex+1 doesn't overflow, otherwise the buffer validation is bypassed !!!
|
||||
// maxIndex is a WebGLuint, ValidateBuffers takes a PRUint32, we validate maxIndex+1 as a PRUint32.
|
||||
CheckedUint32 checked_neededCount = CheckedUint32(maxIndex) + 1;
|
||||
if (!checked_neededCount.valid())
|
||||
return ErrorInvalidOperation("drawElements: overflow in maxIndex+1");
|
||||
if (!ValidateBuffers(checked_neededCount.value())) {
|
||||
return ErrorInvalidOperation("DrawElements: bound vertex attribute buffers do not have sufficient "
|
||||
"data for given indices from the bound element array");
|
||||
}
|
||||
@ -1306,14 +1328,7 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
|
||||
break;
|
||||
|
||||
#define LOCAL_GL_MAX_VARYING_VECTORS 0x8dfc // not present in desktop OpenGL
|
||||
// temporarily add those defs here, as they're missing from
|
||||
// gfx/thebes/public/GLDefs.h
|
||||
// and from
|
||||
// gfx/layers/opengl/glDefs.h
|
||||
// and I don't know in which of these 2 files they should go (probably we're going to
|
||||
// kill one of them soon?)
|
||||
#define LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
|
||||
#define LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
|
||||
|
||||
case LOCAL_GL_MAX_VARYING_VECTORS:
|
||||
{
|
||||
#ifdef USE_GLES2
|
||||
@ -2117,7 +2132,7 @@ WebGLContext::IsEnabled(WebGLenum cap, WebGLboolean *retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_1(LineWidth, LineWidth, float)
|
||||
GL_SAME_METHOD_1(LineWidth, LineWidth, WebGLfloat)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::LinkProgram(nsIWebGLProgram *pobj)
|
||||
@ -2179,7 +2194,7 @@ WebGLContext::PixelStorei(WebGLenum pname, WebGLint param)
|
||||
}
|
||||
|
||||
|
||||
GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, float, float)
|
||||
GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, WebGLfloat, WebGLfloat)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::ReadPixels(PRInt32 dummy)
|
||||
@ -2232,16 +2247,19 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
||||
PRUint32 packAlignment;
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &packAlignment);
|
||||
|
||||
PRUint32 plainRowSize = width*size;
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
|
||||
|
||||
// alignedRowSize = row size rounded up to next multiple of
|
||||
// packAlignment which is a power of 2
|
||||
PRUint32 alignedRowSize = (plainRowSize + packAlignment-1) &
|
||||
~PRUint32(packAlignment-1);
|
||||
// alignedRowSize = row size rounded up to next multiple of packAlignment
|
||||
CheckedUint32 checked_alignedRowSize
|
||||
= ((checked_plainRowSize + packAlignment-1) / packAlignment) * packAlignment;
|
||||
|
||||
PRUint32 neededByteLength = (height-1)*alignedRowSize + plainRowSize;
|
||||
CheckedUint32 checked_neededByteLength
|
||||
= (height-1) * checked_alignedRowSize + checked_plainRowSize;
|
||||
|
||||
if(neededByteLength > byteLength)
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
|
||||
|
||||
if (checked_neededByteLength.value() > byteLength)
|
||||
return ErrorInvalidOperation("ReadPixels: buffer too small");
|
||||
|
||||
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) {
|
||||
@ -2277,7 +2295,14 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
||||
GLint subrect_end_y = PR_MIN(y+height, boundHeight);
|
||||
GLsizei subrect_height = subrect_end_y - subrect_y;
|
||||
|
||||
if (subrect_width < 0 || subrect_height < 0 ||
|
||||
subrect_width > width || subrect_height)
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing clipped rect size");
|
||||
|
||||
// now we know that subrect_width is in the [0..width] interval, and same for heights.
|
||||
|
||||
// now, same computation as above to find the size of the intermediate buffer to allocate for the subrect
|
||||
// no need to check again for integer overflow here, since we already know the sizes aren't greater than before
|
||||
PRUint32 subrect_plainRowSize = subrect_width * size;
|
||||
PRUint32 subrect_alignedRowSize = (subrect_plainRowSize + packAlignment-1) &
|
||||
~PRUint32(packAlignment-1);
|
||||
@ -2286,11 +2311,13 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
||||
// create subrect buffer, call glReadPixels, copy pixels into destination buffer, delete subrect buffer
|
||||
GLubyte *subrect_data = new GLubyte[subrect_byteLength];
|
||||
gl->fReadPixels(subrect_x, subrect_y, subrect_width, subrect_height, format, type, subrect_data);
|
||||
|
||||
// notice that this for loop terminates because we already checked that subrect_height is at most height
|
||||
for (GLint y_inside_subrect = 0; y_inside_subrect < subrect_height; ++y_inside_subrect) {
|
||||
GLint subrect_x_in_dest_buffer = subrect_x - x;
|
||||
GLint subrect_y_in_dest_buffer = subrect_y - y;
|
||||
memcpy(static_cast<GLubyte*>(data)
|
||||
+ alignedRowSize * (subrect_y_in_dest_buffer + y_inside_subrect)
|
||||
+ checked_alignedRowSize.value() * (subrect_y_in_dest_buffer + y_inside_subrect)
|
||||
+ size * subrect_x_in_dest_buffer, // destination
|
||||
subrect_data + subrect_alignedRowSize * y_inside_subrect, // source
|
||||
subrect_plainRowSize); // size
|
||||
@ -2353,14 +2380,19 @@ WebGLContext::ReadPixels_byteLength_old_API_deprecated(WebGLsizei width, WebGLsi
|
||||
PRUint32 packAlignment;
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &packAlignment);
|
||||
|
||||
PRUint32 plainRowSize = width*size;
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
|
||||
|
||||
// alignedRowSize = row size rounded up to next multiple of
|
||||
// packAlignment which is a power of 2
|
||||
PRUint32 alignedRowSize = (plainRowSize + packAlignment-1) &
|
||||
~PRUint32(packAlignment-1);
|
||||
CheckedUint32 checked_alignedRowSize
|
||||
= ((checked_plainRowSize + packAlignment-1) / packAlignment) * packAlignment;
|
||||
|
||||
*retval = (height-1)*alignedRowSize + plainRowSize;
|
||||
CheckedUint32 checked_neededByteLength = (height-1)*checked_alignedRowSize + checked_plainRowSize;
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
|
||||
|
||||
*retval = checked_neededByteLength.value();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2395,7 +2427,7 @@ WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, We
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, float, WebGLboolean)
|
||||
GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, WebGLfloat, WebGLboolean)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::Scissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
|
||||
@ -2943,9 +2975,6 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
|
||||
if (size < 1 || size > 4)
|
||||
return ErrorInvalidValue("VertexAttribPointer: invalid element size");
|
||||
|
||||
if (stride < 0)
|
||||
return ErrorInvalidValue("VertexAttribPointer: stride cannot be negative");
|
||||
|
||||
/* XXX make work with bufferSubData & heterogeneous types
|
||||
if (type != mBoundArrayBuffer->GLType())
|
||||
return ErrorInvalidOperation("VertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
|
||||
@ -3021,11 +3050,15 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
if (!ValidateTexFormatAndType(format, type, &texelSize, "texImage2D"))
|
||||
return NS_OK;
|
||||
|
||||
// XXX overflow!
|
||||
uint32 bytesNeeded = width * height * texelSize;
|
||||
CheckedUint32 checked_bytesNeeded = CheckedUint32(width) * height * texelSize;
|
||||
|
||||
if (!checked_bytesNeeded.valid())
|
||||
return ErrorInvalidOperation("texImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
PRUint32 bytesNeeded = checked_bytesNeeded.value();
|
||||
|
||||
if (byteLength && byteLength < bytesNeeded)
|
||||
return ErrorInvalidValue("TexImage2D: not enough data for operation (need %d, have %d)",
|
||||
return ErrorInvalidOperation("TexImage2D: not enough data for operation (need %d, have %d)",
|
||||
bytesNeeded, byteLength);
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -3154,8 +3187,13 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
if (width == 0 || height == 0)
|
||||
return NS_OK; // ES 2.0 says it has no effect, we better return right now
|
||||
|
||||
// XXX overflow!
|
||||
uint32 bytesNeeded = width * height * texelSize;
|
||||
CheckedUint32 checked_bytesNeeded = CheckedUint32(width) * height * texelSize;
|
||||
|
||||
if (!checked_bytesNeeded.valid())
|
||||
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
PRUint32 bytesNeeded = checked_bytesNeeded.value();
|
||||
|
||||
if (byteLength < bytesNeeded)
|
||||
return ErrorInvalidValue("TexSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
|
||||
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/*
|
||||
@ -112,12 +114,18 @@ WebGLContext::ValidateBuffers(PRUint32 count)
|
||||
continue;
|
||||
|
||||
// compute the number of bytes we actually need
|
||||
WebGLuint needed = vd.byteOffset + // the base offset
|
||||
vd.actualStride() * (count-1) + // to stride to the start of the last element group
|
||||
vd.componentSize() * vd.size; // and the number of bytes needed for these components
|
||||
CheckedUint32 checked_needed = CheckedUint32(vd.byteOffset) + // the base offset
|
||||
CheckedUint32(vd.actualStride()) * (count-1) + // to stride to the start of the last element group
|
||||
CheckedUint32(vd.componentSize()) * vd.size; // and the number of bytes needed for these components
|
||||
|
||||
if (vd.buf->ByteLength() < needed) {
|
||||
LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d", i, needed, vd.buf->ByteLength());
|
||||
if (!checked_needed.valid()) {
|
||||
LogMessage("Integer overflow computing the size of bound vertex attrib buffer at index %d", i);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (vd.buf->ByteLength() < checked_needed.value()) {
|
||||
LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d",
|
||||
i, checked_needed.value(), vd.buf->ByteLength());
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
@ -250,6 +258,19 @@ PRBool WebGLContext::ValidateFaceEnum(WebGLenum target, const char *info)
|
||||
}
|
||||
}
|
||||
|
||||
PRBool WebGLContext::ValidateBufferUsageEnum(WebGLenum target, const char *info)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_STREAM_DRAW:
|
||||
case LOCAL_GL_STATIC_DRAW:
|
||||
case LOCAL_GL_DYNAMIC_DRAW:
|
||||
return PR_TRUE;
|
||||
default:
|
||||
ErrorInvalidEnumInfo(info);
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
|
||||
PRUint32 *texelSize, const char *info)
|
||||
{
|
||||
|
@ -3111,7 +3111,7 @@ nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
|
||||
cap = gfxContext::LINE_CAP_SQUARE;
|
||||
else
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
|
||||
mThebes->SetLineCap(cap);
|
||||
return NS_OK;
|
||||
@ -3147,7 +3147,7 @@ nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
|
||||
j = gfxContext::LINE_JOIN_MITER;
|
||||
else
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
|
||||
mThebes->SetLineJoin(j);
|
||||
return NS_OK;
|
||||
@ -3532,7 +3532,8 @@ nsCanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op)
|
||||
else CANVAS_OP_TO_THEBES_OP("xor", XOR)
|
||||
// not part of spec, kept here for compat
|
||||
else CANVAS_OP_TO_THEBES_OP("over", OVER)
|
||||
else return NS_ERROR_NOT_IMPLEMENTED;
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
else return NS_OK;
|
||||
|
||||
#undef CANVAS_OP_TO_THEBES_OP
|
||||
|
||||
|
@ -1463,7 +1463,7 @@ ok(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -1569,7 +1569,7 @@ ok(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -1596,7 +1596,7 @@ ok(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -1642,7 +1642,7 @@ ok(ctx.globalCompositeOperation == 'xor', "ctx.globalCompositeOperation == 'xor'
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -9131,7 +9131,7 @@ ok(ctx.lineCap === 'butt', "ctx.lineCap === 'butt'");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -9505,7 +9505,7 @@ ok(ctx.lineJoin === 'bevel', "ctx.lineJoin === 'bevel'");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19316,7 +19316,7 @@ ok(canvas.getContext('2D') === null, "canvas.getContext('2D') === null");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19342,7 +19342,7 @@ ok(canvas.getContext("") === null, "canvas.getContext(\"\") === null");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19368,7 +19368,7 @@ ok(canvas.getContext('This is not an implemented context in any real browser') =
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19394,7 +19394,7 @@ ok(canvas.getContext("2d#") === null, "canvas.getContext(\"2d#\") === null");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19420,7 +19420,7 @@ ok(canvas.getContext("2d\0") === null, "canvas.getContext(\"2d\\0\") === null");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -19446,7 +19446,7 @@ ok(canvas.getContext("2\uFF44") === null, "canvas.getContext(\"2\\uFF44\") === n
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -20607,7 +20607,7 @@ ok(/^data:image\/png[;,]/.test(data), "data =~ /^data:image\\/png[;,]/");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
@ -20715,7 +20715,7 @@ ok(/^data:image\/png[;,]/.test(data), "data =~ /^data:image\\/png[;,]/");
|
||||
} catch (e) {
|
||||
_thrown_outer = true;
|
||||
}
|
||||
todo(!_thrown_outer, 'should not throw exception');
|
||||
ok(!_thrown_outer, 'should not throw exception');
|
||||
|
||||
|
||||
}
|
||||
|
@ -140,11 +140,11 @@ function go() {
|
||||
checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list");
|
||||
checkGetAttachedShaders([fs, vs, fs2, vs2], [], [fs, vs, fs2, vs2],
|
||||
"attaching some shaders should give the expected list");
|
||||
checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it shoud leave an empty list");
|
||||
checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it should leave an empty list");
|
||||
checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs, fs2, vs2], [],
|
||||
"attaching some shaders and detaching them in same order shoud leave an empty list");
|
||||
"attaching some shaders and detaching them in same order should leave an empty list");
|
||||
checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2, vs, fs2], [],
|
||||
"attaching some shaders and detaching them in random order shoud leave an empty list");
|
||||
"attaching some shaders and detaching them in random order should leave an empty list");
|
||||
checkGetAttachedShaders([fs, vs, fs2, vs2], [vs], [fs, fs2, vs2],
|
||||
"attaching and detaching some shaders should leave the difference list");
|
||||
checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2], [vs, fs2],
|
||||
|
@ -139,10 +139,13 @@ nsEventListenerInfo::ToSource(nsAString& aResult)
|
||||
JSContext* cx = nsnull;
|
||||
stack->GetSafeJSContext(&cx);
|
||||
if (cx && NS_SUCCEEDED(stack->Push(cx))) {
|
||||
JSAutoRequest ar(cx);
|
||||
JSString* str = JS_ValueToSource(cx, v);
|
||||
if (str) {
|
||||
aResult.Assign(nsDependentJSString(str));
|
||||
{
|
||||
// Extra block to finish the auto request before calling pop
|
||||
JSAutoRequest ar(cx);
|
||||
JSString* str = JS_ValueToSource(cx, v);
|
||||
if (str) {
|
||||
aResult.Assign(nsDependentJSString(str));
|
||||
}
|
||||
}
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
|
@ -1581,9 +1581,9 @@ nsGenericHTMLElement::ParseTableVAlignValue(const nsAString& aString,
|
||||
return aResult.ParseEnumValue(aString, kTableVAlignTable, PR_FALSE);
|
||||
}
|
||||
|
||||
PRBool
|
||||
PRBool
|
||||
nsGenericHTMLElement::ParseDivAlignValue(const nsAString& aString,
|
||||
nsAttrValue& aResult) const
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
return aResult.ParseEnumValue(aString, kDivAlignTable, PR_FALSE);
|
||||
}
|
||||
|
@ -253,8 +253,8 @@ public:
|
||||
* @param aResult the resulting HTMLValue
|
||||
* @return whether the value was parsed
|
||||
*/
|
||||
PRBool ParseDivAlignValue(const nsAString& aString,
|
||||
nsAttrValue& aResult) const;
|
||||
static PRBool ParseDivAlignValue(const nsAString& aString,
|
||||
nsAttrValue& aResult);
|
||||
|
||||
/**
|
||||
* Convert a table halign string to value (left/right/center/char/justify)
|
||||
|
@ -202,13 +202,7 @@ nsHTMLCanvasElement::ToDataURL(const nsAString& aType, const nsAString& aParams,
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsAutoString type(aType);
|
||||
|
||||
if (type.IsEmpty()) {
|
||||
type.AssignLiteral("image/png");
|
||||
}
|
||||
|
||||
return ToDataURLImpl(type, aParams, aDataURL);
|
||||
return ToDataURLImpl(aType, aParams, aDataURL);
|
||||
}
|
||||
|
||||
|
||||
@ -229,13 +223,13 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
|
||||
const nsAString& aEncoderOptions,
|
||||
nsAString& aDataURL)
|
||||
{
|
||||
nsresult rv;
|
||||
bool fallbackToPNG = false;
|
||||
|
||||
// We get an input stream from the context. If more than one context type
|
||||
// is supported in the future, this will have to be changed to do the right
|
||||
// thing. For now, just assume that the 2D context has all the goods.
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> context;
|
||||
rv = GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(context));
|
||||
nsresult rv = GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(context));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// get image bytes
|
||||
@ -244,8 +238,15 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
|
||||
rv = context->GetInputStream(nsPromiseFlatCString(aMimeType8).get(),
|
||||
nsPromiseFlatString(aEncoderOptions).get(),
|
||||
getter_AddRefs(imgStream));
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Use image/png instead.
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
fallbackToPNG = true;
|
||||
rv = context->GetInputStream("image/png",
|
||||
nsPromiseFlatString(aEncoderOptions).get(),
|
||||
getter_AddRefs(imgStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Generally, there will be only one chunk of data, and it will be available
|
||||
// for us to read right away, so optimize this case.
|
||||
@ -283,8 +284,12 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// build data URL string
|
||||
aDataURL = NS_LITERAL_STRING("data:") + aMimeType +
|
||||
NS_LITERAL_STRING(";base64,") + NS_ConvertUTF8toUTF16(encodedImg);
|
||||
if (fallbackToPNG)
|
||||
aDataURL = NS_LITERAL_STRING("data:image/png;base64,") +
|
||||
NS_ConvertUTF8toUTF16(encodedImg);
|
||||
else
|
||||
aDataURL = NS_LITERAL_STRING("data:") + aMimeType +
|
||||
NS_LITERAL_STRING(";base64,") + NS_ConvertUTF8toUTF16(encodedImg);
|
||||
|
||||
PR_Free(encodedImg);
|
||||
|
||||
@ -309,7 +314,7 @@ nsHTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
|
||||
(ctxId[i] != '_'))
|
||||
{
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +331,7 @@ nsHTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
|
||||
if (NS_FAILED(rv)) {
|
||||
*aContext = nsnull;
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = ctx->SetCanvasElement(this);
|
||||
@ -376,7 +381,7 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
|
||||
mCurrentContextId.Assign(aContextId);
|
||||
} else if (!mCurrentContextId.Equals(aContextId)) {
|
||||
//XXX eventually allow for more than one active context on a given canvas
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ADDREF (*aContext = mCurrentContext);
|
||||
|
@ -116,7 +116,7 @@ function checkHtmlForIDLAttribute(element)
|
||||
|
||||
// DOMSettableTokenList is tested in another bug so we just test assignation
|
||||
element.htmlFor.value = 'a b c';
|
||||
is(element.htmlFor, 'a b c', "htmlFor shoud have changed");
|
||||
is(element.htmlFor, 'a b c', "htmlFor should have changed");
|
||||
}
|
||||
|
||||
function submitForm()
|
||||
|
@ -148,11 +148,13 @@ NS_NewHTMLNOTUSEDElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
|
||||
}
|
||||
|
||||
#define HTML_TAG(_tag, _classname) NS_NewHTML##_classname##Element,
|
||||
#define HTML_HTMLELEMENT_TAG(_tag) NS_NewHTMLElement,
|
||||
#define HTML_OTHER(_tag) NS_NewHTMLNOTUSEDElement,
|
||||
static const contentCreatorCallback sContentCreatorCallbacks[] = {
|
||||
NS_NewHTMLUnknownElement,
|
||||
#include "nsHTMLTagList.h"
|
||||
#undef HTML_TAG
|
||||
#undef HTML_HTMLELEMENT_TAG
|
||||
#undef HTML_OTHER
|
||||
NS_NewHTMLUnknownElement
|
||||
};
|
||||
|
@ -1254,21 +1254,11 @@ nsHTMLDocument::CreateElement(const nsAString& aTagName,
|
||||
nsIDOMElement** aReturn)
|
||||
{
|
||||
*aReturn = nsnull;
|
||||
nsresult rv;
|
||||
nsresult rv = nsContentUtils::CheckQName(aTagName, PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoString tagName(aTagName);
|
||||
|
||||
// if we are in quirks, allow surrounding '<' '>' for IE compat
|
||||
if (mCompatMode == eCompatibility_NavQuirks &&
|
||||
tagName.Length() > 2 &&
|
||||
tagName.First() == '<' &&
|
||||
tagName.Last() == '>') {
|
||||
tagName = Substring(tagName, 1, tagName.Length() - 2);
|
||||
}
|
||||
|
||||
rv = nsContentUtils::CheckQName(tagName, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (IsHTML()) {
|
||||
ToLowerCase(tagName);
|
||||
}
|
||||
|
@ -1006,7 +1006,10 @@ nsHTMLParanoidFragmentSink::AddAttributes(const nsIParserNode& aNode,
|
||||
nsContentUtils::TrimCharsInSet(kWhitespace, aNode.GetValueAt(i));
|
||||
|
||||
// check the attributes we allow that contain URIs
|
||||
if (IsAttrURI(keyAtom)) {
|
||||
// special case src attributes for img tags, because they can't
|
||||
// run any dangerous code.
|
||||
if (IsAttrURI(keyAtom) &&
|
||||
!(nodeType == eHTMLTag_img && keyAtom == nsGkAtoms::src)) {
|
||||
if (!baseURI) {
|
||||
baseURI = aContent->GetBaseURI();
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ _TEST_FILES = test_bug1682.html \
|
||||
test_bug311681.xhtml \
|
||||
test_bug324378.html \
|
||||
test_bug332848.xhtml \
|
||||
test_bug340017.xhtml \
|
||||
test_bug359657.html \
|
||||
test_bug369370.html \
|
||||
bug369370-popup.png \
|
||||
@ -95,13 +96,13 @@ _TEST_FILES = test_bug1682.html \
|
||||
test_bug481647.html \
|
||||
test_bug482659.html \
|
||||
test_bug486741.html \
|
||||
test_bug489532.html \
|
||||
test_bug497242.xhtml \
|
||||
test_bug512367.html \
|
||||
test_bug570375.html \
|
||||
test_bug340017.xhtml \
|
||||
test_bug499092.html \
|
||||
bug499092.xml \
|
||||
bug499092.html \
|
||||
test_bug512367.html \
|
||||
test_bug570376.html \
|
||||
test_bug571981.html \
|
||||
$(NULL)
|
||||
|
||||
|
32
content/html/document/test/test_bug489532.html
Normal file
32
content/html/document/test/test_bug489532.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=489532
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 489532</title>
|
||||
<script src="/MochiKit/packed.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=489532">Mozilla Bug 489532</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
/** Test for Bug 489532 **/
|
||||
try {
|
||||
document.createElement("<div>");
|
||||
ok(false, "Should throw.")
|
||||
} catch (e) {
|
||||
ok(e instanceof DOMException, "Expected DOMException.");
|
||||
is(e.code, DOMException.INVALID_CHARACTER_ERR,
|
||||
"Expected INVALID_CHARACTER_ERR.");
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,16 +1,16 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=570375
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=570376
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 570375</title>
|
||||
<title>Test for Bug 570376</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570375">Mozilla Bug 570375</a>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570376">Mozilla Bug 570376</a>
|
||||
<p id="display">
|
||||
<iframe id="testiframe"></iframe>
|
||||
</p>
|
||||
@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=570375
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 570375
|
||||
/** Test for Bug 570376
|
||||
Don't crash loading <form><legend> with the html5 parser preffed off.
|
||||
**/
|
||||
|
@ -126,9 +126,9 @@ VideoData* VideoData::Create(nsVideoInfo& aInfo,
|
||||
PRUint32 picXLimit;
|
||||
PRUint32 picYLimit;
|
||||
if (!AddOverflow32(aInfo.mPicture.x, aInfo.mPicture.width, picXLimit) ||
|
||||
picXLimit > PRUint32(aBuffer.mPlanes[0].mStride) ||
|
||||
picXLimit > aBuffer.mPlanes[0].mStride ||
|
||||
!AddOverflow32(aInfo.mPicture.y, aInfo.mPicture.height, picYLimit) ||
|
||||
picYLimit > PRUint32(aBuffer.mPlanes[0].mHeight))
|
||||
picYLimit > aBuffer.mPlanes[0].mHeight)
|
||||
{
|
||||
// The specified picture dimensions can't be contained inside the video
|
||||
// frame, we'll stomp memory if we try to copy it. Fail.
|
||||
|
@ -904,10 +904,11 @@ PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset)
|
||||
// This page is from a bitstream which we haven't encountered yet.
|
||||
// It's probably from a new "link" in a "chained" ogg. Don't
|
||||
// bother even trying to find a duration...
|
||||
endTime = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
PRInt64 t = codecState ? codecState->Time(granulepos) : -1;
|
||||
PRInt64 t = codecState->Time(granulepos);
|
||||
if (t != -1) {
|
||||
endTime = t;
|
||||
}
|
||||
|
@ -325,6 +325,9 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
mResampleNeeded = PR_FALSE;
|
||||
|
||||
// STEP 1: Bring model up to date
|
||||
// (i) Rewind elements where necessary
|
||||
// (ii) Run milestone samples
|
||||
RewindElements();
|
||||
DoMilestoneSamples();
|
||||
|
||||
// STEP 2: Sample the child time containers
|
||||
@ -402,6 +405,56 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
NS_ASSERTION(!mResampleNeeded, "Resample dirty flag set during sample!");
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILAnimationController::RewindElements()
|
||||
{
|
||||
PRBool rewindNeeded = PR_FALSE;
|
||||
mChildContainerTable.EnumerateEntries(RewindNeeded, &rewindNeeded);
|
||||
if (!rewindNeeded)
|
||||
return;
|
||||
|
||||
mAnimationElementTable.EnumerateEntries(RewindAnimation, nsnull);
|
||||
mChildContainerTable.EnumerateEntries(ClearRewindNeeded, nsnull);
|
||||
}
|
||||
|
||||
/*static*/ PR_CALLBACK PLDHashOperator
|
||||
nsSMILAnimationController::RewindNeeded(TimeContainerPtrKey* aKey,
|
||||
void* aData)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aData,
|
||||
"Null data pointer during time container enumeration");
|
||||
PRBool* rewindNeeded = static_cast<PRBool*>(aData);
|
||||
|
||||
nsSMILTimeContainer* container = aKey->GetKey();
|
||||
if (container->NeedsRewind()) {
|
||||
*rewindNeeded = PR_TRUE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/*static*/ PR_CALLBACK PLDHashOperator
|
||||
nsSMILAnimationController::RewindAnimation(AnimationElementPtrKey* aKey,
|
||||
void* aData)
|
||||
{
|
||||
nsISMILAnimationElement* animElem = aKey->GetKey();
|
||||
nsSMILTimeContainer* timeContainer = animElem->GetTimeContainer();
|
||||
if (timeContainer && timeContainer->NeedsRewind()) {
|
||||
animElem->TimedElement().Rewind();
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/*static*/ PR_CALLBACK PLDHashOperator
|
||||
nsSMILAnimationController::ClearRewindNeeded(TimeContainerPtrKey* aKey,
|
||||
void* aData)
|
||||
{
|
||||
aKey->GetKey()->ClearNeedsRewind();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILAnimationController::DoMilestoneSamples()
|
||||
{
|
||||
@ -542,6 +595,7 @@ nsSMILAnimationController::SampleTimeContainer(TimeContainerPtrKey* aKey,
|
||||
(container->NeedsSample() || !params->mSkipUnchangedContainers)) {
|
||||
container->ClearMilestones();
|
||||
container->Sample();
|
||||
container->MarkSeekFinished();
|
||||
params->mActiveContainers->PutEntry(container);
|
||||
}
|
||||
|
||||
@ -587,6 +641,8 @@ nsSMILAnimationController::SampleTimedElement(
|
||||
|
||||
nsSMILTime containerTime = timeContainer->GetCurrentTime();
|
||||
|
||||
NS_ABORT_IF_FALSE(!timeContainer->IsSeeking(),
|
||||
"Doing a regular sample but the time container is still seeking");
|
||||
aElement->TimedElement().SampleAt(containerTime);
|
||||
}
|
||||
|
||||
|
@ -152,11 +152,21 @@ protected:
|
||||
// Sample-related callbacks and implementation helpers
|
||||
virtual void DoSample();
|
||||
void DoSample(PRBool aSkipUnchangedContainers);
|
||||
|
||||
void RewindElements();
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) RewindNeeded(
|
||||
TimeContainerPtrKey* aKey, void* aData);
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) RewindAnimation(
|
||||
AnimationElementPtrKey* aKey, void* aData);
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) ClearRewindNeeded(
|
||||
TimeContainerPtrKey* aKey, void* aData);
|
||||
|
||||
void DoMilestoneSamples();
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) GetNextMilestone(
|
||||
TimeContainerPtrKey* aKey, void* aData);
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) GetMilestoneElements(
|
||||
TimeContainerPtrKey* aKey, void* aData);
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) SampleTimeContainer(
|
||||
TimeContainerPtrKey* aKey, void* aData);
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) SampleAnimation(
|
||||
|
@ -74,9 +74,9 @@ nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
|
||||
nsSMILInterval* aBaseInterval)
|
||||
: mTime(aTime),
|
||||
mFlags(0),
|
||||
mSerial(0),
|
||||
mVisited(PR_FALSE),
|
||||
mChainEnd(PR_FALSE),
|
||||
mFixedEndpointRefCnt(0),
|
||||
mSerial(0),
|
||||
mCreator(aCreator),
|
||||
mBaseInterval(nsnull) // This will get set to aBaseInterval in a call to
|
||||
// SetBaseInterval() at end of constructor
|
||||
@ -87,7 +87,7 @@ nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
|
||||
break;
|
||||
|
||||
case SOURCE_DOM:
|
||||
mFlags = kClearOnReset | kFromDOM;
|
||||
mFlags = kDynamic | kFromDOM;
|
||||
break;
|
||||
|
||||
case SOURCE_SYNCBASE:
|
||||
@ -95,7 +95,7 @@ nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
|
||||
break;
|
||||
|
||||
case SOURCE_EVENT:
|
||||
mFlags = kClearOnReset;
|
||||
mFlags = kDynamic;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -106,6 +106,9 @@ nsSMILInstanceTime::~nsSMILInstanceTime()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mBaseInterval && !mCreator,
|
||||
"Destroying instance time without first calling Unlink()");
|
||||
NS_ABORT_IF_FALSE(mFixedEndpointRefCnt == 0,
|
||||
"Destroying instance time that is still used as the fixed endpoint of an "
|
||||
"interval");
|
||||
}
|
||||
|
||||
void
|
||||
@ -129,12 +132,9 @@ nsSMILInstanceTime::HandleChangedInterval(
|
||||
"Got call to HandleChangedInterval on an independent instance time.");
|
||||
NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not.");
|
||||
|
||||
if (mVisited || mChainEnd) {
|
||||
// We're breaking the cycle here but we need to ensure that if we later
|
||||
// receive a change notice in a different context (e.g. due to a time
|
||||
// container change) that we don't end up following the chain further and so
|
||||
// we set a flag to that effect.
|
||||
mChainEnd = PR_TRUE;
|
||||
if (mVisited) {
|
||||
// Break the cycle here
|
||||
Unlink();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,20 +152,63 @@ void
|
||||
nsSMILInstanceTime::HandleDeletedInterval()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mBaseInterval,
|
||||
"Got call to HandleDeletedInterval on an independent instance time.");
|
||||
NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not.");
|
||||
"Got call to HandleDeletedInterval on an independent instance time");
|
||||
NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not");
|
||||
|
||||
mBaseInterval = nsnull;
|
||||
mFlags &= ~kMayUpdate; // Can't update without a base interval
|
||||
|
||||
nsRefPtr<nsSMILInstanceTime> deathGrip(this);
|
||||
mCreator->HandleDeletedInstanceTime(*this);
|
||||
mCreator = nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILInstanceTime::IsDependent(const nsSMILInstanceTime& aOther) const
|
||||
void
|
||||
nsSMILInstanceTime::HandleFilteredInterval()
|
||||
{
|
||||
if (mVisited || mChainEnd)
|
||||
NS_ABORT_IF_FALSE(mBaseInterval,
|
||||
"Got call to HandleFilteredInterval on an independent instance time");
|
||||
|
||||
mBaseInterval = nsnull;
|
||||
mFlags &= ~kMayUpdate; // Can't update without a base interval
|
||||
mCreator = nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILInstanceTime::ShouldPreserve() const
|
||||
{
|
||||
return mFixedEndpointRefCnt > 0 || (mFlags & kWasDynamicEndpoint);
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInstanceTime::UnmarkShouldPreserve()
|
||||
{
|
||||
mFlags &= ~kWasDynamicEndpoint;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInstanceTime::AddRefFixedEndpoint()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mFixedEndpointRefCnt < PR_UINT16_MAX,
|
||||
"Fixed endpoint reference count upper limit reached");
|
||||
++mFixedEndpointRefCnt;
|
||||
mFlags &= ~kMayUpdate; // Once fixed, always fixed
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInstanceTime::ReleaseFixedEndpoint()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mFixedEndpointRefCnt > 0, "Duplicate release");
|
||||
--mFixedEndpointRefCnt;
|
||||
if (mFixedEndpointRefCnt == 0 && IsDynamic()) {
|
||||
mFlags |= kWasDynamicEndpoint;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const
|
||||
{
|
||||
if (mVisited)
|
||||
return PR_FALSE;
|
||||
|
||||
const nsSMILInstanceTime* myBaseTime = GetBaseTime();
|
||||
@ -177,7 +220,7 @@ nsSMILInstanceTime::IsDependent(const nsSMILInstanceTime& aOther) const
|
||||
|
||||
// mVisited is mutable
|
||||
AutoBoolSetter setVisited(const_cast<nsSMILInstanceTime*>(this)->mVisited);
|
||||
return myBaseTime->IsDependent(aOther);
|
||||
return myBaseTime->IsDependentOn(aOther);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -92,24 +92,31 @@ public:
|
||||
PRBool aBeginObjectChanged,
|
||||
PRBool aEndObjectChanged);
|
||||
void HandleDeletedInterval();
|
||||
void HandleFilteredInterval();
|
||||
|
||||
const nsSMILTimeValue& Time() const { return mTime; }
|
||||
const nsSMILTimeValueSpec* GetCreator() const { return mCreator; }
|
||||
|
||||
PRBool ClearOnReset() const { return !!(mFlags & kClearOnReset); }
|
||||
PRBool MayUpdate() const { return !!(mFlags & kMayUpdate); }
|
||||
PRBool IsDynamic() const { return !!(mFlags & kDynamic); }
|
||||
PRBool IsFixedTime() const { return !(mFlags & kMayUpdate); }
|
||||
PRBool FromDOM() const { return !!(mFlags & kFromDOM); }
|
||||
|
||||
void MarkNoLongerUpdating() { mFlags &= ~kMayUpdate; }
|
||||
PRBool ShouldPreserve() const;
|
||||
void UnmarkShouldPreserve();
|
||||
|
||||
void AddRefFixedEndpoint();
|
||||
void ReleaseFixedEndpoint();
|
||||
|
||||
void DependentUpdate(const nsSMILTimeValue& aNewTime)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(MayUpdate(),
|
||||
NS_ABORT_IF_FALSE(!IsFixedTime(),
|
||||
"Updating an instance time that is not expected to be updated");
|
||||
mTime = aNewTime;
|
||||
}
|
||||
|
||||
PRBool IsDependent(const nsSMILInstanceTime& aOther) const;
|
||||
PRBool IsDependent() const { return !!mBaseInterval; }
|
||||
PRBool IsDependentOn(const nsSMILInstanceTime& aOther) const;
|
||||
const nsSMILInterval* GetBaseInterval() const { return mBaseInterval; }
|
||||
|
||||
PRBool SameTimeAndBase(const nsSMILInstanceTime& aOther) const
|
||||
{
|
||||
@ -131,15 +138,16 @@ protected:
|
||||
|
||||
// Internal flags used to represent the behaviour of different instance times
|
||||
enum {
|
||||
// Indicates if this instance time should be removed when the owning timed
|
||||
// element is reset. True for events and DOM calls.
|
||||
kClearOnReset = 1,
|
||||
// Indicates that this instance time was generated by an event or a DOM
|
||||
// call. Such instance times require special handling when (i) the owning
|
||||
// element is reset, and (ii) when a backwards seek is performed and the
|
||||
// timing model is reconstructed.
|
||||
kDynamic = 1,
|
||||
|
||||
// Indicates that this instance time is referred to by an
|
||||
// nsSMILTimeValueSpec and as such may be updated. Such instance time should
|
||||
// not be filtered out by the nsSMILTimedElement even if they appear to be
|
||||
// in the past as they may be updated to a future time. Initially set for
|
||||
// syncbase-generated times until they are frozen.
|
||||
// in the past as they may be updated to a future time.
|
||||
kMayUpdate = 2,
|
||||
|
||||
// Indicates that this instance time was generated from the DOM as opposed
|
||||
@ -147,17 +155,33 @@ protected:
|
||||
// reset we should clear all the instance times that have been generated by
|
||||
// that attribute (and hence an nsSMILTimeValueSpec), but not those from the
|
||||
// DOM.
|
||||
kFromDOM = 4
|
||||
kFromDOM = 4,
|
||||
|
||||
// Indicates that this instance time was used as the endpoint of an interval
|
||||
// that has been filtered or removed. However, since it is a dynamic time it
|
||||
// should be preserved and not filtered.
|
||||
kWasDynamicEndpoint = 8
|
||||
};
|
||||
PRUint8 mFlags; // Combination of kClearOnReset, kMayUpdate, etc.
|
||||
PRUint8 mFlags; // Combination of kDynamic, kMayUpdate, etc.
|
||||
PRPackedBool mVisited; // (mutable) Cycle tracking
|
||||
|
||||
// Additional reference count to determine if this instance time is currently
|
||||
// used as a fixed endpoint in any intervals. Instance times that are used in
|
||||
// this way should not be removed when the owning nsSMILTimedElement removes
|
||||
// instance times in response to a restart or in an attempt to free up memory
|
||||
// by filtering out old instance times.
|
||||
//
|
||||
// Instance times are only shared in a few cases, namely:
|
||||
// a) early ends,
|
||||
// b) zero-duration intervals, and
|
||||
// c) momentarily whilst establishing new intervals and updating the current
|
||||
// interval
|
||||
// Hence the limited range of a PRUint16 should be more than adequate.
|
||||
PRUint16 mFixedEndpointRefCnt;
|
||||
|
||||
PRUint32 mSerial; // A serial number used by the containing class to
|
||||
// specify the sort order for instance times with the
|
||||
// same mTime.
|
||||
PRPackedBool mVisited; // (mutable) Cycle tracking
|
||||
PRPackedBool mChainEnd; // Flag to indicate that this instance time is part
|
||||
// of some cyclic dependency and that in order to
|
||||
// avoid infinite recursion the cycle should not be
|
||||
// followed any further than this point.
|
||||
|
||||
nsSMILTimeValueSpec* mCreator; // The nsSMILTimeValueSpec object that created
|
||||
// us. (currently only needed for syncbase
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
nsSMILInterval::nsSMILInterval()
|
||||
:
|
||||
mBeginFixed(PR_FALSE),
|
||||
mEndFixed(PR_FALSE),
|
||||
mBeginObjectChanged(PR_FALSE),
|
||||
mEndObjectChanged(PR_FALSE)
|
||||
{
|
||||
@ -48,19 +50,28 @@ nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther)
|
||||
:
|
||||
mBegin(aOther.mBegin),
|
||||
mEnd(aOther.mEnd),
|
||||
mBeginFixed(PR_FALSE),
|
||||
mEndFixed(PR_FALSE),
|
||||
mBeginObjectChanged(PR_FALSE),
|
||||
mEndObjectChanged(PR_FALSE)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aOther.mDependentTimes.IsEmpty(),
|
||||
"Attempting to copy-construct an interval with dependent times, "
|
||||
"this will lead to instance times being shared between intervals.");
|
||||
|
||||
// For the time being we don't allow intervals with fixed endpoints to be
|
||||
// copied since we only ever copy-construct to establish a new current
|
||||
// interval. If we ever need to copy historical intervals we may need to move
|
||||
// the ReleaseFixedEndpoint calls from Unlink to the dtor.
|
||||
NS_ABORT_IF_FALSE(!aOther.mBeginFixed && !aOther.mEndFixed,
|
||||
"Attempting to copy-construct an interval with fixed endpoints");
|
||||
}
|
||||
|
||||
nsSMILInterval::~nsSMILInterval()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mDependentTimes.IsEmpty(),
|
||||
"Destroying interval without disassociating dependent instance times. "
|
||||
"NotifyDeleting was not called.");
|
||||
"Unlink was not called");
|
||||
}
|
||||
|
||||
void
|
||||
@ -76,12 +87,24 @@ nsSMILInterval::NotifyChanged(const nsSMILTimeContainer* aContainer)
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInterval::NotifyDeleting()
|
||||
nsSMILInterval::Unlink(PRBool aFiltered)
|
||||
{
|
||||
for (PRInt32 i = mDependentTimes.Length() - 1; i >= 0; --i) {
|
||||
mDependentTimes[i]->HandleDeletedInterval();
|
||||
if (aFiltered) {
|
||||
mDependentTimes[i]->HandleFilteredInterval();
|
||||
} else {
|
||||
mDependentTimes[i]->HandleDeletedInterval();
|
||||
}
|
||||
}
|
||||
mDependentTimes.Clear();
|
||||
if (mBegin && mBeginFixed) {
|
||||
mBegin->ReleaseFixedEndpoint();
|
||||
}
|
||||
mBegin = nsnull;
|
||||
if (mEnd && mEndFixed) {
|
||||
mEnd->ReleaseFixedEndpoint();
|
||||
}
|
||||
mEnd = nsnull;
|
||||
}
|
||||
|
||||
nsSMILInstanceTime*
|
||||
@ -104,7 +127,9 @@ void
|
||||
nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aBegin.Time().IsResolved(),
|
||||
"Attempting to set unresolved begin time on interval.");
|
||||
"Attempting to set unresolved begin time on interval");
|
||||
NS_ABORT_IF_FALSE(!mBeginFixed,
|
||||
"Attempting to set begin time but the begin point is fixed");
|
||||
|
||||
if (mBegin == &aBegin)
|
||||
return;
|
||||
@ -116,6 +141,9 @@ nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
|
||||
void
|
||||
nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mEndFixed,
|
||||
"Attempting to set end time but the end point is fixed");
|
||||
|
||||
if (mEnd == &aEnd)
|
||||
return;
|
||||
|
||||
@ -123,6 +151,28 @@ nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd)
|
||||
mEndObjectChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInterval::FixBegin()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mBegin && mEnd,
|
||||
"Fixing begin point on un-initialized interval");
|
||||
NS_ABORT_IF_FALSE(!mBeginFixed, "Duplicate calls to FixBegin()");
|
||||
mBeginFixed = PR_TRUE;
|
||||
mBegin->AddRefFixedEndpoint();
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInterval::FixEnd()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mBegin && mEnd,
|
||||
"Fixing end point on un-initialized interval");
|
||||
NS_ABORT_IF_FALSE(mBeginFixed,
|
||||
"Fixing the end of an interval without a fixed begin");
|
||||
NS_ABORT_IF_FALSE(!mEndFixed, "Duplicate calls to FixEnd()");
|
||||
mEndFixed = PR_TRUE;
|
||||
mEnd->AddRefFixedEndpoint();
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILInterval::AddDependentTime(nsSMILInstanceTime& aTime)
|
||||
{
|
||||
@ -142,3 +192,19 @@ nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime)
|
||||
mDependentTimes.RemoveElementSorted(&aTime);
|
||||
NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete.");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILInterval::IsDependencyChainLink() const
|
||||
{
|
||||
if (!mBegin || !mEnd)
|
||||
return PR_FALSE; // Not yet initialised so it can't be part of a chain
|
||||
|
||||
if (mDependentTimes.IsEmpty())
|
||||
return PR_FALSE; // No dependents, chain end
|
||||
|
||||
// So we have dependents, but we're still only a link in the chain (as opposed
|
||||
// to the end of the chain) if one of our endpoints is dependent on an
|
||||
// interval other than ourselves.
|
||||
return (mBegin->IsDependent() && mBegin->GetBaseInterval() != this) ||
|
||||
(mEnd->IsDependent() && mEnd->GetBaseInterval() != this);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user