Merge mozilla-central to electrolysis.

This commit is contained in:
Benjamin Smedberg 2009-10-20 12:08:28 -04:00
commit 9ae75c423f
1271 changed files with 11388 additions and 35688 deletions

View file

@ -4,6 +4,7 @@
~$ ~$
\.pyc$ \.pyc$
(^|/)TAGS$ (^|/)TAGS$
(^|/)ID$
(^|/)\.DS_Store$ (^|/)\.DS_Store$
# User files that may appear at the root # User files that may appear at the root
@ -12,7 +13,6 @@
^configure$ ^configure$
^config\.cache$ ^config\.cache$
^config\.log$ ^config\.log$
^ID$
# Empty marker file that's generated when we check out NSS # Empty marker file that's generated when we check out NSS
^security/manager/\.nss\.checkout$ ^security/manager/\.nss\.checkout$
@ -27,6 +27,8 @@ _OPT\.OBJ/
# SpiderMonkey configury # SpiderMonkey configury
^js/src/configure$ ^js/src/configure$
^js/src/autom4te.cache$ ^js/src/autom4te.cache$
# SpiderMonkey test result logs
^js/src/tests/results-.*\.(html|txt)$
# Java HTML5 parser classes # Java HTML5 parser classes
^parser/html/java/(html|java)parser/ ^parser/html/java/(html|java)parser/

View file

@ -44,7 +44,7 @@
* @note - When adding a new role, be sure to also add it to nsRoleMap.h for * @note - When adding a new role, be sure to also add it to nsRoleMap.h for
* each platform. * each platform.
*/ */
[scriptable, uuid(6793ca5c-c7cb-41db-9fb9-c16c0525f962)] [scriptable, uuid(f134da65-39a8-4330-843c-5bd42780b34c)]
interface nsIAccessibleRole : nsISupports interface nsIAccessibleRole : nsISupports
{ {
/** /**
@ -776,10 +776,15 @@ interface nsIAccessibleRole : nsISupports
*/ */
const unsigned long ROLE_GRID_CELL = 121; const unsigned long ROLE_GRID_CELL = 121;
/**
* Represents an embedded object. It is used for html:object or html:embed.
*/
const unsigned long ROLE_EMBEDDED_OBJECT = 122;
/** /**
* It's not role actually. This constant is important to help ensure * It's not role actually. This constant is important to help ensure
* nsRoleMap's are synchronized. * nsRoleMap's are synchronized.
*/ */
const unsigned long ROLE_LAST_ENTRY = 122; const unsigned long ROLE_LAST_ENTRY = 123;
}; };

View file

@ -168,6 +168,7 @@ static const PRUint32 atkRoleMap[] = {
ATK_ROLE_LIST, // nsIAccessibleRole::ROLE_LISTBOX 119 ATK_ROLE_LIST, // nsIAccessibleRole::ROLE_LISTBOX 119
ATK_ROLE_UNKNOWN, // nsIAccessibleRole::ROLE_FLAT_EQUATION 120 ATK_ROLE_UNKNOWN, // nsIAccessibleRole::ROLE_FLAT_EQUATION 120
ATK_ROLE_TABLE_CELL, // nsIAccessibleRole::ROLE_GRID_CELL 121 ATK_ROLE_TABLE_CELL, // nsIAccessibleRole::ROLE_GRID_CELL 121
ATK_ROLE_PANEL, // nsIAccessibleRole::ROLE_EMBEDDED_OBJECT 122
kROLE_ATK_LAST_ENTRY // nsIAccessibleRole::ROLE_LAST_ENTRY kROLE_ATK_LAST_ENTRY // nsIAccessibleRole::ROLE_LAST_ENTRY
}; };

View file

@ -408,14 +408,30 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
nsIAccessible **aTreeItemParentResult) nsIAccessible **aTreeItemParentResult)
{ {
*aTreeItemParentResult = nsnull; *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; nsAutoString levelStr;
PRInt32 level = 0;
if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) && if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) &&
aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) { aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) {
// This is a tree 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
PRInt32 success; PRInt32 success;
level = levelStr.ToInteger(&success); PRInt32 level = levelStr.ToInteger(&success);
if (level > 1 && NS_SUCCEEDED(success)) { if (level > 1 && NS_SUCCEEDED(success)) {
nsCOMPtr<nsIAccessible> currentAccessible = aStartTreeItem, prevAccessible; nsCOMPtr<nsIAccessible> currentAccessible = aStartTreeItem, prevAccessible;
while (PR_TRUE) { while (PR_TRUE) {
@ -426,8 +442,9 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
break; // Reached top of tree, no higher level found break; // Reached top of tree, no higher level found
} }
PRUint32 role = nsAccUtils::Role(currentAccessible); PRUint32 role = nsAccUtils::Role(currentAccessible);
if (role != nsIAccessibleRole::ROLE_OUTLINEITEM) if (role != startTreeItemRole)
continue; continue;
nsCOMPtr<nsIDOMNode> treeItemNode; nsCOMPtr<nsIDOMNode> treeItemNode;
accessNode->GetDOMNode(getter_AddRefs(treeItemNode)); accessNode->GetDOMNode(getter_AddRefs(treeItemNode));
nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode); nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode);
@ -445,19 +462,25 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
} }
} }
// Possibly a tree arranged by using role="group" to organize levels // In the case of ARIA treegrid, return its parent since ARIA group isn't
// In this case the parent of the tree item will be a group and the // used to organize levels in ARIA treegrids.
// previous sibling of that should be the tree item parent.
// Or, if the parent is something other than a tree we will return that. if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) {
nsCOMPtr<nsIAccessible> parentAccessible; NS_ADDREF(*aTreeItemParentResult = parentAccessible);
aStartTreeItem->GetParent(getter_AddRefs(parentAccessible)); return; // The container for the tree grid rows
if (!parentAccessible) }
return;
// 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); PRUint32 role = nsAccUtils::Role(parentAccessible);
if (role != nsIAccessibleRole::ROLE_GROUPING) { if (role != nsIAccessibleRole::ROLE_GROUPING) {
NS_ADDREF(*aTreeItemParentResult = parentAccessible); NS_ADDREF(*aTreeItemParentResult = parentAccessible);
return; // The container for the tree items return; // The container for the tree items
} }
nsCOMPtr<nsIAccessible> prevAccessible; nsCOMPtr<nsIAccessible> prevAccessible;
parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible)); parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
if (!prevAccessible) if (!prevAccessible)

View file

@ -548,6 +548,15 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame *aFrame,
*aAccessible = new nsHTMLListAccessible(aNode, aWeakShell); *aAccessible = new nsHTMLListAccessible(aNode, aWeakShell);
} }
else if (tag == nsAccessibilityAtoms::a) { else if (tag == nsAccessibilityAtoms::a) {
// Only some roles truly enjoy life as nsHTMLLinkAccessibles, for details
// see closed bug 494807.
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
if (roleMapEntry && roleMapEntry->role != nsIAccessibleRole::ROLE_NOTHING
&& roleMapEntry->role != nsIAccessibleRole::ROLE_LINK) {
return CreateHyperTextAccessible(aFrame, aAccessible);
}
*aAccessible = new nsHTMLLinkAccessible(aNode, aWeakShell); *aAccessible = new nsHTMLLinkAccessible(aNode, aWeakShell);
} }
else if (tag == nsAccessibilityAtoms::li && aFrame->GetType() != nsAccessibilityAtoms::blockFrame) { else if (tag == nsAccessibilityAtoms::li && aFrame->GetType() != nsAccessibilityAtoms::blockFrame) {
@ -763,15 +772,16 @@ nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame *aFrame,
nsCOMPtr<nsIPluginInstance> pluginInstance ; nsCOMPtr<nsIPluginInstance> pluginInstance ;
aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance)); aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
if (pluginInstance) { if (pluginInstance) {
// Note: pluginPort will be null if windowless.
HWND pluginPort = nsnull; HWND pluginPort = nsnull;
aFrame->GetPluginPort(&pluginPort); aFrame->GetPluginPort(&pluginPort);
if (pluginPort) {
*aAccessible = new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort); *aAccessible =
if (*aAccessible) { new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort);
NS_ADDREF(*aAccessible); NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
} NS_ADDREF(*aAccessible);
} return NS_OK;
} }
#endif #endif

View file

@ -289,7 +289,8 @@ static const char kRoleNames[][20] = {
"listbox rich option", //ROLE_RICH_OPTION "listbox rich option", //ROLE_RICH_OPTION
"listbox", //ROLE_LISTBOX "listbox", //ROLE_LISTBOX
"flat equation", //ROLE_FLAT_EQUATION "flat equation", //ROLE_FLAT_EQUATION
"gridcell" //ROLE_GRID_CELL "gridcell", //ROLE_GRID_CELL
"embedded object" //ROLE_EMBEDDED_OBJECT
}; };
/** /**

View file

@ -2492,13 +2492,16 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
if (rv != NS_OK_NO_RELATION_TARGET) if (rv != NS_OK_NO_RELATION_TARGET)
return NS_OK; // XXX bug 381599, avoid performance problems return NS_OK; // XXX bug 381599, avoid performance problems
// This is an ARIA tree or treegrid that doesn't use owns, so we need to
// get the parent the hard way.
if (mRoleMapEntry && if (mRoleMapEntry &&
mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM) { (mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
// This is an ARIA tree that doesn't use owns, so we need to get mRoleMapEntry->role == nsIAccessibleRole::ROLE_ROW)) {
// the parent the hard way.
nsCOMPtr<nsIAccessible> accTarget; nsCOMPtr<nsIAccessible> accTarget;
nsAccUtils::GetARIATreeItemParent(this, content, nsAccUtils::GetARIATreeItemParent(this, content,
getter_AddRefs(accTarget)); getter_AddRefs(accTarget));
return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget); return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget);
} }

View file

@ -924,20 +924,12 @@ NS_IMETHODIMP
nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn, nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
nsIAccessible **aTableCellAccessible) nsIAccessible **aTableCellAccessible)
{ {
NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMElement> cellElement; nsCOMPtr<nsIDOMElement> cellElement;
rv = GetCellAt(aRow, aColumn, *getter_AddRefs(cellElement)); nsresult rv = GetCellAt(aRow, aColumn, *getter_AddRefs(cellElement));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAccessibilityService> return GetAccService()->GetAccessibleInWeakShell(cellElement, mWeakShell,
accService(do_GetService("@mozilla.org/accessibilityService;1")); aTableCellAccessible);
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
return accService->GetAccessibleInWeakShell(cellElement, mWeakShell,
aTableCellAccessible);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -946,8 +938,6 @@ nsHTMLTableAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
{ {
NS_ENSURE_ARG_POINTER(aIndex); NS_ENSURE_ARG_POINTER(aIndex);
NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
nsITableLayout *tableLayout = GetTableLayout(); nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
@ -970,7 +960,10 @@ nsHTMLTableAccessible::GetColumnIndexAt(PRInt32 aIndex, PRInt32 *aColumn)
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
PRInt32 row; PRInt32 row;
return tableLayout->GetRowAndColumnByIndex(aIndex, &row, aColumn); nsresult rv = tableLayout->GetRowAndColumnByIndex(aIndex, &row, aColumn);
NS_ENSURE_SUCCESS(rv, rv);
return (row == -1 || *aColumn == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -985,7 +978,10 @@ nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
PRInt32 column; PRInt32 column;
return tableLayout->GetRowAndColumnByIndex(aIndex, aRow, &column); nsresult rv = tableLayout->GetRowAndColumnByIndex(aIndex, aRow, &column);
NS_ENSURE_SUCCESS(rv, rv);
return (*aRow == -1 || column == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -993,9 +989,6 @@ nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
PRInt32 aColumnIndex, PRInt32 aColumnIndex,
PRInt32 *aExtentCount) PRInt32 *aExtentCount)
{ {
NS_ENSURE_TRUE(IsValidRow(aRowIndex) && IsValidColumn(aColumnIndex),
NS_ERROR_INVALID_ARG);
nsITableLayout *tableLayout = GetTableLayout(); nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
@ -1003,19 +996,18 @@ nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan; PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan;
PRBool isSelected; PRBool isSelected;
return tableLayout-> nsresult rv = tableLayout->
GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement), GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan, startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, *aExtentCount, isSelected); actualRowSpan, *aExtentCount, isSelected);
return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex, nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32 *aExtentCount) PRInt32 *aExtentCount)
{ {
NS_ENSURE_TRUE(IsValidRow(aRowIndex) && IsValidColumn(aColumnIndex),
NS_ERROR_INVALID_ARG);
nsITableLayout *tableLayout = GetTableLayout(); nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
@ -1023,10 +1015,12 @@ nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualColSpan; PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualColSpan;
PRBool isSelected; PRBool isSelected;
return tableLayout-> nsresult rv = tableLayout->
GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement), GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan, startRowIndex, startColIndex, rowSpan, colSpan,
*aExtentCount, actualColSpan, isSelected); *aExtentCount, actualColSpan, isSelected);
return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1042,51 +1036,63 @@ nsHTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString &_retval)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLTableAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *_retval) nsHTMLTableAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *aIsSelected)
{ {
NS_ENSURE_ARG_POINTER(_retval); NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = PR_FALSE;
NS_ENSURE_TRUE(IsValidColumn(aColumn), NS_ERROR_INVALID_ARG); PRInt32 colCount = 0;
nsresult rv = GetColumnCount(&colCount);
nsresult rv = NS_OK;
PRInt32 rows;
rv = GetRowCount(&rows);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 index = 0; index < rows; index++) { if (aColumn < 0 || aColumn >= colCount)
rv = IsCellSelected(index, aColumn, _retval); return NS_ERROR_INVALID_ARG;
NS_ENSURE_SUCCESS(rv, rv);
if (!*_retval) { PRInt32 rowCount = 0;
break; rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
PRBool isSelected = PR_FALSE;
rv = IsCellSelected(rowIdx, aColumn, &isSelected);
if (NS_SUCCEEDED(rv)) {
*aIsSelected = isSelected;
if (!isSelected)
break;
} }
} }
return rv; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLTableAccessible::IsRowSelected(PRInt32 aRow, PRBool *_retval) nsHTMLTableAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
{ {
NS_ENSURE_ARG_POINTER(_retval); NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = PR_FALSE;
NS_ENSURE_TRUE(IsValidRow(aRow), NS_ERROR_INVALID_ARG); PRInt32 rowCount = 0;
nsresult rv = GetRowCount(&rowCount);
nsresult rv = NS_OK;
PRInt32 columns;
rv = GetColumnCount(&columns);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 index = 0; index < columns; index++) { if (aRow < 0 || aRow >= rowCount)
rv = IsCellSelected(aRow, index, _retval); return NS_ERROR_INVALID_ARG;
NS_ENSURE_SUCCESS(rv, rv);
if (!*_retval) { PRInt32 colCount = 0;
break; rv = GetColumnCount(&colCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++) {
PRBool isSelected = PR_FALSE;
rv = IsCellSelected(aRow, colIdx, &isSelected);
if (NS_SUCCEEDED(rv)) {
*aIsSelected = isSelected;
if (!isSelected)
break;
} }
} }
return rv; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1096,9 +1102,6 @@ nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
NS_ENSURE_ARG_POINTER(aIsSelected); NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = PR_FALSE; *aIsSelected = PR_FALSE;
NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn),
NS_ERROR_INVALID_ARG);
nsITableLayout *tableLayout = GetTableLayout(); nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout); NS_ENSURE_STATE(tableLayout);
@ -1116,22 +1119,6 @@ nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
return rv; return rv;
} }
PRBool
nsHTMLTableAccessible::IsValidColumn(PRInt32 aColumn)
{
PRInt32 colCount = 0;
nsresult rv = GetColumnCount(&colCount);
return NS_SUCCEEDED(rv) && (aColumn >= 0) && (aColumn < colCount);
}
PRBool
nsHTMLTableAccessible::IsValidRow(PRInt32 aRow)
{
PRInt32 rowCount = 0;
nsresult rv = GetRowCount(&rowCount);
return NS_SUCCEEDED(rv) && (aRow >= 0) && (aRow < rowCount);
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLTableAccessible::SelectRow(PRInt32 aRow) nsHTMLTableAccessible::SelectRow(PRInt32 aRow)
{ {

View file

@ -143,20 +143,6 @@ public:
// nsHTMLTableAccessible // nsHTMLTableAccessible
/**
* Returns true if the column index is in the valid column range.
*
* @param aColumn The index to check for validity.
*/
PRBool IsValidColumn(PRInt32 aColumn);
/**
* Returns true if the given index is in the valid row range.
*
* @param aRow The index to check for validity.
*/
PRBool IsValidRow(PRInt32 aRow);
/** /**
* Retun cell element at the given row and column index. * Retun cell element at the given row and column index.
*/ */

View file

@ -164,5 +164,6 @@ static const NSString* AXRoles [] = {
NSAccessibilityListRole, // ROLE_LISTBOX NSAccessibilityListRole, // ROLE_LISTBOX
NSAccessibilityUnknownRole, // ROLE_FLAT_EQUATION NSAccessibilityUnknownRole, // ROLE_FLAT_EQUATION
NSAccessibilityGroupRole, // ROLE_GRID_CELL NSAccessibilityGroupRole, // ROLE_GRID_CELL
NSAccessibilityGroupRole, // ROLE_EMBEDDED_OBJECT
@"ROLE_LAST_ENTRY" // ROLE_LAST_ENTRY. bogus role that will never be shown (just marks the end of this array)! @"ROLE_LAST_ENTRY" // ROLE_LAST_ENTRY. bogus role that will never be shown (just marks the end of this array)!
}; };

View file

@ -39,13 +39,21 @@
#include "nsHTMLWin32ObjectAccessible.h" #include "nsHTMLWin32ObjectAccessible.h"
#include "nsAccessibleWrap.h" #include "nsAccessibleWrap.h"
////////////////////////////////////////////////////////////////////////////////
// nsHTMLWin32ObjectOwnerAccessible
////////////////////////////////////////////////////////////////////////////////
nsHTMLWin32ObjectOwnerAccessible::nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell, void* aHwnd): nsHTMLWin32ObjectOwnerAccessible::
nsAccessibleWrap(aNode, aShell) nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell,
void* aHwnd) :
nsAccessibleWrap(aNode, aShell)
{ {
mHwnd = aHwnd; mHwnd = aHwnd;
} }
////////////////////////////////////////////////////////////////////////////////
// nsHTMLWin32ObjectOwnerAccessible: nsAccessNode implementation
nsresult nsresult
nsHTMLWin32ObjectOwnerAccessible::Shutdown() nsHTMLWin32ObjectOwnerAccessible::Shutdown()
{ {
@ -54,37 +62,83 @@ nsHTMLWin32ObjectOwnerAccessible::Shutdown()
return NS_OK; return NS_OK;
} }
/** ////////////////////////////////////////////////////////////////////////////////
* Our only child is a nsHTMLWin32ObjectAccessible // nsHTMLWin32ObjectOwnerAccessible: nsIAccessible implementation
*/
NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetFirstChild(nsIAccessible **aFirstChild) NS_IMETHODIMP
nsHTMLWin32ObjectOwnerAccessible::GetFirstChild(nsIAccessible **aFirstChild)
{ {
*aFirstChild = mNativeAccessible; NS_ENSURE_ARG_POINTER(aFirstChild);
*aFirstChild = nsnull;
// Our only child is a nsHTMLWin32ObjectAccessible object.
if (!mNativeAccessible) { if (!mNativeAccessible) {
if (!mHwnd) { if (!mHwnd)
return NS_OK; return NS_OK;
}
mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd) ; mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd);
NS_ENSURE_TRUE(mNativeAccessible, NS_ERROR_OUT_OF_MEMORY);
SetFirstChild(mNativeAccessible); SetFirstChild(mNativeAccessible);
*aFirstChild = mNativeAccessible;
} }
*aFirstChild = mNativeAccessible;
NS_IF_ADDREF(*aFirstChild); NS_IF_ADDREF(*aFirstChild);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetLastChild(nsIAccessible **aLastChild) NS_IMETHODIMP
nsHTMLWin32ObjectOwnerAccessible::GetLastChild(nsIAccessible **aLastChild)
{ {
return GetFirstChild(aLastChild); return GetFirstChild(aLastChild);
} }
NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetChildCount(PRInt32 *aChildCount) NS_IMETHODIMP
nsHTMLWin32ObjectOwnerAccessible::GetChildCount(PRInt32 *aChildCount)
{ {
NS_ENSURE_ARG_POINTER(aChildCount);
nsCOMPtr<nsIAccessible> onlyChild; nsCOMPtr<nsIAccessible> onlyChild;
GetFirstChild(getter_AddRefs(onlyChild)); GetFirstChild(getter_AddRefs(onlyChild));
*aChildCount = onlyChild ? 1 : 0; *aChildCount = onlyChild ? 1 : 0;
return NS_OK; return NS_OK;
} }
////////////////////////////////////////////////////////////////////////////////
// nsHTMLWin32ObjectOwnerAccessible: nsAccessible implementation
nsresult
nsHTMLWin32ObjectOwnerAccessible::GetRoleInternal(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = nsIAccessibleRole::ROLE_EMBEDDED_OBJECT;
return NS_OK;
}
nsresult
nsHTMLWin32ObjectOwnerAccessible::GetStateInternal(PRUint32 *aState,
PRUint32 *aExtraState)
{
nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
if (rv == NS_OK_DEFUNCT_OBJECT)
return rv;
// XXX: No HWND means this is windowless plugin which is not accessible in
// the meantime.
if (!mHwnd)
*aState = nsIAccessibleStates::STATE_UNAVAILABLE;
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLWin32ObjectAccessible
////////////////////////////////////////////////////////////////////////////////
nsHTMLWin32ObjectAccessible::nsHTMLWin32ObjectAccessible(void* aHwnd): nsHTMLWin32ObjectAccessible::nsHTMLWin32ObjectAccessible(void* aHwnd):
nsLeafAccessible(nsnull, nsnull) nsLeafAccessible(nsnull, nsnull)
{ {

View file

@ -64,6 +64,10 @@ public:
// nsAccessNode // nsAccessNode
virtual nsresult Shutdown(); virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
protected: protected:
void* mHwnd; void* mHwnd;
nsCOMPtr<nsIAccessible> mNativeAccessible; nsCOMPtr<nsIAccessible> mNativeAccessible;

View file

@ -440,6 +440,9 @@ static const WindowsRoleMapItem gWindowsRoleMap[] = {
// nsIAccessibleRole::ROLE_GRID_CELL // nsIAccessibleRole::ROLE_GRID_CELL
{ ROLE_SYSTEM_CELL, ROLE_SYSTEM_CELL }, { ROLE_SYSTEM_CELL, ROLE_SYSTEM_CELL },
// nsIAccessibleRole::ROLE_EMBEDDED_OBJECT
{ USE_ROLE_STRING, IA2_ROLE_EMBEDDED_OBJECT },
// nsIAccessibleRole::ROLE_LAST_ENTRY // nsIAccessibleRole::ROLE_LAST_ENTRY
{ ROLE_WINDOWS_LAST_ENTRY, ROLE_WINDOWS_LAST_ENTRY } { ROLE_WINDOWS_LAST_ENTRY, ROLE_WINDOWS_LAST_ENTRY }
}; };

View file

@ -89,6 +89,7 @@ _TEST_FILES =\
test_elm_filectrl.html \ test_elm_filectrl.html \
test_elm_listbox.xul \ test_elm_listbox.xul \
$(warning test_elm_media.html temporarily disabled) \ $(warning test_elm_media.html temporarily disabled) \
test_elm_plugin.html \
test_elm_tree.xul \ test_elm_tree.xul \
test_elm_txtcntnr.html \ test_elm_txtcntnr.html \
test_events_caretmove.html \ test_events_caretmove.html \
@ -159,6 +160,7 @@ _TEST_FILES =\
test_textattrs.html \ test_textattrs.html \
test_textboxes.html \ test_textboxes.html \
test_textboxes.xul \ test_textboxes.xul \
test_value.html \
test_value.xul \ test_value.xul \
testTextboxes.js \ testTextboxes.js \
treeview.css \ treeview.css \

View file

@ -12,6 +12,7 @@ const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION; const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER; const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT; const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY; const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION; const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
const ROLE_FORM = nsIAccessibleRole.ROLE_FORM; const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;

View file

@ -94,10 +94,12 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
} }
// unavailable // unavailable
if ((state & STATE_UNAVAILABLE) if (state & STATE_UNAVAILABLE) {
&& (getRole(aAccOrElmOrID) != ROLE_GROUPING)) var role = getRole(aAccOrElmOrID);
isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false, if (role != ROLE_GROUPING && role != ROLE_EMBEDDED_OBJECT)
"Disabled " + id + " must be focusable!"); isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
"Disabled " + id + " must be focusable!");
}
} }
/** /**

View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugin tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js"></script>
<script type="application/javascript">
function doTest()
{
if (!WIN) {
ok(true,
"Nothing to test because accessible plugins are supported on Windows only");
SimpleTest.finish();
return;
}
testRole("plugin", ROLE_EMBEDDED_OBJECT);
testStates("plugin", STATE_UNAVAILABLE);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="embed and object HTML tags should be given an accessible role of embedded object"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=485270">Mozilla Bug 485270</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<embed id="plugin" type="application/x-test" width="300" height="300"></embed>
</body>
</html>

View file

@ -49,6 +49,12 @@
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree"); testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree"); testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4"); testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4");
testRelation("treeitem6", RELATION_NODE_CHILD_OF, "treeitem5");
// 'node child of' relation for row role of treegrid
testRelation("treegridrow1", RELATION_NODE_CHILD_OF, "treegrid");
testRelation("treegridrow2", RELATION_NODE_CHILD_OF, "treegrid");
testRelation("treegridrow3", RELATION_NODE_CHILD_OF, "treegridrow2");
// 'node child of' relation for the document having window, returns // 'node child of' relation for the document having window, returns
// direct accessible parent (fixed in bug 419770). // direct accessible parent (fixed in bug 419770).
@ -147,6 +153,21 @@
<div role="treeitem" id="treeitem3">Blue</div> <div role="treeitem" id="treeitem3">Blue</div>
<div role="treeitem" id="treeitem4" aria-level="1">Green</div> <div role="treeitem" id="treeitem4" aria-level="1">Green</div>
<div role="treeitem" id="treeitem5" aria-level="2">Light green</div> <div role="treeitem" id="treeitem5" aria-level="2">Light green</div>
<div role="group">
<div role="treeitem" id="treeitem6">Super light green</div>
</div>
</div>
<div role="treegrid" id="treegrid">
<div role="row" id="treegridrow1">
<span role="gridcell">cell1</span><span role="gridcell">cell2</span>
</div>
<div role="row" id="treegridrow2" aria-level="1">
<span role="gridcell">cell3</span><span role="gridcell">cell4</span>
</div>
<div role="row" id="treegridrow3" aria-level="2">
<span role="gridcell">cell5</span><span role="gridcell">cell6</span>
</div>
</div> </div>
<iframe id="iframe"></iframe> <iframe id="iframe"></iframe>

View file

@ -69,6 +69,30 @@
// offscreen test // offscreen test
testStates("aria_offscreen_textbox", STATE_OFFSCREEN); testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
//
// This section tests aria roles on links/anchors for underlying
// nsHTMLLinkAccessible creation. (see closed bug 494807)
//
// strong roles
testStates("aria_menuitem_link", 0, 0, STATE_LINKED);
testStates("aria_button_link", 0, 0, STATE_LINKED);
testStates("aria_checkbox_link", 0, 0, STATE_LINKED);
// strong landmark
testStates("aria_application_link", 0, 0, STATE_LINKED);
testStates("aria_application_anchor", 0, 0, STATE_SELECTABLE);
// strange cases
testStates("aria_link_link", STATE_LINKED);
testStates("aria_link_anchor", STATE_SELECTABLE);
// some weak landmarks
testStates("aria_main_link", STATE_LINKED);
testStates("aria_navigation_link", STATE_LINKED);
testStates("aria_main_anchor", STATE_SELECTABLE);
testStates("aria_navigation_anchor", STATE_SELECTABLE);
SimpleTest.finish(); SimpleTest.finish();
} }
@ -140,5 +164,24 @@
<div id="offscreen_log" role="log" class="offscreen"> <div id="offscreen_log" role="log" class="offscreen">
<div id="aria_offscreen_textbox" role="textbox" aria-readonly="true">This text should be offscreen</div> <div id="aria_offscreen_textbox" role="textbox" aria-readonly="true">This text should be offscreen</div>
</div> </div>
<a id="aria_menuitem_link" role="menuitem" href="foo">menuitem</a>
<a id="aria_button_link" role="button" href="foo">button</a>
<a id="aria_checkbox_link" role="checkbox" href="foo">checkbox</a>
<!-- strange edge case: please don't do this in the wild -->
<a id="aria_link_link" role="link" href="foo">link</a>
<a id="aria_link_anchor" role="link" name="link_anchor">link</a>
<!-- landmarks: links -->
<a id="aria_application_link" role="application" href="foo">app</a>
<a id="aria_main_link" role="main" href="foo">main</a>
<a id="aria_navigation_link" role="navigation" href="foo">nav</a>
<!-- landmarks: anchors -->
<a id="aria_application_anchor" role="application" name="app_anchor">app</a>
<a id="aria_main_anchor" role="main" name="main_anchor">main</a>
<a id="aria_navigation_anchor" role="navigation" name="nav_anchor">nav</a>
</body> </body>
</html> </html>

View file

@ -22,6 +22,9 @@
function doTest() function doTest()
{ {
//////////////////////////////////////////////////////////////////////////
// table
var cellsArray = var cellsArray =
[ [
[false, false, false, kColSpanned, false, false, false, false], [false, false, false, kColSpanned, false, false, false, false],
@ -53,6 +56,20 @@
var accTable = getAccessible("table", [nsIAccessibleTable]); var accTable = getAccessible("table", [nsIAccessibleTable]);
ok(!accTable.isProbablyForLayout(), "table is not for layout"); ok(!accTable.isProbablyForLayout(), "table is not for layout");
//////////////////////////////////////////////////////////////////////////
// table instane
cellsArray =
[
[false, false, false, -1, -1],
[false, false, false, -1, -1],
[false, false, kColSpanned, kColSpanned, -1],
[kRowSpanned, false, false, -1, -1],
[kRowSpanned, false, kRowSpanned, false, false]
];
testTableSelection("tableinsane", cellsArray);
SimpleTest.finish(); SimpleTest.finish();
} }
@ -77,6 +94,11 @@
title="nsIAccessiblTable selectRows does not unselect previously selected rows"> title="nsIAccessiblTable selectRows does not unselect previously selected rows">
Mozilla Bug 417929 Mozilla Bug 417929
</a> </a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=501659"
title="HTML table's isRowSelected/isColumnSelected shouldn't fail if row or column has cell holes">
Mozilla Bug 501659
</a>
<p id="display"></p> <p id="display"></p>
<div id="content" style="display: none"></div> <div id="content" style="display: none"></div>
@ -122,6 +144,37 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table border="1" id="tableinsane">
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td rowspan="3">4</td>
<td colspan="4">5</td>
</tr>
<tr>
<td>6</td>
<td rowspan="2">7</td>
</tr>
<tr>
<td>8</td>
<td>9</td>
<td>10</td>
</tr>
</tbody>
</table>
</center> </center>
</body> </body>
</html> </html>

View file

@ -0,0 +1,81 @@
<html>
<head>
<title>nsIAccessible value testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<style type="text/css">
.offscreen {
position: absolute;
left: -5000px;
top: -5000px;
height: 100px;
width: 100px;
}
</style>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript">
function doTest()
{
function testValue(aID, aValue)
{
var acc = getAccessible(aID);
if (!acc)
return;
is(acc.value, aValue, "Wrong value for " + aID + "!");
}
var href = "chrome://mochikit/content/a11y/accessible/foo";
// roles that can't live as nsHTMLLinkAccessibles
testValue("aria_menuitem_link", "");
testValue("aria_button_link", "");
testValue("aria_checkbox_link", "");
testValue("aria_application_link", "");
// roles that can live as nsHTMLLinkAccessibles
testValue("aria_link_link", href);
testValue("aria_main_link", href);
testValue("aria_navigation_link", href);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=494807"
title="Do not expose a11y info specific to hyperlinks when role is overridden using ARIA">
Mozilla Bug 494807
</a><br />
<a id="aria_menuitem_link" role="menuitem" href="foo">menuitem</a>
<a id="aria_button_link" role="button" href="foo">button</a>
<a id="aria_checkbox_link" role="checkbox" href="foo">checkbox</a>
<!-- landmark links -->
<a id="aria_application_link" role="application" href="foo">app</a>
<a id="aria_main_link" role="main" href="foo">main</a>
<a id="aria_navigation_link" role="navigation" href="foo">nav</a>
<!-- strange edge case: please don't do this in the wild -->
<a id="aria_link_link" role="link" href="foo">link</a>
</body>
</html>

View file

@ -298,9 +298,6 @@ libs::
endif endif
endif endif
libs::
touch $(DIST)/bin/.autoreg
libs:: $(srcdir)/profile/prefs.js libs:: $(srcdir)/profile/prefs.js
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile $(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile

View file

@ -338,7 +338,6 @@ pref("browser.tabs.warnOnClose", true);
pref("browser.tabs.warnOnOpen", true); pref("browser.tabs.warnOnOpen", true);
pref("browser.tabs.maxOpenBeforeWarn", 15); pref("browser.tabs.maxOpenBeforeWarn", 15);
pref("browser.tabs.loadInBackground", true); pref("browser.tabs.loadInBackground", true);
pref("browser.tabs.loadFolderAndReplace", true);
pref("browser.tabs.opentabfor.middleclick", true); pref("browser.tabs.opentabfor.middleclick", true);
pref("browser.tabs.loadDivertedInBackground", false); pref("browser.tabs.loadDivertedInBackground", false);
pref("browser.tabs.loadBookmarksInBackground", false); pref("browser.tabs.loadBookmarksInBackground", false);

View file

@ -134,6 +134,43 @@ td {
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
// We use a preferences whitelist to make sure we only show preferences that
// are useful for support and won't compromise the user's privacy. Note that
// entries are *prefixes*: for example, "accessibility." applies to all prefs
// under the "accessibility.*" branch.
const Whitelist = [
"accessibility.",
"browser.fixup.",
"browser.history_expire_",
"browser.link.open_newwindow",
"browser.mousewheel.",
"browser.places.",
"browser.startup.homepage",
"browser.tabs.",
"browser.zoom.",
"dom.",
"extensions.checkCompatibility",
"extensions.lastAppVersion",
"font.",
"general.useragent.",
"gfx.color_management.mode",
"javascript.",
"keyword.",
"layout.css.dpi",
"network.",
"places.",
"print.",
"privacy.",
"security."
];
// The blacklist, unlike the whitelist, is a list of regular expressions.
const Blacklist = [
/^print[.]print_to_filename$/,
/^print[.].*[.]print_to_filename$/,
/^network[.]proxy[.].*$/
];
window.onload = function () { window.onload = function () {
// Get the FUEL Application object. // Get the FUEL Application object.
let Application = Cc["@mozilla.org/fuel/application;1"] let Application = Cc["@mozilla.org/fuel/application;1"]
@ -144,16 +181,9 @@ window.onload = function () {
.getService(Ci.nsIURLFormatter); .getService(Ci.nsIURLFormatter);
let supportUrl = urlFormatter.formatURLPref("app.support.baseURL"); let supportUrl = urlFormatter.formatURLPref("app.support.baseURL");
// Get the profile directory.
let propertiesService = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
let currProfD = propertiesService.get("ProfD", Ci.nsIFile);
let profileDir = currProfD.path;
// Update the application basics section. // Update the application basics section.
document.getElementById("application-box").textContent = Application.name; document.getElementById("application-box").textContent = Application.name;
document.getElementById("version-box").textContent = Application.version; document.getElementById("version-box").textContent = Application.version;
document.getElementById("profile-box").textContent = profileDir;
document.getElementById("supportLink").href = supportUrl; document.getElementById("supportLink").href = supportUrl;
// Update the other sections. // Update the other sections.
@ -193,7 +223,7 @@ function populatePreferencesSection() {
let trPrefs = []; let trPrefs = [];
for each (let pref in sortedPrefs) { for each (let pref in sortedPrefs) {
let tdName = createElement("td", pref.name, "pref-name"); let tdName = createElement("td", pref.name, "pref-name");
let tdValue = createElement("td", pref.value, "pref-value"); let tdValue = createElement("td", formatPrefValue(pref.value), "pref-value");
let tr = createParentElement("tr", [tdName, tdValue]); let tr = createParentElement("tr", [tdName, tdValue]);
trPrefs.push(tr); trPrefs.push(tr);
} }
@ -201,6 +231,18 @@ function populatePreferencesSection() {
appendChildren(document.getElementById("prefs-tbody"), trPrefs); appendChildren(document.getElementById("prefs-tbody"), trPrefs);
} }
function formatPrefValue(prefValue) {
// Some pref values are really long and don't have spaces. This can cause
// problems when copying and pasting into some WYSIWYG editors. In general
// the exact contents of really long pref values aren't particularly useful,
// so we truncate them to some reasonable length.
let maxPrefValueLen = 120;
let text = "" + prefValue;
if (text.length > maxPrefValueLen)
text = text.substring(0, maxPrefValueLen) + "…";
return text;
}
function getModifiedPrefs() { function getModifiedPrefs() {
// We use the low-level prefs API to identify prefs that have been // We use the low-level prefs API to identify prefs that have been
// modified, rather that Application.prefs.all since the latter is // modified, rather that Application.prefs.all since the latter is
@ -209,13 +251,27 @@ function getModifiedPrefs() {
let prefService = Cc["@mozilla.org/preferences-service;1"] let prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService); .getService(Ci.nsIPrefService);
let prefRootBranch = prefService.getBranch(""); let prefRootBranch = prefService.getBranch("");
let prefNames = prefRootBranch.getChildList("", { value: 0 }); let prefNames = getWhitelistedPrefNames(prefRootBranch);
let prefs = [Application.prefs.get(prefName) let prefs = [Application.prefs.get(prefName)
for each (prefName in prefNames) for each (prefName in prefNames)
if (prefRootBranch.prefHasUserValue(prefName))]; if (prefRootBranch.prefHasUserValue(prefName)
&& !isBlacklisted(prefName))];
return prefs; return prefs;
} }
function getWhitelistedPrefNames(prefRootBranch) {
let results = [];
for each (let prefStem in Whitelist) {
let prefNames = prefRootBranch.getChildList(prefStem, {});
results = results.concat(prefNames);
}
return results;
}
function isBlacklisted(prefName) {
return Blacklist.some(function (re) {return re.test(prefName);});
}
function createParentElement(tagName, childElems) { function createParentElement(tagName, childElems) {
let elem = document.createElement(tagName); let elem = document.createElement(tagName);
appendChildren(elem, childElems); appendChildren(elem, childElems);
@ -275,7 +331,10 @@ function createTextForElement(elem) {
// Trim extraneous whitespace before newlines, then squash extraneous // Trim extraneous whitespace before newlines, then squash extraneous
// blank lines. // blank lines.
text = text.replace(/[ \t]+\n/g, "\n"); text = text.replace(/[ \t]+\n/g, "\n");
text = text.replace(/\n\n\n*/g, "\n\n"); text = text.replace(/\n\n\n+/g, "\n\n");
// Actual CR/LF pairs are needed for some Windows text editors.
text = text.replace(/\n/g, "\r\n");
return text; return text;
} }
@ -316,6 +375,19 @@ function generateTextForTextNode(node, indent, textFragmentAccumulator) {
textFragmentAccumulator.push(text); textFragmentAccumulator.push(text);
} }
function openProfileDirectory() {
// Get the profile directory.
let propertiesService = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
let currProfD = propertiesService.get("ProfD", Ci.nsIFile);
let profileDir = currProfD.path;
// Show the profile directory.
let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1",
"nsILocalFile", "initWithPath");
new nsLocalFile(profileDir).reveal();
}
]]></script> ]]></script>
</head> </head>
@ -369,10 +441,17 @@ function generateTextForTextNode(node, indent, textFragmentAccumulator) {
&aboutSupport.appBasicsProfileDir; &aboutSupport.appBasicsProfileDir;
</th> </th>
<td id="profile-box"> <td>
<button onclick="openProfileDirectory()">
#ifdef XP_MACOSX
&aboutSupport.showMac.label;
#else
&aboutSupport.show.label;
#endif
</button>
</td> </td>
</tr> </tr>
<tr> <tr>
<th class="column"> <th class="column">
&aboutSupport.appBasicsPlugins; &aboutSupport.appBasicsPlugins;

View file

@ -220,8 +220,13 @@ function SetClickAndHoldHandlers() {
if (aEvent.button == 0 && if (aEvent.button == 0 &&
aEvent.target == aEvent.currentTarget && aEvent.target == aEvent.currentTarget &&
!aEvent.currentTarget.open && !aEvent.currentTarget.open &&
!aEvent.currentTarget.disabled) !aEvent.currentTarget.disabled) {
aEvent.currentTarget.doCommand(); let cmdEvent = document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, window, 0,
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
aEvent.metaKey, null);
aEvent.currentTarget.dispatchEvent(cmdEvent);
}
} }
function stopTimer(aEvent) { function stopTimer(aEvent) {
@ -786,13 +791,14 @@ let gGestureSupport = {
_power: function GS__power(aArray) { _power: function GS__power(aArray) {
// Create a bitmask based on the length of the array // Create a bitmask based on the length of the array
let num = 1 << aArray.length; let num = 1 << aArray.length;
while (--num >= 0) while (--num >= 0) {
// Only select array elements where the current bit is set // Only select array elements where the current bit is set
yield aArray.reduce(function(aPrev, aCurr, aIndex) { yield aArray.reduce(function (aPrev, aCurr, aIndex) {
if (num & 1 << aIndex) if (num & 1 << aIndex)
aPrev.push(aCurr); aPrev.push(aCurr);
return aPrev; return aPrev;
}, []); }, []);
}
}, },
/** /**
@ -807,47 +813,44 @@ let gGestureSupport = {
* command is found, no value is returned (undefined). * command is found, no value is returned (undefined).
*/ */
_doAction: function GS__doAction(aEvent, aGesture) { _doAction: function GS__doAction(aEvent, aGesture) {
// Create a fake event that pretends the gesture is a button click
let fakeEvent = { shiftKey: aEvent.shiftKey, ctrlKey: aEvent.ctrlKey,
metaKey: aEvent.metaKey, altKey: aEvent.altKey, button: 0 };
// Create an array of pressed keys in a fixed order so that a command for // Create an array of pressed keys in a fixed order so that a command for
// "meta" is preferred over "ctrl" when both buttons are pressed (and a // "meta" is preferred over "ctrl" when both buttons are pressed (and a
// command for both don't exist) // command for both don't exist)
let keyCombos = []; let keyCombos = [];
const keys = ["shift", "alt", "ctrl", "meta"]; ["shift", "alt", "ctrl", "meta"].forEach(function (key) {
for each (let key in keys)
if (aEvent[key + "Key"]) if (aEvent[key + "Key"])
keyCombos.push(key); keyCombos.push(key);
});
try { // Try each combination of key presses in decreasing order for commands
// Try each combination of key presses in decreasing order for commands for each (let subCombo in this._power(keyCombos)) {
for (let subCombo in this._power(keyCombos)) { // Convert a gesture and pressed keys into the corresponding command
// Convert a gesture and pressed keys into the corresponding command // action where the preference has the gesture before "shift" before
// action where the preference has the gesture before "shift" before // "alt" before "ctrl" before "meta" all separated by periods
// "alt" before "ctrl" before "meta" all separated by periods let command;
let command = this._getPref(aGesture.concat(subCombo).join(".")); try {
command = this._getPref(aGesture.concat(subCombo).join("."));
} catch (e) {}
// Do the command if we found one to do if (!command)
if (command) { continue;
let node = document.getElementById(command);
// Use the command element if it exists
if (node && node.hasAttribute("oncommand")) {
// XXX: Use node.oncommand(event) once bug 246720 is fixed
if (node.getAttribute("disabled") != "true")
new Function("event", node.getAttribute("oncommand")).
call(node, fakeEvent);
}
// Otherwise it should be a "standard" command
else
goDoCommand(command);
return command; let node = document.getElementById(command);
if (node) {
if (node.getAttribute("disabled") != "true") {
let cmdEvent = document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, window, 0,
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
aEvent.metaKey, null);
node.dispatchEvent(cmdEvent);
} }
} else {
goDoCommand(command);
} }
return command;
} }
// The generator ran out of key combinations, so just do nothing return null;
catch (e) {}
}, },
/** /**

View file

@ -289,7 +289,7 @@
<image id="thepreviewimage"/> <image id="thepreviewimage"/>
</hbox> </hbox>
<hbox id="brokenimagecontainer" pack="center" collapsed="true"> <hbox id="brokenimagecontainer" pack="center" collapsed="true">
<image id="brokenimage" src="resource:///res/broken-image.png"/> <image id="brokenimage" src="resource://gre-resources/broken-image.png"/>
</hbox> </hbox>
</vbox> </vbox>
</vbox> </vbox>

View file

@ -525,7 +525,7 @@
if (aWebProgress.DOMWindow == this.mBrowser.contentWindow && if (aWebProgress.DOMWindow == this.mBrowser.contentWindow &&
aWebProgress.isLoadingDocument) aWebProgress.isLoadingDocument)
this.mTabBrowser.setIcon(this.mTab, null); this.mTabBrowser.getBrowserForTab(this.mTab).mIconURL = null;
// changing location, clear out the missing plugins list // changing location, clear out the missing plugins list
this.mBrowser.missingPlugins = null; this.mBrowser.missingPlugins = null;
@ -1266,7 +1266,7 @@
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"tab"); "tab");
var blank = (aURI == "about:blank"); var blank = !aURI || (aURI == "about:blank");
if (blank) if (blank)
t.setAttribute("label", this.mStringBundle.getString("tabs.untitled")); t.setAttribute("label", this.mStringBundle.getString("tabs.untitled"));
@ -2865,14 +2865,6 @@
return document.getBindingParent(this).childNodes; return document.getBindingParent(this).childNodes;
]]></body> ]]></body>
</method> </method>
#ifdef XP_MACOSX
<field name="_scrollButtonDownBox">
document.getAnonymousElementByAttribute(this, "anonid", "down-box");
</field>
<field name="_scrollButtonDownBoxAnimate">
document.getAnonymousElementByAttribute(this, "anonid", "down-box-animate");
</field>
#endif
</implementation> </implementation>
<handlers> <handlers>
@ -2882,10 +2874,6 @@
var tabs = document.getBindingParent(this); var tabs = document.getBindingParent(this);
tabs.removeAttribute("overflow"); tabs.removeAttribute("overflow");
#ifdef XP_MACOSX
this._scrollButtonDownBox.collapsed = true;
this._scrollButtonDownBoxAnimate.collapsed = true;
#endif
]]></handler> ]]></handler>
<handler event="overflow"><![CDATA[ <handler event="overflow"><![CDATA[
if (event.detail == 0) if (event.detail == 0)
@ -2893,59 +2881,9 @@
var tabs = document.getBindingParent(this); var tabs = document.getBindingParent(this);
tabs.setAttribute("overflow", "true"); tabs.setAttribute("overflow", "true");
#ifdef XP_MACOSX
this._scrollButtonDownBox.collapsed = false;
this._scrollButtonDownBoxAnimate.collapsed = false;
#endif
this.ensureElementIsVisible(tabs.selectedItem, false); this.ensureElementIsVisible(tabs.selectedItem, false);
]]></handler> ]]></handler>
#ifdef XP_MACOSX
<handler event="UpdatedScrollButtonsDisabledState"><![CDATA[
// fix for bug #352353
// unlike the scrollup button on the tab strip (which is a
// simple toolbarbutton) the scrolldown button is
// a more complicated stack of boxes and a toolbarbutton
// so that we can animate when a tab is opened offscreen.
// in order to style the box with the actual background image
// we need to manually set the disable state to match the
// disable state of the toolbarbutton.
this._scrollButtonDownBox
.setAttribute("disabled", this._scrollButtonDown.disabled);
]]></handler>
#endif
</handlers> </handlers>
#ifdef XP_MACOSX
<content>
<xul:toolbarbutton class="scrollbutton-up" collapsed="true"
xbl:inherits="orient"
anonid="scrollbutton-up"
onclick="_distanceScroll(event);"
onmousedown="_startScroll(-1);"
onmouseover="_continueScroll(-1);"
onmouseup="_stopScroll();"
onmouseout="_pauseScroll();"/>
<xul:scrollbox xbl:inherits="orient,align,pack,dir" flex="1" anonid="scrollbox">
<children/>
</xul:scrollbox>
<xul:stack align="center" pack="end" class="scrollbutton-down-stack">
<xul:hbox flex="1" class="scrollbutton-down-box"
collapsed="true" anonid="down-box"/>
<xul:hbox flex="1" class="scrollbutton-down-box-animate"
collapsed="true" anonid="down-box-animate"/>
<xul:toolbarbutton class="scrollbutton-down" collapsed="true"
xbl:inherits="orient"
anonid="scrollbutton-down"
onclick="_distanceScroll(event);"
onmousedown="_startScroll(1);"
onmouseover="_continueScroll(1);"
onmouseup="_stopScroll();"
onmouseout="_pauseScroll();"/>
</xul:stack>
</content>
#endif
</binding> </binding>
<binding id="tabbrowser-tabs" <binding id="tabbrowser-tabs"
@ -2981,15 +2919,12 @@
<xul:toolbarbutton class="tabs-newtab-button" anonid="newtab-button" <xul:toolbarbutton class="tabs-newtab-button" anonid="newtab-button"
command="cmd_newNavigatorTab" command="cmd_newNavigatorTab"
tooltiptext="&newTabButton.tooltip;"/> tooltiptext="&newTabButton.tooltip;"/>
<xul:stack align="center" pack="end"> <xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button"
<xul:hbox flex="1" class="tabs-alltabs-box-animate" anonid="alltabs-box-animate"/> type="menu"
<xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button" tooltiptext="&listAllTabs.label;">
type="menu" <xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup"
tooltiptext="&listAllTabs.label;"> position="after_end"/>
<xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup" </xul:toolbarbutton>
position="after_end"/>
</xul:toolbarbutton>
</xul:stack>
<xul:toolbarbutton anonid="tabs-closebutton" <xul:toolbarbutton anonid="tabs-closebutton"
class="close-button tabs-closebutton"/> class="close-button tabs-closebutton"/>
</xul:hbox> </xul:hbox>
@ -3168,19 +3103,13 @@
"anonid", "alltabs-popup"); "anonid", "alltabs-popup");
</field> </field>
<field name="mAllTabsBoxAnimate"> <field name="_animateElement">
document.getAnonymousElementByAttribute(this, this.mTabstrip._scrollButtonDown;
"anonid",
"alltabs-box-animate");
</field> </field>
#ifdef XP_MACOSX
<field name="mDownBoxAnimate">
this.mTabstrip._scrollButtonDownBoxAnimate;
</field>
#endif
<field name="_animateTimer">null</field> <field name="_animateTimer">null</field>
<field name="_animateBaseOpacity">null</field>
<field name="_animateBaseColor">null</field>
<field name="_animateStep">-1</field> <field name="_animateStep">-1</field>
<field name="_animateDelay">25</field> <field name="_animateDelay">25</field>
<field name="_animatePercents"> <field name="_animatePercents">
@ -3199,10 +3128,8 @@
this._animateTimer.cancel(); this._animateTimer.cancel();
this._animateStep = -1; this._animateStep = -1;
this.mAllTabsBoxAnimate.style.opacity = 0.0; this._animateElement.style.outlineColor = "";
#ifdef XP_MACOSX this._animateElement.style.outlineStyle = "";
this.mDownBoxAnimate.style.opacity = 0.0;
#endif
} }
]]></body> ]]></body>
</method> </method>
@ -3232,32 +3159,49 @@
selected.left - scrollRect.left); selected.left - scrollRect.left);
} }
this._stopAnimation();
const DEFAULT_OPACITY = .7;
var self = this;
this._animateBaseColor =
window.getComputedStyle(this._animateElement, null)
.outlineColor
.replace(/^rgb\((.*)\)$/, "rgba($1, " + DEFAULT_OPACITY + ")")
.replace(/([^, ]*)\)/, function (m0, m1) {
self._animateBaseOpacity = parseFloat(m1);
return "$opacity)";
});
// start the flash timer // start the flash timer
this._animateStep = 0; this._animateStep = 0;
var outlineWidth =
Math.ceil(Math.min(this._animateElement.clientHeight,
this._animateElement.clientWidth) * .6) + "px";
this._animateElement.style.outlineWidth = outlineWidth;
this._animateElement.style.outlineOffset = "-" + outlineWidth;
this._animateElement.style.outlineColor = "rgba(0,0,0,0)";
this._animateElement.style.outlineStyle = "solid";
if (!this._animateTimer) if (!this._animateTimer)
this._animateTimer = this._animateTimer =
Components.classes["@mozilla.org/timer;1"] Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer); .createInstance(Components.interfaces.nsITimer);
else
this._animateTimer.cancel();
this._animateTimer.initWithCallback(this, this._animateDelay, this._animateTimer.initWithCallback(this, this._animateDelay,
this._animateTimer.TYPE_REPEATING_SLACK); this._animateTimer.TYPE_REPEATING_SLACK);
]]></body> ]]></body>
</method> </method>
<method name="notify"> <method name="notify">
<parameter name="aTimer"/> <parameter name="aTimer"/>
<body><![CDATA[ <body><![CDATA[
if (!document) if (!document)
aTimer.cancel(); aTimer.cancel();
var percent = this._animatePercents[this._animateStep]; var opacity = this._animateBaseOpacity * this._animatePercents[this._animateStep];
this.mAllTabsBoxAnimate.style.opacity = percent; this._animateElement.style.outlineColor =
#ifdef XP_MACOSX this._animateBaseColor.replace("$opacity", opacity);
this.mDownBoxAnimate.style.opacity = percent;
#endif
if (this._animateStep < (this._animatePercents.length - 1)) if (this._animateStep < (this._animatePercents.length - 1))
this._animateStep++; this._animateStep++;
@ -3527,14 +3471,9 @@
var tabs = tabcontainer.childNodes; var tabs = tabcontainer.childNodes;
// Listen for changes in the tab bar. // Listen for changes in the tab bar.
var tabbrowser = document.getBindingParent(tabcontainer); tabcontainer.addEventListener("TabOpen", this, false);
tabbrowser.addEventListener("TabOpen", this, false);
tabcontainer.mTabstrip.addEventListener("scroll", this, false); tabcontainer.mTabstrip.addEventListener("scroll", this, false);
// if an animation is in progress and the user
// clicks on the "all tabs" button, stop the animation
tabcontainer._stopAnimation();
for (var i = 0; i < tabs.length; i++) { for (var i = 0; i < tabs.length; i++) {
this._createTabMenuItem(tabs[i]); this._createTabMenuItem(tabs[i]);
} }
@ -3554,7 +3493,7 @@
} }
var tabcontainer = document.getBindingParent(this); var tabcontainer = document.getBindingParent(this);
tabcontainer.mTabstrip.removeEventListener("scroll", this, false); tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
document.getBindingParent(tabcontainer).removeEventListener("TabOpen", this, false); tabcontainer.removeEventListener("TabOpen", this, false);
]]></handler> ]]></handler>
<handler event="DOMMenuItemActive"> <handler event="DOMMenuItemActive">

View file

@ -2,8 +2,8 @@ var gTestPage = "http://example.org/browser/browser/base/content/test/dummy_page
var gTestImage = "http://example.org/browser/browser/base/content/test/moz.png"; var gTestImage = "http://example.org/browser/browser/base/content/test/moz.png";
var gTab1, gTab2, gTab3; var gTab1, gTab2, gTab3;
var gLevel; var gLevel;
const kBack = 0; const BACK = 0;
const kForward = 1; const FORWARD = 1;
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
@ -59,8 +59,8 @@ function imageLoaded() {
} }
function imageZoomSwitch() { function imageZoomSwitch() {
navigate(kBack, function() { navigate(BACK, function () {
navigate(kForward, function() { navigate(FORWARD, function () {
zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads"); zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
gBrowser.selectedTab = gTab2; gBrowser.selectedTab = gTab2;
zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected"); zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
@ -116,9 +116,9 @@ function testPrintPreview(aTab, aCallback) {
aCallback(); aCallback();
}; };
let printPreview = new Function(document.getElementById("cmd_printPreview") executeSoon(function () {
.getAttribute("oncommand")); document.getElementById("cmd_printPreview").doCommand();
executeSoon(printPreview); });
} }
function finishTest() { function finishTest() {
@ -145,12 +145,12 @@ function load(tab, url, cb) {
} }
function navigate(direction, cb) { function navigate(direction, cb) {
gBrowser.addEventListener("pageshow", function(event) { gBrowser.addEventListener("pageshow", function (event) {
gBrowser.removeEventListener("pageshow", arguments.callee, true); gBrowser.removeEventListener("pageshow", arguments.callee, true);
setTimeout(cb, 0); executeSoon(cb);
}, true); }, true);
if (direction == kBack) if (direction == BACK)
gBrowser.goBack(); gBrowser.goBack();
else if (direction == kForward) else if (direction == FORWARD)
gBrowser.goForward(); gBrowser.goForward();
} }

View file

@ -26,6 +26,7 @@ function continue_test_prefNotSet () {
} }
function end_test_prefNotSet() { function end_test_prefNotSet() {
tabElm.linkedBrowser.removeEventListener("load", end_test_prefNotSet, true);
is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted"); is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted");
// Reset the zoom so that other tests have a fresh zoom level // Reset the zoom so that other tests have a fresh zoom level

View file

@ -49,6 +49,7 @@ function test() {
gBrowser.selectedTab = gBrowser.addTab(); gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () { gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
setTimeout(function () { setTimeout(function () {
var testPageWin = content; var testPageWin = content;

View file

@ -46,6 +46,7 @@ let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
let currentInvoker = 0; let currentInvoker = 0;
function initTest() { function initTest() {
gBrowser.selectedBrowser.removeEventListener("load", initTest, true);
// first, bookmark the page // first, bookmark the page
Application.bookmarks.toolbar.addBookmark("Bug 432599 Test", makeURI(testURL)); Application.bookmarks.toolbar.addBookmark("Bug 432599 Test", makeURI(testURL));

View file

@ -3,6 +3,7 @@ function test() {
gBrowser.selectedTab = gBrowser.addTab(); gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () { gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
is(document.getElementById("identity-box").className, is(document.getElementById("identity-box").className,
gIdentityHandler.IDENTITY_MODE_MIXED_CONTENT, gIdentityHandler.IDENTITY_MODE_MIXED_CONTENT,
"identity box has class name for mixed content"); "identity box has class name for mixed content");

View file

@ -49,13 +49,11 @@ function test() {
// we get here if the test is executed before the pageshow // we get here if the test is executed before the pageshow
// event for the window's first tab // event for the window's first tab
if (!tabToDetach || if (!tabToDetach ||
tabToDetach.linkedBrowser.contentDocument != event.target) { tabToDetach.linkedBrowser.contentDocument != event.target)
return; return;
}
if (!newWindow) { if (!newWindow) {
var pageShowFunc = arguments.callee; gBrowser.removeEventListener("pageshow", onPageShow, false);
gBrowser.removeEventListener("pageshow", pageShowFunc, false);
// prepare the tab (set icon and busy state) // prepare the tab (set icon and busy state)
// we have to set these only after onState* notification, otherwise // we have to set these only after onState* notification, otherwise
@ -69,7 +67,7 @@ function test() {
// wait for gBrowser to come along // wait for gBrowser to come along
function onLoad(event) { function onLoad(event) {
newWindow.gBrowser newWindow.gBrowser
.addEventListener("pageshow", pageShowFunc, false); .addEventListener("pageshow", onPageShow, false);
newWindow.removeEventListener("load", arguments.callee, false); newWindow.removeEventListener("load", arguments.callee, false);
} }
newWindow.addEventListener("load", onLoad, false); newWindow.addEventListener("load", onLoad, false);

View file

@ -1,4 +1,4 @@
var expected = ["TabOpen", "onLinkIconAvailable", "onLocationChange", "onStateChange"]; var expected = ["TabOpen", "onLocationChange", "onStateChange", "onLinkIconAvailable"];
var actual = []; var actual = [];
var tabIndex = -1; var tabIndex = -1;
__defineGetter__("tab", function () gBrowser.tabContainer.childNodes[tabIndex]); __defineGetter__("tab", function () gBrowser.tabContainer.childNodes[tabIndex]);
@ -8,7 +8,7 @@ function test() {
tabIndex = gBrowser.tabContainer.childElementCount; tabIndex = gBrowser.tabContainer.childElementCount;
gBrowser.addTabsProgressListener(progressListener); gBrowser.addTabsProgressListener(progressListener);
gBrowser.tabContainer.addEventListener("TabOpen", TabOpen, false); gBrowser.tabContainer.addEventListener("TabOpen", TabOpen, false);
gBrowser.addTab("http://example.org/browser/browser/base/content/test/dummy_page.html"); gBrowser.addTab("data:text/html,<html><head><link href='about:logo' rel='shortcut icon'>");
} }
function record(aName) { function record(aName) {

View file

@ -1,19 +1,16 @@
var gBrowserHandler; var currentHandler;
var browser; var browser;
function doc() browser.contentDocument; function doc() browser.contentDocument;
function setHandlerFunc(aResultFunc) { function setHandlerFunc(aResultFunc) {
DOMLinkHandler.handleEvent = function (event) { if (currentHandler)
gBrowserHandler.call(DOMLinkHandler, event); gBrowser.removeEventListener("DOMLinkAdded", currentHandler, false);
aResultFunc(); gBrowser.addEventListener("DOMLinkAdded", aResultFunc, false);
} currentHandler = aResultFunc;
} }
function test() { function test() {
gBrowserHandler = DOMLinkHandler.handleEvent;
ok(gBrowserHandler, "found browser handler");
waitForExplicitFinish(); waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab(); gBrowser.selectedTab = gBrowser.addTab();
@ -120,10 +117,7 @@ function runMultipleEnginesTestAndFinalize() {
is(browser.engines[0].uri, "http://first.mozilla.com/search.xml", "first engine wins"); is(browser.engines[0].uri, "http://first.mozilla.com/search.xml", "first engine wins");
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
gBrowser.removeEventListener("DOMLinkAdded", currentHandler, false);
// Reset the default link handler
DOMLinkHandler.handleEvent = gBrowserHandler;
finish(); finish();
} }

View file

@ -1,20 +1,24 @@
var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
var pageInfo, obs, atTest = 0; var pageInfo, atTest = 0;
var gTestPage = gBrowser.addTab(); gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedTab = gTestPage; gBrowser.selectedBrowser.addEventListener("load", function () {
gTestPage.linkedBrowser.addEventListener("load", handleLoad, true); gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
pageInfo = BrowserPageInfo();
obs.addObserver(observer, "page-info-dialog-loaded", false);
}, true);
content.location = content.location =
"https://example.com/browser/browser/base/content/test/feed_tab.html"; "https://example.com/browser/browser/base/content/test/feed_tab.html";
gTestPage.focus();
var observer = { var observer = {
observe: function(win, topic, data) { observe: function(win, topic, data) {
if (topic != "page-info-dialog-loaded") if (topic != "page-info-dialog-loaded")
return; return;
switch(atTest) { switch (atTest) {
case 0: case 0:
atTest++; atTest++;
handlePageInfo(); handlePageInfo();
@ -33,14 +37,6 @@ function test() {
} }
} }
function handleLoad() {
pageInfo = BrowserPageInfo();
obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
obs.addObserver(observer, "page-info-dialog-loaded", false);
}
function $(aId) { return pageInfo.document.getElementById(aId) }; function $(aId) { return pageInfo.document.getElementById(aId) };
function handlePageInfo() { function handlePageInfo() {
@ -82,17 +78,16 @@ function test() {
} }
function testLockDoubleClick() { function testLockDoubleClick() {
var pageInfoDialogs = Components.classes["@mozilla.org/appshell/window-mediator;1"] var pageInfoDialogs = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator) .getService(Ci.nsIWindowMediator)
.getEnumerator("Browser:page-info"); .getEnumerator("Browser:page-info");
var i = 0; var i = 0;
while(pageInfoDialogs.hasMoreElements()) { while (pageInfoDialogs.hasMoreElements()) {
i++; i++;
pageInfo = pageInfoDialogs.getNext(); pageInfo = pageInfoDialogs.getNext();
pageInfo.close(); pageInfo.close();
} }
is(i, 1, "When the lock is clicked twice there should be only one page info dialog"); is(i, 1, "When the lock is clicked twice there should be only one page info dialog");
gTestPage.focus();
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
finish(); finish();
} }

View file

@ -377,10 +377,8 @@ function openAboutDialog()
if (win) if (win)
win.focus(); win.focus();
else { else {
// XXXmano: define minimizable=no although it does nothing on OS X window.openDialog("chrome://browser/content/aboutDialog.xul", "About",
// (see Bug 287162); remove this comment once Bug 287162 is fixed... "chrome, resizable=no, minimizable=no");
window.open("chrome://browser/content/aboutDialog.xul", "About",
"chrome, resizable=no, minimizable=no");
} }
#else #else
window.openDialog("chrome://browser/content/aboutDialog.xul", "About", "centerscreen,chrome,resizable=no"); window.openDialog("chrome://browser/content/aboutDialog.xul", "About", "centerscreen,chrome,resizable=no");

View file

@ -884,7 +884,9 @@ nsOperaCookieMigrator::AddCookieOverride(nsIPermissionManager* aManager)
rv = aManager->Add(uri, "cookie", rv = aManager->Add(uri, "cookie",
(mCurrHandlingInfo == 1 || mCurrHandlingInfo == 3) (mCurrHandlingInfo == 1 || mCurrHandlingInfo == 3)
? (PRUint32) nsIPermissionManager::ALLOW_ACTION ? (PRUint32) nsIPermissionManager::ALLOW_ACTION
: (PRUint32) nsIPermissionManager::DENY_ACTION); : (PRUint32) nsIPermissionManager::DENY_ACTION,
nsIPermissionManager::EXPIRE_NEVER,
0);
mCurrHandlingInfo = 0; mCurrHandlingInfo = 0;

View file

@ -78,7 +78,6 @@ const BrowserGlueServiceFactory = {
// Constructor // Constructor
function BrowserGlue() { function BrowserGlue() {
XPCOMUtils.defineLazyServiceGetter(this, "_prefs", XPCOMUtils.defineLazyServiceGetter(this, "_prefs",
"@mozilla.org/preferences-service;1", "@mozilla.org/preferences-service;1",
"nsIPrefBranch"); "nsIPrefBranch");
@ -91,14 +90,24 @@ function BrowserGlue() {
"@mozilla.org/widget/idleservice;1", "@mozilla.org/widget/idleservice;1",
"nsIIdleService"); "nsIIdleService");
XPCOMUtils.defineLazyServiceGetter(this, "_observerService",
"@mozilla.org/observer-service;1",
"nsIObserverService");
XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() { XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() {
return new DistributionCustomizer(); return new DistributionCustomizer();
}); });
XPCOMUtils.defineLazyGetter(this, "_sanitizer",
function() {
let sanitizerScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader).
loadSubScript("chrome://browser/content/sanitize.js", sanitizerScope);
return sanitizerScope.Sanitizer;
});
// The observer service is immediately used in _init(), so there's no reason
// to have a getter.
this._observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
this._init(); this._init();
} }
@ -109,15 +118,17 @@ function BrowserGlue() {
#endif #endif
BrowserGlue.prototype = { BrowserGlue.prototype = {
_saveSession: false, _saveSession: false,
_isIdleObserver: false, _isIdleObserver: false,
_isPlacesInitObserver: false, _isPlacesInitObserver: false,
_isPlacesLockedObserver: false, _isPlacesLockedObserver: false,
_isPlacesDatabaseLocked: false, _isPlacesDatabaseLocked: false,
_setPrefToSaveSession: function() _setPrefToSaveSession: function(aForce)
{ {
if (!this._saveSession && !aForce)
return;
this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true); this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
// This method can be called via [NSApplication terminate:] on Mac, which // This method can be called via [NSApplication terminate:] on Mac, which
@ -153,12 +164,9 @@ BrowserGlue.prototype = {
this._onQuitRequest(subject, data); this._onQuitRequest(subject, data);
break; break;
case "quit-application-granted": case "quit-application-granted":
if (this._saveSession) { // This pref must be set here because SessionStore will use its value
this._setPrefToSaveSession(); // on quit-application.
} this._setPrefToSaveSession();
// Everything that uses Places during shutdown should be here, since
// on quit-application Places database connection will be closed
// and history synchronization could fail.
this._onProfileShutdown(); this._onProfileShutdown();
break; break;
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS #ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
@ -168,12 +176,11 @@ BrowserGlue.prototype = {
this._onQuitRequest(subject, "lastwindow"); this._onQuitRequest(subject, "lastwindow");
break; break;
case "browser-lastwindow-close-granted": case "browser-lastwindow-close-granted":
if (this._saveSession) this._setPrefToSaveSession();
this._setPrefToSaveSession();
break; break;
#endif #endif
case "session-save": case "session-save":
this._setPrefToSaveSession(); this._setPrefToSaveSession(true);
subject.QueryInterface(Ci.nsISupportsPRBool); subject.QueryInterface(Ci.nsISupportsPRBool);
subject.data = true; subject.data = true;
break; break;
@ -191,8 +198,8 @@ BrowserGlue.prototype = {
break; break;
case "places-database-locked": case "places-database-locked":
this._isPlacesDatabaseLocked = true; this._isPlacesDatabaseLocked = true;
// stop observing, so further attempts to load history service // Stop observing, so further attempts to load history service
// do not show the prompt. // will not show the prompt.
this._observerService.removeObserver(this, "places-database-locked"); this._observerService.removeObserver(this, "places-database-locked");
this._isPlacesLockedObserver = false; this._isPlacesLockedObserver = false;
break; break;
@ -268,7 +275,7 @@ BrowserGlue.prototype = {
// profile startup handler (contains profile initialization routines) // profile startup handler (contains profile initialization routines)
_onProfileStartup: function() _onProfileStartup: function()
{ {
this.Sanitizer.onStartup(); this._sanitizer.onStartup();
// check if we're in safe mode // check if we're in safe mode
var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo). var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime); QueryInterface(Ci.nsIXULRuntime);
@ -302,7 +309,8 @@ BrowserGlue.prototype = {
} }
} }
this._observerService.notifyObservers(null, "browser-ui-startup-complete", ""); this._observerService
.notifyObservers(null, "browser-ui-startup-complete", "");
}, },
// profile shutdown handler (contains profile cleanup routines) // profile shutdown handler (contains profile cleanup routines)
@ -311,7 +319,7 @@ BrowserGlue.prototype = {
this._shutdownPlaces(); this._shutdownPlaces();
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME); this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
this._isIdleObserver = false; this._isIdleObserver = false;
this.Sanitizer.onShutdown(); this._sanitizer.onShutdown();
}, },
// Browser startup complete. All initial windows have opened. // Browser startup complete. All initial windows have opened.
@ -572,17 +580,6 @@ BrowserGlue.prototype = {
browser.selectedTab = browser.addTab(updateUrl); browser.selectedTab = browser.addTab(updateUrl);
}, },
// returns the (cached) Sanitizer constructor
get Sanitizer()
{
if(typeof(Sanitizer) != "function") { // we should dynamically load the script
Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader).
loadSubScript("chrome://browser/content/sanitize.js", null);
}
return Sanitizer;
},
/** /**
* Initialize Places * Initialize Places
* - imports the bookmarks html file if bookmarks database is empty, try to * - imports the bookmarks html file if bookmarks database is empty, try to
@ -907,7 +904,7 @@ BrowserGlue.prototype = {
sanitize: function(aParentWindow) sanitize: function(aParentWindow)
{ {
this.Sanitizer.sanitize(aParentWindow); this._sanitizer.sanitize(aParentWindow);
}, },
ensurePlacesDefaultQueriesInitialized: function() { ensurePlacesDefaultQueriesInitialized: function() {
@ -921,7 +918,7 @@ BrowserGlue.prototype = {
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark"; const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion"; const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
// XXX should this be a pref? see bug #399268 // TODO bug 399268: should this be a pref?
const MAX_RESULTS = 10; const MAX_RESULTS = 10;
// get current smart bookmarks version // get current smart bookmarks version

View file

@ -1,165 +0,0 @@
# ***** 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 the Places Organizer Query Builder.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# 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 *****
<vbox id="advancedSearch">
<hbox align="center">
<label value="&advancedSearch.match.label;" control="advancedSearchType"/>
<menulist id="advancedSearchType"
oncommand="PlacesQueryBuilder.doSearch();">
<menupopup>
<menuitem value="and" label="&advancedSearch.all.label;"/>
<menuitem value="or" label="&advancedSearch.any.label;"/>
</menupopup>
</menulist>
<label value="&advancedSearch.rules.label;"/>
</hbox>
<grid flex="1">
<columns>
<column flex="1"/>
<column flex="1"/>
<column flex="0"/>
<column flex="0"/>
</columns>
<rows id="advancedSearchRows">
<row id="advancedSearch0Row" flex="1" hidden="true">
<menulist id="advancedSearch0Subject" flex="1">
<menupopup>
<menuitem value="keyword"
label="&advancedSearch.subj_keyword.label;"
selected="true"
rowid="1"
id="advancedSearch0SubjectKeyword"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._keywordSearch);"/>
<menuitem value="visited"
label="&advancedSearch.subj_visited.label;"
rowid="1"
id="advancedSearch0SubjectVisited"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._timeSearch);"/>
<menuitem value="location"
label="&advancedSearch.subj_location.label;"
rowid="1"
id="advancedSearch0SubjectLocation"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._locationSearch);"/>
</menupopup>
</menulist>
<hbox flex="1" align="center">
<menulist id="advancedSearch0LocationMenulist"
oncommand="PlacesQueryBuilder.doSearch();"
hidden="true">
<menupopup>
<menuitem id="advancedSearch0LocationMenuSelected"
value="startswith"
label="&advancedSearch.location_startswith.label;"
selected="true"/>
<menuitem value="is"
label="&advancedSearch.location_is.label;"/>
<menuitem value="onsite"
label="&advancedSearch.location_onsite.label;"/>
</menupopup>
</menulist>
<menulist id="advancedSearch0TimeMenulist" hidden="true">
<menupopup>
<menuitem value="on"
id="advancedSearch0TimeDefault"
label="&advancedSearch.time_is.label;"
selected="true"
rowid="1"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._timeSearch);"/>
<menuitem value="before"
label="&advancedSearch.time_before.label;"
rowid="1"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._timeSearch);"/>
<menuitem value="after"
label="&advancedSearch.time_after.label;"
rowid="1"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._timeSearch);"/>
<menuitem value="inLast"
label="&advancedSearch.time_inlast.label;"
rowid="1"
oncommand="PlacesQueryBuilder.showSearch(this.getAttribute('rowid'), PlacesQueryBuilder._timeInLastSearch);"/>
</menupopup>
</menulist>
<textbox type="search"
timeout="50"
id="advancedSearch0Textbox"
flex="1"
oncommand="PlacesQueryBuilder.doSearch();"/>
<textbox type="search"
timeout="50"
id="advancedSearch0TimePicker"
hidden="true" flex="1"
rowid="1"
oncommand="PlacesQueryBuilder.onDateTyped(event, this.getAttribute('rowid'));"
onclick="PlacesQueryBuilder.handleTimePickerClick(event, this.getAttribute('rowid'));"/>
<popup id="advancedSearch0DatePopup"
onpopupshowing="this.setAttribute('showing', true);"
onpopuphidden="this.removeAttribute('showing');">
<vbox id="advancedSearch0Calendar"
class="history-calendar"
rowid="1"
onselectionchanged="return PlacesQueryBuilder.onCalendarChanged(event, event.target.getAttribute('rowid'));"/>
</popup>
<menulist id="advancedSearch0TimeMenulist2"
oncommand="PlacesQueryBuilder.doSearch();"
hidden="true">
<menupopup>
<menuitem value="days"
label="&advancedSearch.last_days.label;"
selected="true"/>
<menuitem value="weeks"
label="&advancedSearch.last_weeks.label;"/>
<menuitem value="months"
label="&advancedSearch.last_months.label;"/>
</menupopup>
</menulist>
</hbox>
<button id="advancedSearch0Minus"
label="&advancedSearch.minus.label;"
class="small advancedSearchMinus"
oncommand="PlacesQueryBuilder.removeRow(event.target.parentNode);"/>
<button id="advancedSearch0Plus"
label="&advancedSearch.plus.label;"
class="small advancedSearchPlus"
command="OrganizerCommand_search:moreCriteria"/>
</row>
</rows>
</grid>
</vbox>

View file

@ -1,5 +0,0 @@
.day1 { background-color:white; }
.day2 { background-color:#EEE; }
.green { background-color:green; }
.red { background-color:red; }

View file

@ -1,20 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
<style type="text/css">
body { background-color:white; color:black; font-family:verdana,helvetica;}
.item { font-size:9pt; padding:3px; padding-top:0px; margin-top:0px; }
.itemnew { font-size:9pt; padding:3px; margin-left:5em; border-top:1px dotted #888; padding-top:0px; }
.time { font-size:7pt; border-top:2px solid black; margin-top:10px; margin-bottom:2px; font-weight:bold; }
.host { font-size:7pt; font-weight:bold; color:#888; width:8em; overflow:hidden; }
.title { margin:0px; padding:2px; }
.url { font-size:7pt; color:#080; padding-left:12em; }
.favicon { padding-right:8px; position:relative; top:2px; }
</style>
</head>
<body>
</body>
</html>

View file

@ -1,297 +0,0 @@
/* ***** 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 Places
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@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 ***** */
window.addEventListener("load", BW_startup, false);
var BW_frame;
var BW_historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"].
getService(Components.interfaces.nsINavHistoryService);
var BW_result;
var loadedIframe = false;
var loadedBretts = false;
function BW_startup() {
BW_frame = document.getElementById("theframe");
var options = BW_historyService.getNewQueryOptions();
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.resultType = options.RESULTS_AS_VISIT;
options.maxResults = 200;
var query = BW_historyService.getNewQuery();
BW_result = BW_historyService.executeQuery(query, options);
BW_result.root.containerOpen = true;
BW_frame.contentWindow.addEventListener("load", BW_fill, true);
loadedBretts = true;
if (loadedIframe && loadedBretts)
BW_fill();
//BW_frame.onload = BW_fill;
//BW_frame.contentDocument.onLoad = BW_fill;
//BW_fill();
}
function BW_loadiframe() {
loadedIframe = true;
if (loadedIframe && loadedBretts)
BW_fill();
}
function BW_getTLD(host) {
var count = 0;
for (var i = host.length - 2; i > 0; i --) {
if (host[i] == '.') {
count ++;
if (count == 2) {
return host.substr(i + 1);
}
}
}
return host;
}
var BW_filled = false;
function BW_fill() {
if (BW_filled)
return;
BW_filled = true;
BW_frame.setAttribute('onload', '');
var container = BW_result.root;
var length = container.childCount;
dump("doc = " + BW_frame.contentDocument + "\n");
var doc = BW_frame.contentDocument;
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
var dateformat = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Components.interfaces.nsIScriptableDateFormat);
var table = doc.createElement('table');
doc.body.appendChild(table);
var counts = new Array(240);
for (var i = 0; i < counts.length; i ++) {
counts[i] = 0;
}
var now = new Date();
now.setHours(0);
now.setMinutes(0);
now.setSeconds(0);
now.setMilliseconds(0);
now.setDate(now.getDate()+1);
var tonightUS = now.getTime() * 1000;
var usPerHour = 3600000000;
var previousSession = -1;
var previousMS = 18437736874454810627;
var previousHost = "";
for (var i = 0; i < length; i ++) {
var child = container.getChild(i);
child.QueryInterface(Components.interfaces.nsINavHistoryVisitResultNode);
var session = child.sessionId;
var thisBin = Math.floor((tonightUS - child.time) / usPerHour);
if (thisBin >= 0 && thisBin < counts.length) {
counts[thisBin] = counts[thisBin] + 1;
}
var ms = child.time / 1000;
var addedTime = false;
if (previousMS - ms > 600000) {
addedTime = true;
var t = new Date(ms);
var tr = doc.createElement('tr');
table.appendChild(tr);
var td = doc.createElement('td');
td.setAttribute('colspan', '2');
td.setAttribute('class', 'time');
tr.appendChild(td);
var timestring = dateformat.FormatDateTime("",
dateformat.dateFormatShort,
dateformat.timeFormatNoSeconds,
t.getFullYear(),
t.getMonth(),
t.getDate(),
t.getHours(),
t.getMinutes(),
0);
var timetext = doc.createTextNode(timestring);
td.appendChild(timetext);
}
previousMS = ms;
var tr = doc.createElement('tr');
table.appendChild(tr);
// URL
var spec;
var uri;
try {
spec = child.uri;
uri = ios.newURI(spec, null, null);
} catch(e) {
spec = null;
uri = null;
}
// host name if needed on left
var td = doc.createElement('td');
td.setAttribute('valign', 'top');
td.setAttribute('align', 'right');
td.setAttribute('class', 'host');
tr.appendChild(td);
var host = BW_getTLD(uri.host);
if (addedTime || host != previousHost) {
// add host name
var hosttext = doc.createTextNode(host);
td.appendChild(hosttext);
}
previousHost = host;
// right section
var td = doc.createElement('td');
td.setAttribute('valign', 'top');
tr.appendChild(td);
if (! addedTime && (i == 0 || child.sessionId != previousSession))
td.setAttribute('class', 'itemnew');
else
td.setAttribute('class', 'item');
previousSession = session;
// title div and text
var titlediv = doc.createElement('div');
titlediv.setAttribute('class', 'title');
var imgelt = doc.createElement('img');
if (child.icon)
imgelt.setAttribute('src', child.icon.spec);
else
imgelt.setAttribute('src', 'chrome://browser/skin/places/defaultFavicon.png');
imgelt.setAttribute('width', 16);
imgelt.setAttribute('height', 16);
imgelt.setAttribute('class', 'favicon');
titlediv.appendChild(imgelt);
var titletext = doc.createTextNode(child.title);
titlediv.appendChild(titletext);
td.appendChild(titlediv);
// URL
if (spec) {
/* // this does bold host names
var host = uri.host;
var hostStart = spec.indexOf(host);
if (hostStart >= 0) {
var prehost = spec.substring(0, hostStart);
var prehosttext = doc.createTextNode(prehost);
var posthost = spec.substring(hostStart + host.length, spec.length);
var posthosttext = doc.createTextNode(posthost);
var hosttext = doc.createTextNode(host);
var boldElement = doc.createElement('b');
boldElement.appendChild(hosttext);
var urldiv = doc.createElement('div');
urldiv.setAttribute('class', 'url');
urldiv.appendChild(prehosttext);
urldiv.appendChild(boldElement);
urldiv.appendChild(posthosttext);
td.appendChild(urldiv);
}
*/
var urldiv = doc.createElement('div');
urldiv.setAttribute('class', 'url');
var urltext = doc.createTextNode(spec);
urldiv.appendChild(urltext);
td.appendChild(urldiv);
}
}
// smooth the counts
var counts2 = new Array(counts.length);
for (var i = 0; i < counts.length; i ++) {
var ttl = 0;
var acc = 0;
for (var j = -2; j <= 2; j ++) {
if (i + j < 0) continue;
if (i + j >= counts.length) continue;
var scale;
if (j == -2 || j == 2) scale = 0.33;
else if (j == -1 || j == 1) scale = 0.66;
else scale = 1.0;
acc += counts[i+j] * scale;
ttl += scale;
}
counts2[i] = Math.round(acc);
}
// fill in the day bargraphs
var daylist = document.getElementById("daylist");
for (var i = 0; i < counts2.length / 24; i ++) {
var day = document.createElement('hbox');
day.setAttribute('align', 'center');
if (i % 2)
day.setAttribute('class', 'day2');
else
day.setAttribute('class', 'day1');
daylist.appendChild(day);
var text = document.createTextNode("Today - " + i );
var description = document.createElement('description');
description.setAttribute('flex', '1');
description.appendChild(text);
day.appendChild(description);
var bars = document.createElement('vbox');
bars.setAttribute('align', 'end');
day.appendChild(bars);
for (var b = 0; b < 24; b++) {
var box = document.createElement('hbox');
box.setAttribute('width', '' + counts2[i*24 + b]);
box.setAttribute('height', '1');
box.setAttribute('class', 'green');
bars.appendChild(box);
}
}
}

View file

@ -1,9 +1,3 @@
%ifdef PLACES_QUERY_BUILDER
.history-calendar {
-moz-binding: url("chrome://browser/content/places/places.xml#calendar");
}
%endif
#contentTitle { #contentTitle {
width: 0px; width: 0px;
} }

View file

@ -88,11 +88,6 @@ var PlacesOrganizer = {
// Set up the search UI. // Set up the search UI.
PlacesSearchBox.init(); PlacesSearchBox.init();
#ifdef PLACES_QUERY_BUILDER
// Set up the advanced query builder UI
PlacesQueryBuilder.init();
#endif
window.addEventListener("AppCommand", this, true); window.addEventListener("AppCommand", this, true);
#ifdef XP_MACOSX #ifdef XP_MACOSX
// 1. Map Edit->Find command to OrganizerCommand_find:all. Need to map // 1. Map Edit->Find command to OrganizerCommand_find:all. Need to map
@ -788,12 +783,7 @@ var PlacesOrganizer = {
// Get the place: uri for the query. // Get the place: uri for the query.
// If the advanced query builder is showing, use that. // If the advanced query builder is showing, use that.
var options = this.getCurrentOptions(); var options = this.getCurrentOptions();
#ifdef PLACES_QUERY_BUILDER
var queries = PlacesQueryBuilder.queries;
#else
var queries = this.getCurrentQueries(); var queries = this.getCurrentQueries();
#endif
var placeSpec = PlacesUtils.history.queriesToQueryString(queries, var placeSpec = PlacesUtils.history.queriesToQueryString(queries,
queries.length, queries.length,
@ -997,12 +987,6 @@ var PlacesSearchBox = {
// Hide the advanced search controls when the user hasn't searched // Hide the advanced search controls when the user hasn't searched
var searchModifiers = document.getElementById("searchModifiers"); var searchModifiers = document.getElementById("searchModifiers");
searchModifiers.hidden = false; searchModifiers.hidden = false;
#ifdef PLACES_QUERY_BUILDER
// if new search, open builder with pre-populated text row
if (PlacesQueryBuilder.numRows == 0)
document.getElementById("OrganizerCommand_search:moreCriteria").doCommand();
#endif
}, },
hideSearchUI: function PSB_hideSearchUI() { hideSearchUI: function PSB_hideSearchUI() {
@ -1019,470 +1003,6 @@ var PlacesQueryBuilder = {
queries: [], queries: [],
queryOptions: null, queryOptions: null,
#ifdef PLACES_QUERY_BUILDER
numRows: 0,
/**
* The maximum number of terms that can be added.
*/
_maxRows: null,
_keywordSearch: {
advancedSearch_N_Subject: "advancedSearch_N_SubjectKeyword",
advancedSearch_N_LocationMenulist: false,
advancedSearch_N_TimeMenulist: false,
advancedSearch_N_Textbox: "",
advancedSearch_N_TimePicker: false,
advancedSearch_N_TimeMenulist2: false
},
_locationSearch: {
advancedSearch_N_Subject: "advancedSearch_N_SubjectLocation",
advancedSearch_N_LocationMenulist: "advancedSearch_N_LocationMenuSelected",
advancedSearch_N_TimeMenulist: false,
advancedSearch_N_Textbox: "",
advancedSearch_N_TimePicker: false,
advancedSearch_N_TimeMenulist2: false
},
_timeSearch: {
advancedSearch_N_Subject: "advancedSearch_N_SubjectVisited",
advancedSearch_N_LocationMenulist: false,
advancedSearch_N_TimeMenulist: true,
advancedSearch_N_Textbox: false,
advancedSearch_N_TimePicker: "date",
advancedSearch_N_TimeMenulist2: false
},
_timeInLastSearch: {
advancedSearch_N_Subject: "advancedSearch_N_SubjectVisited",
advancedSearch_N_LocationMenulist: false,
advancedSearch_N_TimeMenulist: true,
advancedSearch_N_Textbox: "7",
advancedSearch_N_TimePicker: false,
advancedSearch_N_TimeMenulist2: true
},
_nextSearch: null,
_queryBuilders: null,
init: function PQB_init() {
// Initialize advanced search
this._nextSearch = {
"keyword": this._timeSearch,
"visited": this._locationSearch,
"location": null
};
this._queryBuilders = {
"keyword": this.setKeywordQuery,
"visited": this.setVisitedQuery,
"location": this.setLocationQuery
};
this._maxRows = this._queryBuilders.length;
this._dateService = Cc["@mozilla.org/intl/scriptabledateformat;1"].
getService(Ci.nsIScriptableDateFormat);
},
/**
* Hides the query builder, and the match rule UI if visible.
*/
hide: function PQB_hide() {
var advancedSearch = document.getElementById("advancedSearch");
// Need to collapse the advanced search box.
advancedSearch.collapsed = true;
},
/**
* Shows the query builder
*/
show: function PQB_show() {
var advancedSearch = document.getElementById("advancedSearch");
advancedSearch.collapsed = false;
},
toggleVisibility: function ABP_toggleVisibility() {
var expander = document.getElementById("organizerScopeBarExpander");
var advancedSearch = document.getElementById("advancedSearch");
if (advancedSearch.collapsed) {
advancedSearch.collapsed = false;
expander.className = "expander-down";
expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextdown"));
}
else {
advancedSearch.collapsed = true;
expander.className = "expander-up"
expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextup"));
}
},
/**
* Includes the rowId in the id attribute of an element in a row newly
* created from the template row.
* @param element
* The element whose id attribute needs to be updated.
* @param rowId
* The index of the new row.
*/
_setRowId: function PQB__setRowId(element, rowId) {
if (element.id)
element.id = element.id.replace("advancedSearch0", "advancedSearch" + rowId);
if (element.hasAttribute("rowid"))
element.setAttribute("rowid", rowId);
for (var i = 0; i < element.childNodes.length; ++i) {
this._setRowId(element.childNodes[i], rowId);
}
},
_updateUIForRowChange: function PQB__updateUIForRowChange() {
// Update the "can add more criteria" command to make sure various +
// buttons are disabled.
var command = document.getElementById("OrganizerCommand_search:moreCriteria");
if (this.numRows >= this._maxRows)
command.setAttribute("disabled", "true");
else
command.removeAttribute("disabled");
},
/**
* Adds a row to the view, prefilled with the next query subject. If the
* query builder is not visible, it will be shown.
*/
addRow: function PQB_addRow() {
// Limits the number of rows that can be added based on the maximum number
// of search query subjects.
if (this.numRows >= this._maxRows)
return;
// Clone the template row and unset the hidden attribute.
var gridRows = document.getElementById("advancedSearchRows");
var newRow = gridRows.firstChild.cloneNode(true);
newRow.hidden = false;
// Determine what the search type is based on the last visible row. If this
// is the first row, the type is "keyword search". Otherwise, it's the next
// in the sequence after the one defined by the previous visible row's
// Subject selector, as defined in _nextSearch.
var searchType = this._keywordSearch;
var lastMenu = document.getElementById("advancedSearch" +
this.numRows +
"Subject");
if (this.numRows > 0 && lastMenu && lastMenu.selectedItem)
searchType = this._nextSearch[lastMenu.selectedItem.value];
// There is no "next" search type. We are here in error.
if (!searchType)
return;
// We don't insert into the document until _after_ the searchType is
// determined, since this will interfere with the computation.
gridRows.appendChild(newRow);
this._setRowId(newRow, ++this.numRows);
// Ensure the Advanced Search container is visible, if this is the first
// row being added.
if (this.numRows == 1) {
this.show();
// Pre-fill the search terms field with the value from the one on the
// toolbar.
// For some reason, setting.value here synchronously does not appear to
// work.
var searchTermsField = document.getElementById("advancedSearch1Textbox");
if (searchTermsField)
setTimeout(function() { searchTermsField.value = PlacesSearchBox.value; }, 10);
this.queries = PlacesOrganizer.getCurrentQueries();
return;
}
this.showSearch(this.numRows, searchType);
this._updateUIForRowChange();
},
/**
* Remove a row from the set of terms
* @param row
* The row to remove. If this is null, the last row will be removed.
* If there are no more rows, the query builder will be hidden.
*/
removeRow: function PQB_removeRow(row) {
if (!row)
row = document.getElementById("advancedSearch" + this.numRows + "Row");
row.parentNode.removeChild(row);
--this.numRows;
if (this.numRows < 1) {
this.hide();
// Re-do the original toolbar-search-box search that the user used to
// spawn the advanced UI... this effectively "reverts" the UI to the
// point it was in before they began monkeying with advanced search.
PlacesSearchBox.search(PlacesSearchBox.value);
return;
}
this.doSearch();
this._updateUIForRowChange();
},
onDateTyped: function PQB_onDateTyped(event, row) {
var textbox = document.getElementById("advancedSearch" + row + "TimePicker");
var dateString = textbox.value;
var dateArr = dateString.split("-");
// The date can be split into a range by the '-' character, i.e.
// 9/5/05 - 10/2/05. Unfortunately, dates can also be written like
// 9-5-05 - 10-2-05. Try to parse the date based on how many hyphens
// there are.
var d0 = null;
var d1 = null;
// If there are an even number of elements in the date array, try to
// parse it as a range of two dates.
if ((dateArr.length & 1) == 0) {
var mid = dateArr.length / 2;
var dateStr0 = dateArr[0];
var dateStr1 = dateArr[mid];
for (var i = 1; i < mid; ++i) {
dateStr0 += "-" + dateArr[i];
dateStr1 += "-" + dateArr[i + mid];
}
d0 = new Date(dateStr0);
d1 = new Date(dateStr1);
}
// If that didn't work, try to parse it as a single date.
if (d0 == null || d0 == "Invalid Date") {
d0 = new Date(dateString);
}
if (d0 != null && d0 != "Invalid Date") {
// Parsing succeeded -- update the calendar.
var calendar = document.getElementById("advancedSearch" + row + "Calendar");
if (d0.getFullYear() < 2000)
d0.setFullYear(2000 + (d0.getFullYear() % 100));
if (d1 != null && d1 != "Invalid Date") {
if (d1.getFullYear() < 2000)
d1.setFullYear(2000 + (d1.getFullYear() % 100));
calendar.updateSelection(d0, d1);
}
else {
calendar.updateSelection(d0, d0);
}
// And update the search.
this.doSearch();
}
},
onCalendarChanged: function PQB_onCalendarChanged(event, row) {
var calendar = document.getElementById("advancedSearch" + row + "Calendar");
var begin = calendar.beginrange;
var end = calendar.endrange;
// If the calendar doesn't have a begin/end, don't change the textbox.
if (begin == null || end == null)
return true;
// If the begin and end are the same day, only fill that into the textbox.
var textbox = document.getElementById("advancedSearch" + row + "TimePicker");
var beginDate = begin.getDate();
var beginMonth = begin.getMonth() + 1;
var beginYear = begin.getFullYear();
var endDate = end.getDate();
var endMonth = end.getMonth() + 1;
var endYear = end.getFullYear();
if (beginDate == endDate && beginMonth == endMonth && beginYear == endYear) {
// Just one date.
textbox.value = this._dateService.FormatDate("",
this._dateService.dateFormatShort,
beginYear,
beginMonth,
beginDate);
}
else
{
// Two dates.
var beginStr = this._dateService.FormatDate("",
this._dateService.dateFormatShort,
beginYear,
beginMonth,
beginDate);
var endStr = this._dateService.FormatDate("",
this._dateService.dateFormatShort,
endYear,
endMonth,
endDate);
textbox.value = beginStr + " - " + endStr;
}
// Update the search.
this.doSearch();
return true;
},
handleTimePickerClick: function PQB_handleTimePickerClick(event, row) {
var popup = document.getElementById("advancedSearch" + row + "DatePopup");
if (popup.showing)
popup.hidePopup();
else {
var textbox = document.getElementById("advancedSearch" + row + "TimePicker");
popup.showPopup(textbox, -1, -1, "popup", "bottomleft", "topleft");
}
},
showSearch: function PQB_showSearch(row, values) {
for (val in values) {
var id = val.replace("_N_", row);
var element = document.getElementById(id);
if (values[val] || typeof(values[val]) == "string") {
if (typeof(values[val]) == "string") {
if (values[val] == "date") {
// "date" means that the current date should be filled into the
// textbox, and the calendar for the row updated.
var d = new Date();
element.value = this._dateService.FormatDate("",
this._dateService.dateFormatShort,
d.getFullYear(),
d.getMonth() + 1,
d.getDate());
var calendar = document.getElementById("advancedSearch" + row + "Calendar");
calendar.updateSelection(d, d);
}
else if (element.nodeName == "textbox") {
// values[val] is the initial value of the textbox.
element.value = values[val];
} else {
// values[val] is the menuitem which should be selected.
var itemId = values[val].replace("_N_", row);
var item = document.getElementById(itemId);
element.selectedItem = item;
}
}
element.hidden = false;
}
else {
element.hidden = true;
}
}
this.doSearch();
},
setKeywordQuery: function PQB_setKeywordQuery(query, prefix) {
query.searchTerms += document.getElementById(prefix + "Textbox").value + " ";
},
setLocationQuery: function PQB_setLocationQuery(query, prefix) {
var type = document.getElementById(prefix + "LocationMenulist").selectedItem.value;
if (type == "onsite") {
query.domain = document.getElementById(prefix + "Textbox").value;
}
else {
query.uriIsPrefix = (type == "startswith");
var spec = document.getElementById(prefix + "Textbox").value;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
try {
query.uri = ios.newURI(spec, null, null);
}
catch (e) {
// Invalid input can cause newURI to barf, that's OK, tack "http://"
// onto the front and try again to see if the user omitted it
try {
query.uri = ios.newURI("http://" + spec, null, null);
}
catch (e) {
// OK, they have entered something which can never match. This should
// not happen.
}
}
}
},
setVisitedQuery: function PQB_setVisitedQuery(query, prefix) {
var searchType = document.getElementById(prefix + "TimeMenulist").selectedItem.value;
const DAY_MSEC = 86400000;
switch (searchType) {
case "on":
var calendar = document.getElementById(prefix + "Calendar");
var begin = calendar.beginrange.getTime();
var end = calendar.endrange.getTime();
if (begin == end) {
end = begin + DAY_MSEC;
}
query.beginTime = begin * 1000;
query.endTime = end * 1000;
break;
case "before":
var calendar = document.getElementById(prefix + "Calendar");
var time = calendar.beginrange.getTime();
query.endTime = time * 1000;
break;
case "after":
var calendar = document.getElementById(prefix + "Calendar");
var time = calendar.endrange.getTime();
query.beginTime = time * 1000;
break;
case "inLast":
var textbox = document.getElementById(prefix + "Textbox");
var amount = parseInt(textbox.value);
amount = amount * DAY_MSEC;
var menulist = document.getElementById(prefix + "TimeMenulist2");
if (menulist.selectedItem.value == "weeks")
amount = amount * 7;
else if (menulist.selectedItem.value == "months")
amount = amount * 30;
var now = new Date();
now = now - amount;
query.beginTime = now * 1000;
break;
}
},
doSearch: function PQB_doSearch() {
// Create the individual queries.
var queryType = document.getElementById("advancedSearchType").selectedItem.value;
this.queries = [];
if (queryType == "and")
this.queries.push(PlacesUtils.history.getNewQuery());
var updated = 0;
for (var i = 1; updated < this.numRows; ++i) {
var prefix = "advancedSearch" + i;
// The user can remove rows from the middle and start of the list, not
// just from the end, so we need to make sure that this row actually
// exists before attempting to construct a query for it.
var querySubjectElement = document.getElementById(prefix + "Subject");
if (querySubjectElement) {
// If the queries are being AND-ed, put all the rows in one query.
// If they're being OR-ed, add a separate query for each row.
var query;
if (queryType == "and")
query = this.queries[0];
else
query = PlacesUtils.history.getNewQuery();
var querySubject = querySubjectElement.value;
this._queryBuilders[querySubject](query, prefix);
if (queryType == "or")
this.queries.push(query);
++updated;
}
}
// Make sure we're getting uri results, not visits
this.options = PlacesOrganizer.getCurrentOptions();
this.options.resultType = this.options.RESULT_TYPE_URI;
// XXXben - find some public way of doing this!
PlacesOrganizer._content.load(this.queries, this.options);
// Update the details panel
PlacesOrganizer.onContentTreeSelect();
},
#endif
/** /**
* Called when a scope button in the scope bar is clicked. * Called when a scope button in the scope bar is clicked.
* @param aButton * @param aButton

View file

@ -1,426 +0,0 @@
<?xml version="1.0"?>
<bindings id="placesBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
#ifdef PLACES_QUERY_BUILDER
<binding id="calendar">
<content>
<xul:vbox class="calendar-box">
<xul:hbox class="calendar-header">
<xul:label anonid="prevmonth" class="calendar-month-jump">&#xab;</xul:label>
<xul:label anonid="monthtitle" class="calendar-month-title" flex="1"/>
<xul:label anonid="nextmonth" class="calendar-month-jump">&#xbb;</xul:label>
</xul:hbox>
<xul:tooltip anonid="calendartooltip">
<!-- FIXME -->
</xul:tooltip>
<xul:grid anonid="calendargrid" class="calendar-grid">
<xul:columns><xul:column flex="1"/><xul:column flex="1"/><xul:column flex="1"/><xul:column flex="1"/><xul:column flex="1"/><xul:column flex="1"/><xul:column flex="1"/></xul:columns>
<xul:rows>
<xul:row class="calendar-day-header">
<xul:label anonid="calendarhead0"></xul:label>
<xul:label anonid="calendarhead1"></xul:label>
<xul:label anonid="calendarhead2"></xul:label>
<xul:label anonid="calendarhead3"></xul:label>
<xul:label anonid="calendarhead4"></xul:label>
<xul:label anonid="calendarhead5"></xul:label>
<xul:label anonid="calendarhead6"></xul:label>
</xul:row>
<!-- The "00" is so that the table has the correct dimensions (most
numbers are the same width) when it is first displayed. The
default definition for "calendar-day" should have the same color
fore- and background so you won't see this. -->
<xul:row>
<xul:label anonid="calendar0" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar1" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar2" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar3" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar4" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar5" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar6" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
<xul:row>
<xul:label anonid="calendar7" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar8" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar9" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar10" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar11" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar12" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar13" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
<xul:row>
<xul:label anonid="calendar14" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar15" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar16" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar17" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar18" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar19" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar20" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
<xul:row>
<xul:label anonid="calendar21" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar22" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar23" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar24" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar25" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar26" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar27" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
<xul:row>
<xul:label anonid="calendar28" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar29" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar30" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar31" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar32" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar33" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar34" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
<xul:row>
<xul:label anonid="calendar35" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar36" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar37" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar38" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar39" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar40" class="calendar-day" tooltip="calendartooltip">00</xul:label>
<xul:label anonid="calendar41" class="calendar-day" tooltip="calendartooltip">00</xul:label>
</xul:row>
</xul:rows>
</xul:grid>
</xul:vbox>
</content>
<implementation>
<constructor><![CDATA[
var grid = document.getAnonymousElementByAttribute(this, "anonid",
"calendargrid");
this._numCells = 42; // max number of cells displayable in the calendar
this._cellPrefix = "calendar"; // value before the number in the ID of cells
this._currentMonth = -1;
this._currentYear = -1;
this._cell0Date = null; // date for top left of calendar
this._selectNothing = false;
this._selectBegin = null;
this._selectEnd = null;
// localized stuff, FIXME: move somewhere else
this._pref_firstDayOfWeek = 0; // 0 = Sunday, 1 = Monday
this._pref_dayHeaders = ["S", "M", "T", "W", "T", "F", "S"];
this._pref_shortMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// day headers
for (var i = 0; i < 7; i ++) {
var cell = document.getAnonymousElementByAttribute(this, "anonid",
"calendarhead" + i);
cell.value = this._pref_dayHeaders[i];
}
// cell item
var calendargrid = document.getAnonymousElementByAttribute(this, "anonid", "calendargrid");
this._days = new Array(this._numCells);
this._selected = new Array(this._numCells);
for (var i = 0; i < this._numCells; i ++) {
this._days[i] = document.getAnonymousElementByAttribute(this, "anonid", this._cellPrefix + i);
this._selected[i] = false;
}
// month navigation hooks
var myself = this;
document.getAnonymousElementByAttribute(this, "anonid", "prevmonth").
addEventListener("click", function() { myself.jumpMonth(-1); }, false);
document.getAnonymousElementByAttribute(this, "anonid", "nextmonth").
addEventListener("click", function() { myself.jumpMonth(1); }, false);
// day selection hooks
calendargrid.addEventListener("mousedown", function(event) { myself.mouseDown(event); }, false);
calendargrid.addEventListener("mouseup", function(event) { myself.mouseUp(event); }, false);
calendargrid.addEventListener("mousemove", function(event) { myself.mouseMove(event); }, false);
this.visibleMonth = new Date(); // today
]]></constructor>
<property name="visibleMonth">
<getter>
return new Date(this._visibleMonth);
</getter>
<setter>
this._visibleMonth = new Date(val.getFullYear(), val.getMonth(), 1);
this.drawMonth();
</setter>
</property>
<property name="beginrange">
<getter>
if (! this._selectBegin)
return null;
else
return new Date(this._selectBegin);
</getter>
<setter>
this._selectNothing = false;
this._selectBegin = val;
this.updateSelection(this._selectBegin, this._selectEnd);
this.fireRangeEvent();
</setter>
</property>
<property name="endrange">
<getter>
if (! this._selectEnd)
return null;
else
return new Date(this._selectEnd);
</getter>
<setter>
this._selectNothing = false;
this._selectEnd = val;
this.updateSelection(this._selectBegin, this._selectEnd);
this.fireRangeEvent();
</setter>
</property>
<!-- Use this to set the range at once. It will be more efficient than
setting begin and end independently since there will be only one
redraw. Set updateVisible to have the calendar change the active
month if necessary. -->
<method name="setRange">
<parameter name="begin"/>
<parameter name="end"/>
<parameter name="updateVisible"/>
<body><![CDATA[
if (updateVisible && end) {
// this just tries to make the end range visible. If there is no
// end range, we don't do anything. We might want to set the visible
// month to the begin range in this case, but I don't think this
// situation arises in practice.
var daysToEnd = this.daysBetweenDates(end, this._cell0Date);
if (daysToEnd < 0 || daysToEnd >= this._numCells) {
// reselect month for end range
this.visibleMonth = end;
}
}
this._selectNothing = false;
this.updateSelection(begin, end);
this.fireRangeEvent();
]]></body>
</method>
<!-- Normally, null begin and end means select all, so you can set
this if you don't want anything selected.-->
<property name="selectNothing">
<getter>
return this._selectNothing;
</getter>
<setter>
this._selectNothing = val;
</setter>
</property>
<!--===== jumpMonth =====-->
<method name="jumpMonth">
<parameter name="relative"/>
<body><![CDATA[
var newMonth = this._visibleMonth.getMonth() + relative;
var newYear = this._visibleMonth.getFullYear() + Math.floor(newMonth / 12);
newMonth = (newMonth + 12) % 12;
this._visibleMonth = new Date(newYear, newMonth, 1);
this.drawMonth();
]]></body>
</method>
<!--===== mouseDown =====-->
<method name="mouseDown">
<parameter name="event"/>
<body><![CDATA[
var date = this.cellToDate(event.target.getAttribute("anonid"));
if (! date)
return;
this._selectNothing = false;
this._dragging = true;
this._mouseDownOn = date;
this.updateSelection(date, date);
]]></body>
</method>
<!--===== mouseUp =====-->
<method name="mouseUp">
<parameter name="event"/>
<body><![CDATA[
this._dragging = false;
this.fireRangeEvent();
]]></body>
</method>
<!--===== mouseMove =====-->
<method name="mouseMove">
<parameter name="event"/>
<body><![CDATA[
if (! this._dragging)
return;
var date = this.cellToDate(event.target.getAttribute("anonid"));
if (! date)
return;
this.updateSelection(this._mouseDownOn, date);
]]></body>
</method>
<!--===== updateSelection =====-->
<method name="updateSelection">
<parameter name="begin"/>
<parameter name="end"/>
<body><![CDATA[
var realBegin = begin;
var realEnd = end;
if (begin && end && begin.getTime() > end.getTime()) {
this._selectBegin = end;
this._selectEnd = begin;
} else {
this._selectBegin = begin;
this._selectEnd = end;
}
this.drawSelection();
]]></body>
</method>
<!--===== daysBetweenDates =====-->
<method name="daysBetweenDates">
<parameter name="a"/>
<parameter name="b"/>
<body>
var msDiff = a.getTime() - b.getTime();
return Math.floor(msDiff / 86400000); // 1000ms/s * 60s/m * 60m/h * 24h/d = 86400000ms/d
</body>
</method>
<!--===== suppressRangeEvents =====-->
<field name="suppressRangeEvents">false</field>
<!--===== fireRangeEvent =====-->
<method name="fireRangeEvent"><body><![CDATA[
if (this.suppressRangeEvents)
return true;
var event = document.createEvent("Events");
event.initEvent("selectionchanged", false, true);
// handle dom event handlers
var noCancel = this.dispatchEvent(event);
// handle any xml attribute event handlers
var handler = this.getAttribute("onselectionchanged");
if (handler != "") {
var fn = new Function("event", handler);
var returned = fn(event);
if (returned == false)
noCancel = false;
}
return noCancel;
]]></body></method>
<!--===== drawSelection =====-->
<method name="drawSelection"><body><![CDATA[
var beginIndex;
var endIndex;
if (this._selectNothing) {
beginIndex = -1;
endIndex = -1;
} else {
if (! this._selectBegin) {
beginIndex = 0;
} else {
beginIndex = this.daysBetweenDates(this._selectBegin, this._cell0Date);
}
if (! this._selectEnd) {
endIndex = this._numCells - 1;
} else {
endIndex = this.daysBetweenDates(this._selectEnd, this._cell0Date);
}
}
for (var i = 0; i < this._numCells; i ++) {
var sel = (i >= beginIndex && i <= endIndex);
if (sel != this._selected[i]) {
this._days[i].setAttribute("selected", sel ? "true" : "");
this._selected[i] = sel;
}
}
]]></body></method>
<!--===== cellToDate =====-->
<method name="cellToDate">
<parameter name="cellName"/>
<body><![CDATA[
if (! cellName)
return null;
var tail = cellName.substring(this._cellPrefix.length);
if (tail[0] < "0" || tail[0] > '9') {
return null;
}
var cellNumber = Number(tail);
var d = new Date(this._cell0Date);
d.setDate(d.getDate() + cellNumber);
return d;
]]></body>
</method>
<!--===== drawMonth =====-->
<method name="drawMonth"><body><![CDATA[
var curCell = 0;
var monthIndex = this._visibleMonth.getMonth();
var yearNumber = this._visibleMonth.getFullYear();
var firstOfMonth = new Date(yearNumber, monthIndex, 1);
// update title
document.getAnonymousElementByAttribute(this, "anonid", "monthtitle").value =
this._pref_shortMonthNames[monthIndex] + " " + yearNumber;
// first, fill in any days of the previous month in the first week
var numPrefixDays = firstOfMonth.getDay() - this._pref_firstDayOfWeek;
var curDay = firstOfMonth;
curDay.setDate(firstOfMonth.getDate() - numPrefixDays);
this._cell0Date = new Date(curDay); // save the first cell
for (var i = 0; i < numPrefixDays; i ++) {
var cell = document.getAnonymousElementByAttribute(this, "anonid", this._cellPrefix + curCell);
cell.setAttribute("month", "other");
cell.value = curDay.getDate();
curCell ++;
curDay.setDate(curDay.getDate() + 1);
}
// now fill in the rest of this month
while (curDay.getMonth() == monthIndex) {
var cell = document.getAnonymousElementByAttribute(this, "anonid", this._cellPrefix + curCell);
cell.setAttribute("month", "this");
cell.value = curDay.getDate();
curCell ++;
curDay.setDate(curDay.getDate() + 1);
}
// fill out the end of this week with next month
while (curDay.getDay() != this._pref_firstDayOfWeek) {
var cell = document.getAnonymousElementByAttribute(this, "anonid", this._cellPrefix + curCell);
cell.setAttribute("month", "other");
cell.value = curDay.getDate();
curCell ++;
curDay.setDate(curDay.getDate() + 1);
}
// fill the bottom row with days from the next month
while (curCell < this._numCells) {
var cell = document.getAnonymousElementByAttribute(this, "anonid", this._cellPrefix + curCell);
cell.setAttribute("month", "other");
cell.value = curDay.getDate();
curCell ++;
curDay.setDate(curDay.getDate() + 1);
}
this.drawSelection();
]]></body></method>
</implementation>
</binding> <!-- end calendar -->
#endif
</bindings>

View file

@ -289,25 +289,6 @@
#endif #endif
id="viewMenu" label="&views.label;"> id="viewMenu" label="&views.label;">
<menupopup id="viewMenuPopup"> <menupopup id="viewMenuPopup">
<!--
<menuitem id="viewDetails"
type="radio"
#ifdef XP_MACOSX
label="&view.detailsMacOSX.label;"
#else
label="&view.details.label;"
#endif
accesskey="&view.details.accesskey;">
</menuitem>
<menuseparator id="addonsSeparator"/>
<menuitem id="viewAddons"
command=""
label="&view.addons.label;"
accesskey="&view.addons.label;"/>
<menuseparator id="sortingSeparator"/>
-->
<menu id="viewColumns" <menu id="viewColumns"
label="&view.columns.label;" accesskey="&view.columns.accesskey;"> label="&view.columns.label;" accesskey="&view.columns.accesskey;">
@ -331,14 +312,6 @@
oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/> oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
</menupopup> </menupopup>
</menu> </menu>
<!--
<menuseparator id="groupingSeparator" observes="placesBC_grouping:separator"/>
<menuitem id="viewGroupNone" type="radio" name="group"
observes="placesBC_grouping:off"/>
<menuitem id="viewGroupGroup" type="radio" name="group"
observes="placesBC_grouping:on"/>
-->
</menupopup> </menupopup>
#ifdef XP_MACOSX #ifdef XP_MACOSX
</toolbarbutton> </toolbarbutton>
@ -441,18 +414,8 @@
<button id="saveSearch" class="small" <button id="saveSearch" class="small"
label="&saveSearch.label;" accesskey="&saveSearch.accesskey;" label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
command="OrganizerCommand_search:save"/> command="OrganizerCommand_search:save"/>
#ifdef PLACES_QUERY_BUILDER
<button id="organizerScopeBarExpander"
class="expander-down"
tooltiptext="&search.scopeBarExpanderDown.tooltip;"
tooltiptextdown="&search.scopeBarExpanderDown.tooltip;"
tooltiptextup="&search.scopeBarExpanderUp.tooltip;"
oncommand="PlacesQueryBuilder.toggleVisibility();"/>
</toolbar> </toolbar>
#include advancedSearch.inc
#else
</toolbar>
#endif
</vbox> </vbox>
<vbox flex="1"> <vbox flex="1">
<tree id="placeContent" class="placesTree" context="placesContext" <tree id="placeContent" class="placesTree" context="placesContext"

View file

@ -1140,22 +1140,26 @@
halfInd = Math.ceil(halfInd); halfInd = Math.ceil(halfInd);
translateX = 0 - this._scrollbox.getBoundingClientRect().right - translateX = 0 - this._scrollbox.getBoundingClientRect().right -
halfInd; halfInd;
if (dropPoint.beforeIndex == -1) if (this.firstChild) {
translateX += this.lastChild.getBoundingClientRect().left; if (dropPoint.beforeIndex == -1)
else if (this.childNodes.length) { translateX += this.lastChild.getBoundingClientRect().left;
translateX += this.childNodes[dropPoint.beforeIndex] else {
translateX += this.childNodes[dropPoint.beforeIndex]
.getBoundingClientRect().right; .getBoundingClientRect().right;
}
} }
} }
else { else {
halfInd = Math.floor(halfInd); halfInd = Math.floor(halfInd);
translateX = 0 - this._scrollbox.getBoundingClientRect().left + translateX = 0 - this._scrollbox.getBoundingClientRect().left +
halfInd; halfInd;
if (dropPoint.beforeIndex == -1) if (this.firstChild) {
translateX += this.lastChild.getBoundingClientRect().right; if (dropPoint.beforeIndex == -1)
else if (this.childNodes.length) { translateX += this.lastChild.getBoundingClientRect().right;
translateX += this.childNodes[dropPoint.beforeIndex] else {
.getBoundingClientRect().left; translateX += this.childNodes[dropPoint.beforeIndex]
.getBoundingClientRect().left;
}
} }
} }

View file

@ -1,12 +1,11 @@
browser.jar: browser.jar:
# Provide another URI for the bookmarkProperties dialog so we can persist the # Provide another URI for the bookmarkProperties dialog so we can persist the
# attributes separately # attributes separately
* content/browser/places/bookmarkProperties2.xul (content/bookmarkProperties.xul) * content/browser/places/bookmarkProperties2.xul (content/bookmarkProperties.xul)
* content/browser/places/places.xul (content/places.xul) * content/browser/places/places.xul (content/places.xul)
* content/browser/places/places.js (content/places.js) * content/browser/places/places.js (content/places.js)
* content/browser/places/places.xml (content/places.xml)
content/browser/places/places.css (content/places.css) content/browser/places/places.css (content/places.css)
* content/browser/places/organizer.css (content/organizer.css) content/browser/places/organizer.css (content/organizer.css)
* content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul) * content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul)
* content/browser/places/bookmarkProperties.js (content/bookmarkProperties.js) * content/browser/places/bookmarkProperties.js (content/bookmarkProperties.js)
* content/browser/places/placesOverlay.xul (content/placesOverlay.xul) * content/browser/places/placesOverlay.xul (content/placesOverlay.xul)
@ -16,10 +15,6 @@ browser.jar:
* content/browser/places/utils.js (content/utils.js) * content/browser/places/utils.js (content/utils.js)
* content/browser/places/controller.js (content/controller.js) * content/browser/places/controller.js (content/controller.js)
* content/browser/places/treeView.js (content/treeView.js) * content/browser/places/treeView.js (content/treeView.js)
* content/browser/places/demos/time.xul (content/demos/time.xul)
* content/browser/places/demos/time.html (content/demos/time.html)
* content/browser/places/demos/time.css (content/demos/time.css)
* content/browser/places/demos/time.js (content/demos/time.js)
# keep the Places version of the history sidebar at history/history-panel.xul # keep the Places version of the history sidebar at history/history-panel.xul
# to prevent having to worry about between versions of the browser # to prevent having to worry about between versions of the browser
* content/browser/history/history-panel.xul (content/history-panel.xul) * content/browser/history/history-panel.xul (content/history-panel.xul)

View file

@ -48,14 +48,16 @@ _CHROME_FILES = \
perf_large_delete.xul \ perf_large_delete.xul \
$(NULL) $(NULL)
# XXX disabled tests, not working properly yet # Disabled due to bad interactions with next tests.
# browser_ui_history_menu.js # browser_ui_locationbar.js
# browser_ui_locationbar.js # Disabled due to random failures.
# XXX disabled tests, random failures # browser_ui_bookmarks_sidebar.js
# browser_ui_bookmarks_sidebar.js
_BROWSER_TEST_FILES = \ _BROWSER_TEST_FILES = \
browser_ui_000_data.js \ browser_ui_000_data.js \
browser_ui_history_menu.js \
browser_ui_history_sidebar.js \ browser_ui_history_sidebar.js \
browser_ui_history_sidebar_2.js \
browser_ui_history_sidebar_3.js \
$(NULL) $(NULL)
libs:: $(_CHROME_FILES) libs:: $(_CHROME_FILES)

View file

@ -20,6 +20,7 @@
* *
* Contributor(s): * Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com> * Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
* *
* Alternatively, the contents of this file may be used under the terms of * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -62,13 +63,13 @@ var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService); getService(Ci.nsINavBookmarksService);
function add_visit(aURI, aDate) { function add_visit(aURI, aDate) {
var placeID = hs.addVisit(aURI, var visitId = hs.addVisit(aURI,
aDate, aDate,
null, // no referrer null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect false, // not redirect
0); 0);
return placeID; return visitId;
} }
function add_bookmark(aURI) { function add_bookmark(aURI) {
@ -86,7 +87,7 @@ var ptests = [];
/*********************** end header **********************/ /*********************** end header **********************/
const TEST_REPEAT_COUNT = 10; const TEST_REPEAT_COUNT = 6;
// test duration of bookmarks sidebar opening // test duration of bookmarks sidebar opening
ptests.push({ ptests.push({
@ -116,18 +117,19 @@ ptests.push({
var avgDuration = totalDuration/this.times.length; var avgDuration = totalDuration/this.times.length;
var report = make_test_report("open_bookmarks_sidebar", avgDuration); var report = make_test_report("open_bookmarks_sidebar", avgDuration);
ok(true, report); ok(true, report);
runNextTest(); setTimeout(runNextTest, 0);
} }
}); });
function test() { function test() {
// kick off tests // kick off tests
runNextTest(); setTimeout(runNextTest, 0);
} }
function runNextTest() { function runNextTest() {
if (ptests.length > 0) if (ptests.length > 0) {
ptests.shift().run(); ptests.shift().run();
}
else else
finish(); finish();
} }

View file

@ -20,6 +20,7 @@
* *
* Contributor(s): * Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com> * Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
* *
* Alternatively, the contents of this file may be used under the terms of * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -40,8 +41,6 @@ Tests the performance of opening the history menu.
*/ */
/*********************** begin header **********************/ /*********************** begin header **********************/
waitForExplicitFinish();
const TEST_IDENTIFIER = "ui-perf-test"; const TEST_IDENTIFIER = "ui-perf-test";
const TEST_SUITE = "places"; const TEST_SUITE = "places";
@ -60,14 +59,17 @@ var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService); getService(Ci.nsINavBookmarksService);
var historyMenu = document.getElementById("history-menu");
var historyPopup = document.getElementById("goPopup");
function add_visit(aURI, aDate) { function add_visit(aURI, aDate) {
var placeID = hs.addVisit(aURI, var visitId = hs.addVisit(aURI,
aDate, aDate,
null, // no referrer null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect false, // not redirect
0); 0);
return placeID; return visitId;
} }
function add_bookmark(aURI) { function add_bookmark(aURI) {
@ -85,38 +87,56 @@ var ptests = [];
/*********************** end header **********************/ /*********************** end header **********************/
const TEST_REPEAT_COUNT = 6;
// test duration of history menu opening // test duration of history menu opening
ptests.push({ ptests.push({
name: "open_history_menu", name: "open_history_menu",
times: [],
run: function() { run: function() {
var menu = document.getElementById("history-menu"); var self = this;
ok(menu, "history menu should exist!");
var start = Date.now(); var start = Date.now();
historyPopup.addEventListener("popupshown", function() {
var popup = document.getElementById("goPopup"); historyPopup.removeEventListener("popupshown", arguments.callee, true);
popup.addEventListener("popupshown", function() { executeSoon(function() {
var duration = Date.now() - start; var duration = Date.now() - start;
var report = make_test_report("open_history_menu", duration); historyPopup.hidePopup();
ok(true, report); historyMenu.open = false;
self.times.push(duration);
// clean up if (self.times.length == TEST_REPEAT_COUNT)
popup.removeEventListener("popupshown", arguments.callee, false); self.finish();
menu.open = false; else
self.run();
runNextTest(); });
}, false); }, true);
historyMenu.open = true;
// XXX does not work, is still open=false immediately after setting it to true historyPopup.openPopup();
//menu.open = true; },
finish: function() {
// XXX does nada processTestResult(this);
//EventUtils.sendMouseEvent({type:"click"}, "history-menu"); setTimeout(runNextTest, 0);
} }
}); });
function processTestResult(aTest) {
aTest.times.sort(); // sort the scores
aTest.times.pop(); // remove worst
aTest.times.shift(); // remove best
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
var avgDuration = totalDuration/aTest.times.length;
var report = make_test_report(aTest.name, avgDuration);
ok(true, report);
}
function test() { function test() {
// Skip test on Mac due to native menus.
if (navigator.platform.toLowerCase().indexOf("mac") != -1)
return;
waitForExplicitFinish();
// kick off tests // kick off tests
runNextTest(); setTimeout(runNextTest, 0);
} }
function runNextTest() { function runNextTest() {

View file

@ -20,6 +20,7 @@
* *
* Contributor(s): * Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com> * Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
* *
* Alternatively, the contents of this file may be used under the terms of * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -87,7 +88,7 @@ var ptests = [];
/*********************** end header **********************/ /*********************** end header **********************/
const TEST_REPEAT_COUNT = 10; const TEST_REPEAT_COUNT = 6;
// test duration of history sidebar opening // test duration of history sidebar opening
// default: bydayandsite // default: bydayandsite
@ -113,7 +114,7 @@ ptests.push({
}, },
finish: function() { finish: function() {
processTestResult(this); processTestResult(this);
runNextTest(); setTimeout(runNextTest, 0);
} }
}); });
@ -141,7 +142,7 @@ ptests.push({
}, },
finish: function() { finish: function() {
processTestResult(this); processTestResult(this);
runNextTest(); setTimeout(runNextTest, 0);
} }
}); });
@ -169,63 +170,7 @@ ptests.push({
}, },
finish: function() { finish: function() {
processTestResult(this); processTestResult(this);
runNextTest(); setTimeout(runNextTest, 0);
}
});
// byvisited
ptests.push({
name: "history_sidebar_byvisited",
times: [],
run: function() {
var self = this;
var start = Date.now();
sidebar.addEventListener("load", function() {
sidebar.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
var duration = Date.now() - start;
sidebar.contentDocument.getElementById("byvisited").doCommand();
toggleSidebar("viewHistorySidebar", false);
self.times.push(duration);
if (self.times.length == TEST_REPEAT_COUNT)
self.finish();
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
runNextTest();
}
});
// bylastvisited
ptests.push({
name: "history_sidebar_bylastvisited",
times: [],
run: function() {
var self = this;
var start = Date.now();
sidebar.addEventListener("load", function() {
sidebar.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
var duration = Date.now() - start;
sidebar.contentDocument.getElementById("bylastvisited").doCommand();
toggleSidebar("viewHistorySidebar", false);
self.times.push(duration);
if (self.times.length == TEST_REPEAT_COUNT)
self.finish();
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
runNextTest();
} }
}); });
@ -241,7 +186,7 @@ function processTestResult(aTest) {
function test() { function test() {
// kick off tests // kick off tests
runNextTest(); setTimeout(runNextTest, 0);
} }
function runNextTest() { function runNextTest() {

View file

@ -0,0 +1,142 @@
/* ***** 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 Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
*
* 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 ***** */
/*
Tests the performance of opening the History
sidebar in all the available views.
*/
/*********************** begin header **********************/
waitForExplicitFinish();
const TEST_IDENTIFIER = "ui-perf-test";
const TEST_SUITE = "places";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var sidebar = document.getElementById("sidebar");
function add_visit(aURI, aDate) {
var visitId = hs.addVisit(aURI,
aDate,
null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect
0);
return visitId;
}
function add_bookmark(aURI) {
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
return bId;
}
function make_test_report(testName, result, units) {
return [TEST_IDENTIFIER, TEST_SUITE, testName, result, units||"ms"].join(":");
}
// Each test is an obj w/ a name property and run method
var ptests = [];
/*********************** end header **********************/
const TEST_REPEAT_COUNT = 6;
// test duration of history sidebar opening
// byvisited
ptests.push({
name: "history_sidebar_byvisited",
times: [],
run: function() {
var self = this;
var start = Date.now();
sidebar.addEventListener("load", function() {
sidebar.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
var duration = Date.now() - start;
sidebar.contentDocument.getElementById("byvisited").doCommand();
toggleSidebar("viewHistorySidebar", false);
self.times.push(duration);
if (self.times.length == TEST_REPEAT_COUNT)
self.finish();
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
setTimeout(runNextTest, 0);
}
});
function processTestResult(aTest) {
aTest.times.sort(); // sort the scores
aTest.times.pop(); // remove worst
aTest.times.shift(); // remove best
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
var avgDuration = totalDuration/aTest.times.length;
var report = make_test_report(aTest.name, avgDuration);
ok(true, report);
}
function test() {
// kick off tests
setTimeout(runNextTest, 0);
}
function runNextTest() {
if (ptests.length > 0)
ptests.shift().run();
else
finish();
}

View file

@ -0,0 +1,142 @@
/* ***** 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 Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
*
* 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 ***** */
/*
Tests the performance of opening the History
sidebar in all the available views.
*/
/*********************** begin header **********************/
waitForExplicitFinish();
const TEST_IDENTIFIER = "ui-perf-test";
const TEST_SUITE = "places";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var sidebar = document.getElementById("sidebar");
function add_visit(aURI, aDate) {
var visitId = hs.addVisit(aURI,
aDate,
null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect
0);
return visitId;
}
function add_bookmark(aURI) {
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
return bId;
}
function make_test_report(testName, result, units) {
return [TEST_IDENTIFIER, TEST_SUITE, testName, result, units||"ms"].join(":");
}
// Each test is an obj w/ a name property and run method
var ptests = [];
/*********************** end header **********************/
const TEST_REPEAT_COUNT = 6;
// test duration of history sidebar opening
// bylastvisited
ptests.push({
name: "history_sidebar_bylastvisited",
times: [],
run: function() {
var self = this;
var start = Date.now();
sidebar.addEventListener("load", function() {
sidebar.removeEventListener("load", arguments.callee, true);
executeSoon(function() {
var duration = Date.now() - start;
sidebar.contentDocument.getElementById("bylastvisited").doCommand();
toggleSidebar("viewHistorySidebar", false);
self.times.push(duration);
if (self.times.length == TEST_REPEAT_COUNT)
self.finish();
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
setTimeout(runNextTest, 0);
}
});
function processTestResult(aTest) {
aTest.times.sort(); // sort the scores
aTest.times.pop(); // remove worst
aTest.times.shift(); // remove best
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
var avgDuration = totalDuration/aTest.times.length;
var report = make_test_report(aTest.name, avgDuration);
ok(true, report);
}
function test() {
// kick off tests
setTimeout(runNextTest, 0);
}
function runNextTest() {
if (ptests.length > 0)
ptests.shift().run();
else
finish();
}

View file

@ -20,6 +20,7 @@
* *
* Contributor(s): * Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com> * Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
* *
* Alternatively, the contents of this file may be used under the terms of * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -59,15 +60,20 @@ var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService); getService(Ci.nsINavHistoryService);
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService); getService(Ci.nsINavBookmarksService);
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var maxResults = prefs.getIntPref("browser.urlbar.maxRichResults");
var onSearchComplete = gURLBar.onSearchComplete;
function add_visit(aURI, aDate) { function add_visit(aURI, aDate) {
var placeID = hs.addVisit(aURI, var visitId = hs.addVisit(aURI,
aDate, aDate,
null, // no referrer null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect false, // not redirect
0); 0);
return placeID; return visitId;
} }
function add_bookmark(aURI) { function add_bookmark(aURI) {
@ -85,30 +91,61 @@ var ptests = [];
/*********************** end header **********************/ /*********************** end header **********************/
// test duration of history menu opening const TEST_REPEAT_COUNT = 6;
// test duration of locationbar searching
ptests.push({ ptests.push({
name: "open_locationbar_default", name: "open_locationbar_default",
times: [],
run: function() { run: function() {
var urlbar = document.getElementById("urlbar"); var self = this;
urlbar.addEventListener("onsearchcomplete", function() { var start = Date.now();
urlbar.removeEventListener("onsearchcomplete", arguments.callee, false); var acItemsCount = 1;
runNextTest(); gURLBar.onSearchComplete = function() {
}, false); executeSoon(function() {
var duration = Date.now() - start;
urlbar.value = "example"; self.times.push(duration);
urlbar.select(); if (self.times.length == TEST_REPEAT_COUNT)
EventUtils.synthesizeKey("VK_RETURN", {}); self.finish();
else
self.run();
});
};
window.focus();
gURLBar.focus();
var synthesizeSearch = function() {
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
EventUtils.synthesizeKey("e", {});
};
waitForFocus(synthesizeSearch);
},
finish: function() {
gURLBar.value = "";
processTestResult(this);
setTimeout(runNextTest, 0);
} }
}); });
function processTestResult(aTest) {
aTest.times.sort(); // sort the scores
aTest.times.pop(); // remove worst
aTest.times.shift(); // remove best
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
var avgDuration = totalDuration/aTest.times.length;
var report = make_test_report(aTest.name, avgDuration);
ok(true, report);
}
function test() { function test() {
// kick off tests // kick off tests
runNextTest(); setTimeout(runNextTest, 0);
} }
function runNextTest() { function runNextTest() {
if (ptests.length > 0) if (ptests.length > 0)
ptests.shift().run(); ptests.shift().run();
else else {
gURLBar.onSearchComplete = onSearchComplete;
finish(); finish();
}
} }

View file

@ -87,7 +87,7 @@ function test()
// Close the window if it's already open // Close the window if it's already open
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]. let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator); getService(Ci.nsIWindowMediator);
let win = wm.getMostRecentWindow("Places:Orgainzier"); let win = wm.getMostRecentWindow("Places:Organizer");
if (win) if (win)
win.close(); win.close();

View file

@ -329,3 +329,15 @@ function flush_main_thread_events()
while (tm.mainThread.hasPendingEvents()) while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false); tm.mainThread.processNextEvent(false);
} }
// These tests are known to randomly fail due to bug 507790 when database
// flushes are active, so we turn off syncing for them.
let randomFailingSyncTests = [
"test_browserGlue_smartBookmarks.js",
];
let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName;
if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) {
print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component.");
let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver);
sync.observe(null, "places-debug-stop-sync", null);
}

View file

@ -1,65 +0,0 @@
/* ***** 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 Places.
*
* The Initial Developer of the Original Code is
* Mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* 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 ***** */
// put cleanup of the bookmarks test here.
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

View file

@ -132,12 +132,15 @@ function continue_test() {
// Check distribution prefs have been created. // Check distribution prefs have been created.
do_check_eq(ps.getCharPref(PREF_DISTRIBUTION_ID), "516444"); do_check_eq(ps.getCharPref(PREF_DISTRIBUTION_ID), "516444");
// Remove the distribution file. do_test_finished();
}
do_register_cleanup(function() {
// Remove the distribution file, even if the test failed, otherwise all
// next tests will import it.
let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile); let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile);
iniFile.append("distribution"); iniFile.append("distribution");
iniFile.append("distribution.ini"); iniFile.append("distribution.ini");
iniFile.remove(false); iniFile.remove(false);
do_check_false(iniFile.exists()); do_check_false(iniFile.exists());
});
do_test_finished();
}

View file

@ -205,15 +205,16 @@ tests.push({
do_check_false(ps.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS)); do_check_false(ps.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
do_check_false(ps.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); do_check_false(ps.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
finish_test(); do_test_finished();
} }
}); });
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function finish_test() { function finish_test() {
// Simulate application closing to remove the idle observer and avoid leaks. // Clean up database from all bookmarks.
os.notifyObservers(null, "quit-application-granted", null); remove_all_bookmarks();
do_test_finished(); do_test_finished();
} }
@ -222,16 +223,13 @@ function next_test() {
// Clean up database from all bookmarks. // Clean up database from all bookmarks.
remove_all_bookmarks(); remove_all_bookmarks();
// Simulate application closing to remove the idle observer and avoid leaks.
os.notifyObservers(null, "quit-application-granted", null);
// nsBrowserGlue stops observing topics after first notification, // nsBrowserGlue stops observing topics after first notification,
// so we add back the observer to test additional runs. // so we add back the observer to test additional runs.
os.addObserver(bg, TOPIC_PLACES_INIT_COMPLETE, false); os.addObserver(bg, TOPIC_PLACES_INIT_COMPLETE, false);
// Execute next test. // Execute next test.
let test = tests.shift(); let test = tests.shift();
dump("\nTEST " + (++testIndex) + ": " + test.description); print("\nTEST " + (++testIndex) + ": " + test.description);
test.exec(); test.exec();
} }

View file

@ -139,7 +139,7 @@ tests.push({
do_check_eq(profileBookmarksJSONFile.lastModifiedTime, lastMod); do_check_eq(profileBookmarksJSONFile.lastModifiedTime, lastMod);
do_check_eq(profileBookmarksJSONFile.fileSize, fileSize); do_check_eq(profileBookmarksJSONFile.fileSize, fileSize);
finish_test(); do_test_finished();
} }
}); });

View file

@ -51,26 +51,34 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
#ifdef XP_MACOSX
<title></title>
#else
<title>&privatebrowsingpage.title;</title>
#endif
<link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/> <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
<link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/> <link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/>
<script type="application/x-javascript;version=1.7"><![CDATA[ <script type="application/x-javascript;version=1.7"><![CDATA[
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
window.__defineGetter__("mainWindow", function() { var pb = Cc["@mozilla.org/privatebrowsing;1"].
delete window.mainWindow; getService(Ci.nsIPrivateBrowsingService);
return window.mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation) if (!pb.privateBrowsingEnabled) {
.QueryInterface(Ci.nsIDocShellTreeItem) document.title = "]]>&privatebrowsingpage.title.normal;<![CDATA[";
.rootTreeItem setFavIcon("chrome://global/skin/icons/question-16.png");
.QueryInterface(Ci.nsIInterfaceRequestor) } else {
.getInterface(Ci.nsIDOMWindow); #ifndef XP_MACOSX
}); document.title = "]]>&privatebrowsingpage.title;<![CDATA[";
#endif
setFavIcon("chrome://browser/skin/Privacy-16.png");
}
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
// Focus the location bar
mainWindow.focusAndSelectUrlBar();
function openSanitizeDialog() { function openSanitizeDialog() {
let browserGlue = Cc["@mozilla.org/browser/browserglue;1"]. let browserGlue = Cc["@mozilla.org/browser/browserglue;1"].
@ -83,21 +91,17 @@
icon.setAttribute("rel", "icon"); icon.setAttribute("rel", "icon");
icon.setAttribute("type", "image/png"); icon.setAttribute("type", "image/png");
icon.setAttribute("href", url); icon.setAttribute("href", url);
document.getElementsByTagName("head")[0].appendChild(icon); var head = document.getElementsByTagName("head")[0];
head.insertBefore(icon, head.firstChild);
} }
function onLoad() { document.addEventListener("DOMContentLoaded", function () {
let selector; let selector;
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
if (!pb.privateBrowsingEnabled) { if (!pb.privateBrowsingEnabled) {
document.body.setAttribute("class", "normal"); document.body.setAttribute("class", "normal");
document.title = document.body.getAttribute("normaltitle");
setFavIcon("chrome://global/skin/icons/question-16.png");
selector = ".showPrivate"; selector = ".showPrivate";
} }
else { else {
setFavIcon("chrome://browser/skin/Privacy-16.png");
selector = ".showNormal"; selector = ".showNormal";
} }
@ -113,18 +117,12 @@
let moreInfoLink = document.getElementById("moreInfoLink"); let moreInfoLink = document.getElementById("moreInfoLink");
if (moreInfoLink) if (moreInfoLink)
moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing"); moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing");
}, false);
// Focus the location bar
if (mainWindow.gURLBar)
mainWindow.gURLBar.focus();
}
]]></script> ]]></script>
</head> </head>
<body dir="&locale.dir;" <body dir="&locale.dir;"
class="private" class="private">
onload="onLoad();"
normaltitle="&privatebrowsingpage.title.normal;">
<!-- PAGE CONTAINER (for styling purposes only) --> <!-- PAGE CONTAINER (for styling purposes only) -->
<div id="errorPageContainer"> <div id="errorPageContainer">

View file

@ -124,6 +124,9 @@ PrivateBrowsingService.prototype = {
// List of view source window URIs for restoring later // List of view source window URIs for restoring later
_viewSrcURLs: [], _viewSrcURLs: [],
// List of nsIXULWindows we are going to be closing during the transition
_windowsToClose: [],
// XPCOM registration // XPCOM registration
classDescription: "PrivateBrowsing Service", classDescription: "PrivateBrowsing Service",
contractID: "@mozilla.org/privatebrowsing;1", contractID: "@mozilla.org/privatebrowsing;1",
@ -208,12 +211,20 @@ PrivateBrowsingService.prototype = {
// just in case the only remaining window after setBrowserState is different. // just in case the only remaining window after setBrowserState is different.
// it probably shouldn't be with the current sessionstore impl, but we shouldn't // it probably shouldn't be with the current sessionstore impl, but we shouldn't
// rely on behaviour the API doesn't guarantee // rely on behaviour the API doesn't guarantee
let browser = this._getBrowserWindow().gBrowser; browserWindow = this._getBrowserWindow();
let browser = browserWindow.gBrowser;
// this ensures a clean slate from which to transition into or out of // this ensures a clean slate from which to transition into or out of
// private browsing // private browsing
browser.addTab(); browser.addTab();
browser.getBrowserForTab(browser.tabContainer.firstChild).stop();
browser.removeTab(browser.tabContainer.firstChild); browser.removeTab(browser.tabContainer.firstChild);
browserWindow.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow)
.docShell.contentViewer.resetCloseWindow();
} }
} }
} }
@ -298,6 +309,20 @@ PrivateBrowsingService.prototype = {
getMostRecentWindow("navigator:browser"); getMostRecentWindow("navigator:browser");
}, },
_ensureCanCloseWindows: function PBS__ensureCanCloseWindows() {
let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
let windowsEnum = windowMediator.getXULWindowEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let win = windowsEnum.getNext().QueryInterface(Ci.nsIXULWindow);
if (win.docShell.contentViewer.permitUnload(true))
this._windowsToClose.push(win);
else
throw Cr.NS_ERROR_ABORT;
}
},
_closePageInfoWindows: function PBS__closePageInfoWindows() { _closePageInfoWindows: function PBS__closePageInfoWindows() {
let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"]. let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator). getService(Ci.nsIWindowMediator).
@ -401,6 +426,8 @@ PrivateBrowsingService.prototype = {
return; return;
} }
this._ensureCanCloseWindows();
this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart"); this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
this._inPrivateBrowsing = val != false; this._inPrivateBrowsing = val != false;
@ -422,9 +449,16 @@ PrivateBrowsingService.prototype = {
this._onAfterPrivateBrowsingModeChange(); this._onAfterPrivateBrowsingModeChange();
} }
} catch (ex) { } catch (ex) {
Cu.reportError("Exception thrown while processing the " + // We aborted the transition to/from private browsing, we must restore the
"private browsing mode change request: " + ex.toString()); // beforeunload handling on all the windows for which we switched it off.
for (let i = 0; i < this._windowsToClose.length; i++)
this._windowsToClose[i].docShell.contentViewer.resetCloseWindow();
// We don't log an error when the transition is canceled from beforeunload
if (ex != Cr.NS_ERROR_ABORT)
Cu.reportError("Exception thrown while processing the " +
"private browsing mode change request: " + ex.toString());
} finally { } finally {
this._windowsToClose = [];
this._alreadyChangingMode = false; this._alreadyChangingMode = false;
} }
}, },

View file

@ -80,19 +80,11 @@ function test() {
let tab = gBrowser.selectedTab = gBrowser.addTab(); let tab = gBrowser.selectedTab = gBrowser.addTab();
let browser = gBrowser.selectedBrowser; let browser = gBrowser.selectedBrowser;
browser.stop();
// ensure that the test is run after the titlebar has been updated // ensure that the test is run after the titlebar has been updated
let timer = null; browser.addEventListener("pageshow", function () {
let _updateTitlebar = gBrowser.updateTitlebar; browser.removeEventListener("pageshow", arguments.callee, false);
gBrowser.updateTitlebar = function() { executeSoon(function () {
if (timer) {
timer.cancel();
timer = null;
}
timer = Cc["@mozilla.org/timer;1"].
createInstance(Ci.nsITimer);
timer.initWithCallback(function () {
_updateTitlebar.apply(gBrowser, arguments);
gBrowser.updateTitlebar = _updateTitlebar;
is(document.title, expected_title, "The window title for " + url + is(document.title, expected_title, "The window title for " + url +
" is correct (" + (insidePB ? "inside" : "outside") + " is correct (" + (insidePB ? "inside" : "outside") +
" private browsing mode)"); " private browsing mode)");
@ -115,8 +107,8 @@ function test() {
setTimeout(funcNext, 0); setTimeout(funcNext, 0);
}; };
}, false); }, false);
}, 300, Ci.nsITimer.TYPE_ONE_SHOT); });
}; }, false);
browser.loadURI(url); browser.loadURI(url);
} }

View file

@ -564,7 +564,6 @@ function test_cache_cleared()
observe: function(aSubject, aTopic, aData) observe: function(aSubject, aTopic, aData)
{ {
os.removeObserver(observer, "cacheservice:empty-cache"); os.removeObserver(observer, "cacheservice:empty-cache");
shutdownPlaces();
do_test_finished(); do_test_finished();
} }
}; };

View file

@ -155,6 +155,4 @@ function do_test()
// And check our data // And check our data
for (let i = 0; i < data.length; i++) for (let i = 0; i < data.length; i++)
check_active_download(data[i].source, !data[i].removed); check_active_download(data[i].source, !data[i].removed);
shutdownPlaces();
} }

View file

@ -110,15 +110,6 @@ function cleanUp()
} }
cleanUp(); cleanUp();
/**
* Finalize Places statements during quit-application in order to prevent leaks
*/
function shutdownPlaces() {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application", null);
}
var PRIVATEBROWSING_CONTRACT_ID; var PRIVATEBROWSING_CONTRACT_ID;
function run_test_on_all_services() { function run_test_on_all_services() {
var contractIDs = [ var contractIDs = [

View file

@ -269,6 +269,8 @@ SessionStoreService.prototype = {
// make sure that at least the first window doesn't have anything hidden // make sure that at least the first window doesn't have anything hidden
delete this._initialState.windows[0].hidden; delete this._initialState.windows[0].hidden;
// Since nothing is hidden in the first window, it cannot be a popup
delete this._initialState.windows[0].isPopup;
} }
catch (ex) { debug("The session file is invalid: " + ex); } catch (ex) { debug("The session file is invalid: " + ex); }
} }

View file

@ -44,12 +44,14 @@ function test() {
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
is(doc.getElementById("storageTestItem").textContent, "PENDING", is(doc.getElementById("storageTestItem").textContent, "PENDING",
"sessionStorage value has been set"); "sessionStorage value has been set");
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc2 = tab2.linkedBrowser.contentDocument; let doc2 = tab2.linkedBrowser.contentDocument;
is(doc2.getElementById("storageTestItem").textContent, "SUCCESS", is(doc2.getElementById("storageTestItem").textContent, "SUCCESS",
"sessionStorage value has been duplicated"); "sessionStorage value has been duplicated");

View file

@ -99,11 +99,13 @@ function test() {
"browser/components/sessionstore/test/browser/browser_346337_sample.html"; "browser/components/sessionstore/test/browser/browser_346337_sample.html";
let tab = tabbrowser.addTab(testURL); let tab = tabbrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
for (let xpath in fieldList) for (let xpath in fieldList)
setFormValue(tab, xpath, fieldList[xpath]); setFormValue(tab, xpath, fieldList[xpath]);
let tab2 = tabbrowser.duplicateTab(tab); let tab2 = tabbrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
for (let xpath in fieldList) for (let xpath in fieldList)
ok(compareFormValue(tab2, xpath, fieldList[xpath]), ok(compareFormValue(tab2, xpath, fieldList[xpath]),
"The value for \"" + xpath + "\" was correctly restored"); "The value for \"" + xpath + "\" was correctly restored");
@ -114,6 +116,7 @@ function test() {
tab = undoCloseTab(); tab = undoCloseTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
for (let xpath in fieldList) for (let xpath in fieldList)
if (fieldList[xpath]) if (fieldList[xpath])
ok(!compareFormValue(tab, xpath, fieldList[xpath]), ok(!compareFormValue(tab, xpath, fieldList[xpath]),

View file

@ -45,6 +45,7 @@ function test() {
key = "Unique name: " + Math.random(); key = "Unique name: " + Math.random();
value = "Unique value: " + Date.now(); value = "Unique value: " + Date.now();
let tab = tabbrowser.addTab(); let tab = tabbrowser.addTab();
tab.linkedBrowser.stop();
// test adding // test adding
ok(test(function() ss.setTabValue(tab, key, value)), "store a tab value"); ok(test(function() ss.setTabValue(tab, key, value)), "store a tab value");
@ -74,6 +75,7 @@ function test() {
let testURL = "about:"; let testURL = "about:";
tab = tabbrowser.addTab(testURL); tab = tabbrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// make sure that the next closed tab will increase getClosedTabCount // make sure that the next closed tab will increase getClosedTabCount
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1); gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
@ -89,6 +91,7 @@ function test() {
ok(tab, "undoCloseTab doesn't throw") ok(tab, "undoCloseTab doesn't throw")
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
is(this.currentURI.spec, testURL, "correct tab was reopened"); is(this.currentURI.spec, testURL, "correct tab was reopened");
// clean up // clean up

View file

@ -248,6 +248,7 @@ function test() {
// The previously closed window should be restored // The previously closed window should be restored
newWin = openDialog(location, "_blank", CHROME_FEATURES); newWin = openDialog(location, "_blank", CHROME_FEATURES);
newWin.addEventListener("load", function() { newWin.addEventListener("load", function() {
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1, is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
"Restored window in-session with otherpopup windows around"); "Restored window in-session with otherpopup windows around");
@ -281,6 +282,7 @@ function test() {
// The previously closed window should NOT be restored // The previously closed window should NOT be restored
newWin = openDialog(location, "_blank", CHROME_FEATURES); newWin = openDialog(location, "_blank", CHROME_FEATURES);
newWin.addEventListener("load", function() { newWin.addEventListener("load", function() {
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
is(newWin.gBrowser.browsers.length, 1, is(newWin.gBrowser.browsers.length, 1,
"Did not restore in private browing mode"); "Did not restore in private browing mode");
@ -293,6 +295,7 @@ function test() {
newWin = openDialog(location, "_blank", CHROME_FEATURES); newWin = openDialog(location, "_blank", CHROME_FEATURES);
newWin.addEventListener("load", function() { newWin.addEventListener("load", function() {
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1, is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
"Restored after leaving private browsing again"); "Restored after leaving private browsing again");
@ -334,6 +337,7 @@ function test() {
// open a new window the previously closed window should be restored to // open a new window the previously closed window should be restored to
newWin = openDialog(location, "_blank", CHROME_FEATURES); newWin = openDialog(location, "_blank", CHROME_FEATURES);
newWin.addEventListener("load", function() { newWin.addEventListener("load", function() {
this.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1, is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
"Restored window and associated tabs in session"); "Restored window and associated tabs in session");
@ -364,6 +368,7 @@ function test() {
// gets a chance. // gets a chance.
let popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]); let popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
popup.addEventListener("load", function() { popup.addEventListener("load", function() {
this.removeEventListener("load", arguments.callee, true);
is(popup.gBrowser.browsers.length, 1, is(popup.gBrowser.browsers.length, 1,
"Did not restore the popup window (1)"); "Did not restore the popup window (1)");
popup.BrowserTryToCloseWindow(); popup.BrowserTryToCloseWindow();

View file

@ -57,6 +57,7 @@ function test() {
ss.setTabState(tab, "{ entries: [] }"); ss.setTabState(tab, "{ entries: [] }");
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
ok(history.count == 0, "the tab was restored without any history whatsoever"); ok(history.count == 0, "the tab was restored without any history whatsoever");
tabbrowser.removeTab(tab); tabbrowser.removeTab(tab);

View file

@ -21,6 +21,7 @@ function test() {
let tab = tabbrowser.addTab(testURL); let tab = tabbrowser.addTab(testURL);
ss.setTabValue(tab, key, value); ss.setTabValue(tab, key, value);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// get the tab's state // get the tab's state
let state = ss.getTabState(tab); let state = ss.getTabState(tab);
ok(state, "get the tab's state"); ok(state, "get the tab's state");
@ -51,6 +52,7 @@ function test() {
// set the tab's state // set the tab's state
ss.setTabState(tab2, state.toSource()); ss.setTabState(tab2, state.toSource());
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// verify the correctness of the restored tab // verify the correctness of the restored tab
ok(ss.getTabValue(tab2, key2) == value2 && this.currentURI.spec == testURL, ok(ss.getTabValue(tab2, key2) == value2 && this.currentURI.spec == testURL,
"the tab's state was correctly restored"); "the tab's state was correctly restored");
@ -64,6 +66,7 @@ function test() {
tabbrowser.removeTab(tab2); tabbrowser.removeTab(tab2);
duplicateTab.linkedBrowser.addEventListener("load", function(aEvent) { duplicateTab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// verify the correctness of the duplicated tab // verify the correctness of the duplicated tab
ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL, ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL,
"correctly duplicated the tab's state"); "correctly duplicated the tab's state");

View file

@ -63,7 +63,7 @@ function test() {
newWin.gBrowser.removeEventListener("load", arguments.callee, true); newWin.gBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
newWin.gBrowser.addTab(); newWin.gBrowser.addTab().linkedBrowser.stop();
executeSoon(function() { executeSoon(function() {
// mark the window with some unique data to be restored later on // mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey, uniqueValue); ss.setWindowValue(newWin, uniqueKey, uniqueValue);
@ -87,6 +87,7 @@ function test() {
"The reopened window was removed from Recently Closed Windows"); "The reopened window was removed from Recently Closed Windows");
newWin2.addEventListener("load", function(aEvent) { newWin2.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, false);
newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) { newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) {
newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true); newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true);
@ -142,12 +143,14 @@ function test() {
let url = "http://window" + windowsToOpen.length + ".example.com"; let url = "http://window" + windowsToOpen.length + ".example.com";
let window = openDialog(location, "_blank", settings, url); let window = openDialog(location, "_blank", settings, url);
window.addEventListener("load", function(aEvent) { window.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
window.gBrowser.addEventListener("load", function(aEvent) { window.gBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// the window _should_ have state with a tab of url, but it doesn't // the window _should_ have state with a tab of url, but it doesn't
// always happend before window.close(). addTab ensure we don't treat // always happend before window.close(). addTab ensure we don't treat
// this window as a stateless window // this window as a stateless window
window.gBrowser.addTab(); window.gBrowser.addTab();
window.gBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
window.close(); window.close();
executeSoon(function() { executeSoon(function() {

View file

@ -21,6 +21,7 @@
* Contributor(s): * Contributor(s):
* Ehsan Akhgari <ehsan.akhgari@gmail.com> * Ehsan Akhgari <ehsan.akhgari@gmail.com>
* Paul OShannessy <paul@oshannessy.com> * Paul OShannessy <paul@oshannessy.com>
* Marco Bonardo <mak77@bonardo.net>
* *
* Alternatively, the contents of this file may be used under the terms of * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,20 +40,20 @@
function test() { function test() {
/** Private Browsing Test for Bug 394759 **/ /** Private Browsing Test for Bug 394759 **/
// test setup
waitForExplicitFinish(); waitForExplicitFinish();
// private browsing service // Setup.
let pb = Cc["@mozilla.org/privatebrowsing;1"]. let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService); getService(Ci.nsIPrivateBrowsingService);
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
// Remove the sessionstore.js file before setting the interval to 0
let profilePath = Cc["@mozilla.org/file/directory_service;1"]. let profilePath = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties). getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile); get("ProfD", Ci.nsIFile);
// sessionstore service
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
// Remove the sessionstore.js file before setting the interval to 0
let sessionStoreJS = profilePath.clone(); let sessionStoreJS = profilePath.clone();
sessionStoreJS.append("sessionstore.js"); sessionStoreJS.append("sessionstore.js");
if (sessionStoreJS.exists()) if (sessionStoreJS.exists())
@ -79,93 +80,98 @@ function test() {
let closedWindowCount = ss.getClosedWindowCount(); let closedWindowCount = ss.getClosedWindowCount();
is(closedWindowCount, 0, "Correctly set window count"); is(closedWindowCount, 0, "Correctly set window count");
let testURL_A = "about:config"; // Prevent VM timers issues, cache now and increment it manually.
let testURL_B = "about:mozilla"; const NOW = Date.now();
let uniqueKey_A = "bug 394759 Non-PB"; const TESTS = [
let uniqueValue_A = "unik" + Date.now(); { url: "about:config",
let uniqueKey_B = "bug 394759 PB"; key: "bug 394759 Non-PB",
let uniqueValue_B = "uniq" + Date.now(); value: "uniq" + (++NOW) },
{ url: "about:mozilla",
key: "bug 394759 PB",
// Open a window value: "uniq" + (++NOW) },
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_A); ];
newWin.addEventListener("load", function(aEvent) {
newWin.removeEventListener("load", arguments.callee, false);
newWin.gBrowser.addEventListener("load", function(aEvent) {
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
info("Window has been loaded");
executeSoon(function() {
newWin.gBrowser.addTab();
executeSoon(function() {
// mark the window with some unique data to be restored later on
ss.setWindowValue(newWin, uniqueKey_A, uniqueValue_A);
newWin.close();
// ensure that we incremented # of close windows
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The closed window was added to the list");
// ensure we added window to undo list
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1,
"The closed window data was stored correctly");
// enter private browsing mode
pb.privateBrowsingEnabled = true;
ok(pb.privateBrowsingEnabled, "private browsing enabled");
// ensure that we have 0 undo windows when entering PB
is(ss.getClosedWindowCount(), 0,
"Recently Closed Windows are removed when entering Private Browsing");
is(ss.getClosedWindowData(), "[]",
"Recently Closed Windows data is cleared when entering Private Browsing");
// open another window in PB
let pbWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_B);
pbWin.addEventListener("load", function(aEvent) {
pbWin.removeEventListener("load", arguments.callee, false);
pbWin.gBrowser.addEventListener("load", function(aEvent) {
pbWin.gBrowser.removeEventListener("load", arguments.callee, true);
function openWindowAndTest(aTestIndex, aRunNextTestInPBMode) {
info("Opening new window");
let windowObserver = {
observe: function(aSubject, aTopic, aData) {
if (aTopic === "domwindowopened") {
ww.unregisterNotification(this);
info("New window has been opened");
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad(event) {
win.removeEventListener("load", onLoad, false);
info("New window has been loaded");
win.gBrowser.addEventListener("load", function(aEvent) {
win.gBrowser.removeEventListener("load", arguments.callee, true);
info("New window browser has been loaded");
executeSoon(function() { executeSoon(function() {
// Add another tab, though it's not strictly needed // Add a tab.
pbWin.gBrowser.addTab(); win.gBrowser.addTab();
executeSoon(function() { executeSoon(function() {
// mark the window with some unique data to be restored later on // Mark the window with some unique data to be restored later on.
ss.setWindowValue(pbWin, uniqueKey_B, uniqueValue_B); ss.setWindowValue(win, TESTS[aTestIndex].key, TESTS[aTestIndex].value);
pbWin.close(); win.close();
// ensure we added window to undo list // Ensure that we incremented # of close windows.
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_B) > -1,
"The closed window data was stored correctly in PB mode");
// exit private browsing mode
pb.privateBrowsingEnabled = false;
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
// ensure that we still have the closed windows from before
is(ss.getClosedWindowCount(), closedWindowCount + 1, is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The correct number of recently closed windows were restored " + "The closed window was added to the list");
"when exiting PB mode");
// Ensure we added window to undo list.
let data = JSON.parse(ss.getClosedWindowData())[0]; let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(uniqueValue_A) > -1, ok(data.toSource().indexOf(TESTS[aTestIndex].value) > -1,
"The data associated with the recently closed window was " + "The closed window data was stored correctly");
"restored when exiting PB mode");
// cleanup if (aRunNextTestInPBMode) {
gPrefService.clearUserPref("browser.sessionstore.interval"); // Enter private browsing mode.
finish(); pb.privateBrowsingEnabled = true;
ok(pb.privateBrowsingEnabled, "private browsing enabled");
// Ensure that we have 0 undo windows when entering PB.
is(ss.getClosedWindowCount(), 0,
"Recently Closed Windows are removed when entering Private Browsing");
is(ss.getClosedWindowData(), "[]",
"Recently Closed Windows data is cleared when entering Private Browsing");
}
else {
// Exit private browsing mode.
pb.privateBrowsingEnabled = false;
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
// Ensure that we still have the closed windows from before.
is(ss.getClosedWindowCount(), closedWindowCount + 1,
"The correct number of recently closed windows were restored " +
"when exiting PB mode");
let data = JSON.parse(ss.getClosedWindowData())[0];
ok(data.toSource().indexOf(TESTS[aTestIndex].value) > -1,
"The data associated with the recently closed window was " +
"restored when exiting PB mode");
}
if (aTestIndex == TESTS.length - 1) {
// Cleanup and finish.
gPrefService.clearUserPref("browser.sessionstore.interval");
finish();
}
else {
// Run next test.
openWindowAndTest(aTestIndex + 1, !aRunNextTestInPBMode);
}
}); });
}); });
}, true); }, true);
}, false); }, false);
}); }
}); }
}, true); };
}, false); ww.registerNotification(windowObserver);
// Open a window.
openDialog(location, "_blank", "chrome,all,dialog=no", TESTS[aTestIndex].url);
}
openWindowAndTest(0, true);
} }

View file

@ -45,6 +45,7 @@ function test() {
let tab = gBrowser.addTab(testUrl); let tab = gBrowser.addTab(testUrl);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
// enable all stylesheets and verify that they're correctly persisted // enable all stylesheets and verify that they're correctly persisted
Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) { Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) {
pendingCount++; pendingCount++;
@ -53,6 +54,7 @@ function test() {
let newTab = gBrowser.duplicateTab(tab); let newTab = gBrowser.duplicateTab(tab);
newTab.linkedBrowser.addEventListener("load", function(aEvent) { newTab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets, let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets,
function(aSS) !aSS.disabled); function(aSS) !aSS.disabled);
let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1; let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1;
@ -72,6 +74,7 @@ function test() {
tab.linkedBrowser.markupDocumentViewer.authorStyleDisabled = true; tab.linkedBrowser.markupDocumentViewer.authorStyleDisabled = true;
let newTab = gBrowser.duplicateTab(tab); let newTab = gBrowser.duplicateTab(tab);
newTab.linkedBrowser.addEventListener("load", function(aEvent) { newTab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
is(newTab.linkedBrowser.markupDocumentViewer.authorStyleDisabled, true, is(newTab.linkedBrowser.markupDocumentViewer.authorStyleDisabled, true,
"disabled all stylesheets"); "disabled all stylesheets");

View file

@ -47,6 +47,7 @@ function test() {
// set a unique value on a new, blank tab // set a unique value on a new, blank tab
var tab = gBrowser.addTab(); var tab = gBrowser.addTab();
tab.linkedBrowser.stop();
ss.setTabValue(tab, uniqueName, uniqueValue); ss.setTabValue(tab, uniqueName, uniqueValue);
let valueWasCleaned = false; let valueWasCleaned = false;

View file

@ -51,6 +51,7 @@ function test() {
"browser/components/sessionstore/test/browser/browser_454908_sample.html"; "browser/components/sessionstore/test/browser/browser_454908_sample.html";
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
for (let id in fieldValues) for (let id in fieldValues)
doc.getElementById(id).value = fieldValues[id]; doc.getElementById(id).value = fieldValues[id];
@ -59,6 +60,7 @@ function test() {
tab = undoCloseTab(); tab = undoCloseTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
for (let id in fieldValues) { for (let id in fieldValues) {
let node = doc.getElementById(id); let node = doc.getElementById(id);

View file

@ -46,6 +46,7 @@ function test() {
"browser/components/sessionstore/test/browser/browser_456342_sample.xhtml"; "browser/components/sessionstore/test/browser/browser_456342_sample.xhtml";
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
gBrowser.removeTab(tab); gBrowser.removeTab(tab);
let ss = Cc["@mozilla.org/browser/sessionstore;1"] let ss = Cc["@mozilla.org/browser/sessionstore;1"]

View file

@ -60,7 +60,8 @@ function test() {
// wait for all frames to load (and reload!) completely // wait for all frames to load (and reload!) completely
if (frameCount++ < 2) if (frameCount++ < 2)
return; return;
this.removeEventListener("load", arguments.callee, true);
let maxWait = Date.now() + 1000; let maxWait = Date.now() + 1000;
executeSoon(function() { executeSoon(function() {
let iframes = tab2.linkedBrowser.contentWindow.frames; let iframes = tab2.linkedBrowser.contentWindow.frames;

View file

@ -9,6 +9,7 @@
<script type="application/javascript"> <script type="application/javascript">
frames[0].addEventListener("DOMContentLoaded", function() { frames[0].addEventListener("DOMContentLoaded", function() {
frames[0].removeEventListener("DOMContentLoaded", arguments.callee, false);
frames[0].document.designMode = "on"; frames[0].document.designMode = "on";
frames[0].document.__defineGetter__("designMode", function() { frames[0].document.__defineGetter__("designMode", function() {
// inject a cross domain file ... // inject a cross domain file ...

View file

@ -67,6 +67,7 @@ function test() {
// open a window and add the above closed tab list // open a window and add the above closed tab list
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no"); let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) { newWin.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, false);
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length); test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true); ss.setWindowState(newWin, JSON.stringify(test_state), true);

View file

@ -48,6 +48,7 @@ function test() {
executeSoon(function() { executeSoon(function() {
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("461743", function(aEvent) { tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");
executeSoon(function() { executeSoon(function() {

View file

@ -30,6 +30,10 @@
var event = document.createEvent("MessageEvent"); var event = document.createEvent("MessageEvent");
event.initMessageEvent("461743", true, false, "done", location.href, "", window); event.initMessageEvent("461743", true, false, "done", location.href, "", window);
document.dispatchEvent(event); document.dispatchEvent(event);
frames[0].document.removeEventListener("DOMNodeInserted", loadChrome, true);
frames[0].document.removeEventListener("DOMNodeInserted", delay, true);
frames[0].document.removeEventListener("DOMNodeInserted", loadExploit, true);
frames[0].document.removeEventListener("DOMNodeInserted", done, true);
} }
frames[0].document.addEventListener("DOMNodeInserted", loadChrome, true); frames[0].document.addEventListener("DOMNodeInserted", loadChrome, true);

View file

@ -69,7 +69,8 @@ function test() {
// wait for all frames to load (and reload!) completely // wait for all frames to load (and reload!) completely
if (frameCount++ < 4) if (frameCount++ < 4)
return; return;
this.removeEventListener("load", arguments.callee, true);
let win = tab2.linkedBrowser.contentWindow; let win = tab2.linkedBrowser.contentWindow;
isnot(win.frames[0].document.getElementById("original").value, uniqueValue, isnot(win.frames[0].document.getElementById("original").value, uniqueValue,
"subframes must match URL to get text restored"); "subframes must match URL to get text restored");

View file

@ -69,7 +69,8 @@ function test() {
// wait for all frames to load completely // wait for all frames to load completely
if (frameCount++ < 5) if (frameCount++ < 5)
return; return;
this.removeEventListener("load", arguments.callee, true);
let doc = tab2.linkedBrowser.contentDocument; let doc = tab2.linkedBrowser.contentDocument;
let win = tab2.linkedBrowser.contentWindow; let win = tab2.linkedBrowser.contentWindow;
isnot(doc.getElementById("out1").value, isnot(doc.getElementById("out1").value,

View file

@ -75,6 +75,7 @@ function test() {
// open a window and add the above closed tab list // open a window and add the above closed tab list
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no"); let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) { newWin.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, false);
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
test_state.windows[0]._closedTabs.length); test_state.windows[0]._closedTabs.length);
ss.setWindowState(newWin, JSON.stringify(test_state), true); ss.setWindowState(newWin, JSON.stringify(test_state), true);

View file

@ -54,6 +54,7 @@ function test() {
frameCount = 0; frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_a", function(aEvent) { tab2.linkedBrowser.addEventListener("464620_a", function(aEvent) {
tab2.linkedBrowser.removeEventListener("464620_a", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");
// let form restoration complete and take into account the // let form restoration complete and take into account the

View file

@ -54,6 +54,7 @@ function test() {
frameCount = 0; frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_b", function(aEvent) { tab2.linkedBrowser.addEventListener("464620_b", function(aEvent) {
tab2.linkedBrowser.removeEventListener("464620_b", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");
// let form restoration complete and take into account the // let form restoration complete and take into account the

View file

@ -49,6 +49,7 @@ function test() {
// open a window and set a value on it // open a window and set a value on it
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no"); let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) { newWin.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, false);
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1); ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] }; let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };

View file

@ -45,12 +45,14 @@ function test() {
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("reverse_thief").value = "/home/user/secret2"; doc.getElementById("reverse_thief").value = "/home/user/secret2";
doc.getElementById("bystander").value = testPath; doc.getElementById("bystander").value = testPath;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
doc = tab2.linkedBrowser.contentDocument; doc = tab2.linkedBrowser.contentDocument;
is(doc.getElementById("thief").value, "", is(doc.getElementById("thief").value, "",
"file path wasn't set to text field value"); "file path wasn't set to text field value");

View file

@ -9,6 +9,7 @@
<script> <script>
window.addEventListener("DOMContentLoaded", function() { window.addEventListener("DOMContentLoaded", function() {
window.removeEventListener("DOMContentLoaded", arguments.callee, false);
if (!document.location.hash) { if (!document.location.hash) {
document.location.hash = "#ready"; document.location.hash = "#ready";
} }

View file

@ -43,6 +43,7 @@ function test() {
"browser/components/sessionstore/test/browser/browser_476161_sample.html"; "browser/components/sessionstore/test/browser/browser_476161_sample.html";
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("modify1").value += Math.random(); doc.getElementById("modify1").value += Math.random();
@ -50,6 +51,7 @@ function test() {
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab2.linkedBrowser.contentDocument; let doc = tab2.linkedBrowser.contentDocument;
let changed = doc.getElementById("changed").textContent.trim().split(); let changed = doc.getElementById("changed").textContent.trim().split();

View file

@ -42,6 +42,7 @@ function test() {
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no"); let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) { newWin.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, false);
let newState = { windows: [{ let newState = { windows: [{
tabs: [{ entries: [] }], tabs: [{ entries: [] }],
_closedTabs: [{ _closedTabs: [{

View file

@ -108,8 +108,11 @@ function test() {
// cleanup // cleanup
this.window.close(); this.window.close();
// if we're all done, explicitly finish // if we're all done, explicitly finish
if (++completedTests == numTests) if (++completedTests == numTests) {
this.window.removeEventListener("load", this, false);
this.window.removeEventListener("SSTabRestoring", this, false);
finish(); finish();
}
}, },
handleLoad: function (aEvent) { handleLoad: function (aEvent) {

View file

@ -10,7 +10,7 @@ function test() {
let browser = tab.linkedBrowser; let browser = tab.linkedBrowser;
browser.addEventListener("load", function loadListener(e) { browser.addEventListener("load", function loadListener(e) {
browser.removeEventListener("load", arguments.callee, false); browser.removeEventListener("load", arguments.callee, true);
// Scroll the content document // Scroll the content document
browser.contentWindow.scrollTo(1100, 1200); browser.contentWindow.scrollTo(1100, 1200);
@ -21,7 +21,7 @@ function test() {
let newTab = ss.undoCloseTab(window, 0); let newTab = ss.undoCloseTab(window, 0);
newTab.addEventListener("SSTabRestored", function tabRestored(e) { newTab.addEventListener("SSTabRestored", function tabRestored(e) {
newTab.removeEventListener("SSTabRestored", arguments.callee, false); newTab.removeEventListener("SSTabRestored", arguments.callee, true);
let newBrowser = newTab.linkedBrowser; let newBrowser = newTab.linkedBrowser;

View file

@ -45,12 +45,14 @@ function test() {
"browser/components/sessionstore/test/browser/browser_485482_sample.html"; "browser/components/sessionstore/test/browser/browser_485482_sample.html";
let tab = gBrowser.addTab(testURL); let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
doc.querySelector("input[type=text]").value = uniqueValue; doc.querySelector("input[type=text]").value = uniqueValue;
doc.querySelector("input[type=checkbox]").checked = true; doc.querySelector("input[type=checkbox]").checked = true;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
doc = tab2.linkedBrowser.contentDocument; doc = tab2.linkedBrowser.contentDocument;
is(doc.querySelector("input[type=text]").value, uniqueValue, is(doc.querySelector("input[type=text]").value, uniqueValue,
"generated XPath expression was valid"); "generated XPath expression was valid");

View file

@ -44,6 +44,7 @@ function test() {
let tab = gBrowser.addTab(); let tab = gBrowser.addTab();
tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.addEventListener("load", function(aEvent) {
this.removeEventListener("load", arguments.callee, true);
ss.setTabValue(tab, "bug485563", uniqueValue); ss.setTabValue(tab, "bug485563", uniqueValue);
let tabState = eval("(" + ss.getTabState(tab) + ")"); let tabState = eval("(" + ss.getTabState(tab) + ")");
is(tabState.extData["bug485563"], uniqueValue, is(tabState.extData["bug485563"], uniqueValue,

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