Merge mozilla-central to electrolysis.
Merge mozilla-central to electrolysis.
--- a/.hgignore
+++ b/.hgignore
@@ -1,32 +1,34 @@
# .hgignore - List of filenames hg should ignore
# Filenames that should be ignored wherever they appear
~$
\.pyc$
(^|/)TAGS$
+(^|/)ID$
(^|/)\.DS_Store$
# User files that may appear at the root
^\.mozconfig
^mozconfig
^configure$
^config\.cache$
^config\.log$
-^ID$
# Empty marker file that's generated when we check out NSS
^security/manager/\.nss\.checkout$
# Build directories
^obj
# Build directories for js shell
_DBG\.OBJ/
_OPT\.OBJ/
# SpiderMonkey configury
^js/src/configure$
^js/src/autom4te.cache$
+# SpiderMonkey test result logs
+^js/src/tests/results-.*\.(html|txt)$
# Java HTML5 parser classes
^parser/html/java/(html|java)parser/
--- a/accessible/public/nsIAccessibleRole.idl
+++ b/accessible/public/nsIAccessibleRole.idl
@@ -39,17 +39,17 @@
#include "nsISupports.idl"
/**
* Defines cross platform (Gecko) roles.
*
* @note - When adding a new role, be sure to also add it to nsRoleMap.h for
* each platform.
*/
-[scriptable, uuid(6793ca5c-c7cb-41db-9fb9-c16c0525f962)]
+[scriptable, uuid(f134da65-39a8-4330-843c-5bd42780b34c)]
interface nsIAccessibleRole : nsISupports
{
/**
* Used when accessible hans't strong defined role.
*/
const unsigned long ROLE_NOTHING = 0;
/**
@@ -772,14 +772,19 @@ interface nsIAccessibleRole : nsISupport
/**
* Represents a cell within a grid. It is used for role="gridcell". Unlike
* ROLE_CELL, it allows the calculation of the accessible name from subtree.
* Also, see ROLE_TABLE.
*/
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
* nsRoleMap's are synchronized.
*/
- const unsigned long ROLE_LAST_ENTRY = 122;
+ const unsigned long ROLE_LAST_ENTRY = 123;
};
--- a/accessible/src/atk/nsRoleMap.h
+++ b/accessible/src/atk/nsRoleMap.h
@@ -163,11 +163,12 @@ static const PRUint32 atkRoleMap[] = {
ATK_ROLE_MENU, // nsIAccessibleRole::ROLE_COMBOBOX_LIST 114
ATK_ROLE_MENU_ITEM, // nsIAccessibleRole::ROLE_COMBOBOX_OPTION 115
ATK_ROLE_IMAGE, // nsIAccessibleRole::ROLE_IMAGE_MAP 116
ATK_ROLE_LIST_ITEM, // nsIAccessibleRole::ROLE_OPTION 117
ATK_ROLE_LIST_ITEM, // nsIAccessibleRole::ROLE_RICH_OPTION 118
ATK_ROLE_LIST, // nsIAccessibleRole::ROLE_LISTBOX 119
ATK_ROLE_UNKNOWN, // nsIAccessibleRole::ROLE_FLAT_EQUATION 120
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
};
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -403,36 +403,53 @@ nsAccUtils::GetAncestorWithRole(nsIAcces
}
void
nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
nsIContent *aStartContent,
nsIAccessible **aTreeItemParentResult)
{
*aTreeItemParentResult = nsnull;
+
+ nsCOMPtr<nsIAccessible> parentAccessible;
+ aStartTreeItem->GetParent(getter_AddRefs(parentAccessible));
+ if (!parentAccessible)
+ return;
+
+ PRUint32 startTreeItemRole = nsAccUtils::Role(aStartTreeItem);
+
+ // Calculate tree grid row parent only if the row inside of ARIA treegrid.
+ if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) {
+ PRUint32 role = nsAccUtils::Role(parentAccessible);
+ if (role != nsIAccessibleRole::ROLE_TREE_TABLE)
+ return;
+ }
+
+ // This is a tree or treegrid that uses aria-level to define levels, so find
+ // the first previous sibling accessible where level is defined to be less
+ // than the current level.
nsAutoString levelStr;
- PRInt32 level = 0;
if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) &&
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;
- level = levelStr.ToInteger(&success);
+ PRInt32 level = levelStr.ToInteger(&success);
if (level > 1 && NS_SUCCEEDED(success)) {
nsCOMPtr<nsIAccessible> currentAccessible = aStartTreeItem, prevAccessible;
while (PR_TRUE) {
currentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
currentAccessible.swap(prevAccessible);
nsCOMPtr<nsIAccessNode> accessNode = do_QueryInterface(currentAccessible);
if (!accessNode) {
break; // Reached top of tree, no higher level found
}
PRUint32 role = nsAccUtils::Role(currentAccessible);
- if (role != nsIAccessibleRole::ROLE_OUTLINEITEM)
+ if (role != startTreeItemRole)
continue;
+
nsCOMPtr<nsIDOMNode> treeItemNode;
accessNode->GetDOMNode(getter_AddRefs(treeItemNode));
nsCOMPtr<nsIContent> treeItemContent = do_QueryInterface(treeItemNode);
if (treeItemContent &&
nsAccUtils::HasDefinedARIAToken(treeItemContent,
nsAccessibilityAtoms::aria_level) &&
treeItemContent->GetAttr(kNameSpaceID_None,
nsAccessibilityAtoms::aria_level, levelStr)) {
@@ -440,29 +457,35 @@ nsAccUtils::GetARIATreeItemParent(nsIAcc
NS_ADDREF(*aTreeItemParentResult = currentAccessible);
return;
}
}
}
}
}
- // Possibly a tree 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.
- nsCOMPtr<nsIAccessible> parentAccessible;
- aStartTreeItem->GetParent(getter_AddRefs(parentAccessible));
- if (!parentAccessible)
- return;
+ // In the case of ARIA treegrid, return its parent since ARIA group isn't
+ // used to organize levels in ARIA treegrids.
+
+ if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) {
+ NS_ADDREF(*aTreeItemParentResult = parentAccessible);
+ return; // The container for the tree grid rows
+ }
+
+ // In the case of ARIA tree, a tree can be arranged by using role="group" to
+ // organize levels. In this case the parent of the tree item will be a group
+ // and the previous sibling of that should be the tree item parent. Or, if
+ // the parent is something other than a tree we will return that.
+
PRUint32 role = nsAccUtils::Role(parentAccessible);
if (role != nsIAccessibleRole::ROLE_GROUPING) {
NS_ADDREF(*aTreeItemParentResult = parentAccessible);
return; // The container for the tree items
}
+
nsCOMPtr<nsIAccessible> prevAccessible;
parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible));
if (!prevAccessible)
return;
role = nsAccUtils::Role(prevAccessible);
if (role == nsIAccessibleRole::ROLE_TEXT_LEAF) {
// XXX Sometimes an empty text accessible is in the hierarchy here,
// although the text does not appear to be rendered, GetRenderedText() says that it is
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -543,16 +543,25 @@ nsAccessibilityService::CreateHTMLAccess
}
else if (tag == nsAccessibilityAtoms::optgroup) {
*aAccessible = new nsHTMLSelectOptGroupAccessible(aNode, aWeakShell);
}
else if (tag == nsAccessibilityAtoms::ul || tag == nsAccessibilityAtoms::ol) {
*aAccessible = new nsHTMLListAccessible(aNode, aWeakShell);
}
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);
}
else if (tag == nsAccessibilityAtoms::li && aFrame->GetType() != nsAccessibilityAtoms::blockFrame) {
// Normally this is created by the list item frame which knows about the bullet frame
// However, in this case the list item must have been styled using display: foo
*aAccessible = new nsHTMLLIAccessible(aNode, aWeakShell, EmptyString());
}
else if (tag == nsAccessibilityAtoms::abbr ||
@@ -758,25 +767,26 @@ nsAccessibilityService::CreateHTMLObject
if (domDoc)
return CreateOuterDocAccessible(node, aAccessible);
#ifdef XP_WIN
// 2) for plugins
nsCOMPtr<nsIPluginInstance> pluginInstance ;
aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
if (pluginInstance) {
+ // Note: pluginPort will be null if windowless.
HWND pluginPort = nsnull;
aFrame->GetPluginPort(&pluginPort);
- if (pluginPort) {
- *aAccessible = new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort);
- if (*aAccessible) {
- NS_ADDREF(*aAccessible);
- return NS_OK;
- }
- }
+
+ *aAccessible =
+ new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort);
+ NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY);
+
+ NS_ADDREF(*aAccessible);
+ return NS_OK;
}
#endif
// 3) for images and imagemaps, or anything else with a child frame
// we have the object frame, get the image frame
nsIFrame *frame = aFrame->GetFirstChild(nsnull);
if (frame)
return frame->GetAccessible(aAccessible);
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -284,17 +284,18 @@ static const char kRoleNames[][20] = {
"calendar", //ROLE_CALENDAR
"combobox list", //ROLE_COMBOBOX_LIST
"combobox option", //ROLE_COMBOBOX_OPTION
"image map", //ROLE_IMAGE_MAP
"listbox option", //ROLE_OPTION
"listbox rich option", //ROLE_RICH_OPTION
"listbox", //ROLE_LISTBOX
"flat equation", //ROLE_FLAT_EQUATION
- "gridcell" //ROLE_GRID_CELL
+ "gridcell", //ROLE_GRID_CELL
+ "embedded object" //ROLE_EMBEDDED_OBJECT
};
/**
* Map nsIAccessibleEvents constants to strings. Used by
* nsIAccessibleRetrieval::getStringEventType() method.
*/
static const char kEventTypeNames[][40] = {
"unknown", //
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2487,23 +2487,26 @@ nsAccessible::GetRelationByType(PRUint32
rv = nsRelUtils::
AddTargetFromNeighbour(aRelationType, aRelation, content,
nsAccessibilityAtoms::aria_owns);
NS_ENSURE_SUCCESS(rv, rv);
if (rv != NS_OK_NO_RELATION_TARGET)
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 &&
- mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
- // This is an ARIA tree that doesn't use owns, so we need to get
- // the parent the hard way.
+ (mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
+ mRoleMapEntry->role == nsIAccessibleRole::ROLE_ROW)) {
+
nsCOMPtr<nsIAccessible> accTarget;
nsAccUtils::GetARIATreeItemParent(this, content,
getter_AddRefs(accTarget));
+
return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget);
}
// If accessible is in its own Window, or is the root of a document,
// then we should provide NODE_CHILD_OF relation so that MSAA clients
// can easily get to true parent instead of getting to oleacc's
// ROLE_WINDOW accessible which will prevent us from going up further
// (because it is system generated and has no idea about the hierarchy
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -919,40 +919,30 @@ nsHTMLTableAccessible::GetSelectedRowInd
*aRows = outArray;
return rv;
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
nsIAccessible **aTableCellAccessible)
{
- NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
-
- nsresult rv = NS_OK;
-
nsCOMPtr<nsIDOMElement> cellElement;
- rv = GetCellAt(aRow, aColumn, *getter_AddRefs(cellElement));
+ nsresult rv = GetCellAt(aRow, aColumn, *getter_AddRefs(cellElement));
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIAccessibilityService>
- accService(do_GetService("@mozilla.org/accessibilityService;1"));
- NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
-
- return accService->GetAccessibleInWeakShell(cellElement, mWeakShell,
- aTableCellAccessible);
+ return GetAccService()->GetAccessibleInWeakShell(cellElement, mWeakShell,
+ aTableCellAccessible);
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
{
NS_ENSURE_ARG_POINTER(aIndex);
- NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
-
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
nsresult rv = tableLayout->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
return NS_ERROR_INVALID_ARG;
return NS_OK;
@@ -965,145 +955,158 @@ nsHTMLTableAccessible::GetColumnIndexAt(
if (IsDefunct())
return NS_ERROR_FAILURE;
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
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
nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
{
NS_ENSURE_ARG_POINTER(aRow);
if (IsDefunct())
return NS_ERROR_FAILURE;
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
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
nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
PRInt32 aColumnIndex,
PRInt32 *aExtentCount)
{
- NS_ENSURE_TRUE(IsValidRow(aRowIndex) && IsValidColumn(aColumnIndex),
- NS_ERROR_INVALID_ARG);
-
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
nsCOMPtr<nsIDOMElement> domElement;
PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan;
PRBool isSelected;
- return tableLayout->
+ nsresult rv = tableLayout->
GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, *aExtentCount, isSelected);
+
+ return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32 *aExtentCount)
{
- NS_ENSURE_TRUE(IsValidRow(aRowIndex) && IsValidColumn(aColumnIndex),
- NS_ERROR_INVALID_ARG);
-
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
nsCOMPtr<nsIDOMElement> domElement;
PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualColSpan;
PRBool isSelected;
- return tableLayout->
+ nsresult rv = tableLayout->
GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan,
*aExtentCount, actualColSpan, isSelected);
+
+ return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetColumnDescription(PRInt32 aColumn, nsAString &_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString &_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
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);
-
- nsresult rv = NS_OK;
-
- PRInt32 rows;
- rv = GetRowCount(&rows);
+ PRInt32 colCount = 0;
+ nsresult rv = GetColumnCount(&colCount);
NS_ENSURE_SUCCESS(rv, rv);
- for (PRInt32 index = 0; index < rows; index++) {
- rv = IsCellSelected(index, aColumn, _retval);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!*_retval) {
- break;
+ if (aColumn < 0 || aColumn >= colCount)
+ return NS_ERROR_INVALID_ARG;
+
+ PRInt32 rowCount = 0;
+ 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
-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);
-
- nsresult rv = NS_OK;
-
- PRInt32 columns;
- rv = GetColumnCount(&columns);
+ PRInt32 rowCount = 0;
+ nsresult rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
- for (PRInt32 index = 0; index < columns; index++) {
- rv = IsCellSelected(aRow, index, _retval);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!*_retval) {
- break;
+ if (aRow < 0 || aRow >= rowCount)
+ return NS_ERROR_INVALID_ARG;
+
+ PRInt32 colCount = 0;
+ 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
nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
PRBool *aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = PR_FALSE;
- NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn),
- NS_ERROR_INVALID_ARG);
-
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
nsCOMPtr<nsIDOMElement> domElement;
PRInt32 startRowIndex = 0, startColIndex = 0,
rowSpan, colSpan, actualRowSpan, actualColSpan;
nsresult rv = tableLayout->
@@ -1111,32 +1114,16 @@ nsHTMLTableAccessible::IsCellSelected(PR
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, *aIsSelected);
if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
return NS_ERROR_INVALID_ARG;
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
nsHTMLTableAccessible::SelectRow(PRInt32 aRow)
{
if (IsDefunct())
return NS_ERROR_FAILURE;
nsresult rv =
RemoveRowsOrColumnsFromSelection(aRow,
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -139,30 +139,16 @@ public:
virtual nsresult GetNameInternal(nsAString& aName);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
// 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.
*/
nsresult GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex,
nsIDOMElement* &aCell);
/**
* Return nsITableLayout for the frame of the accessible table.
*/
--- a/accessible/src/mac/nsRoleMap.h
+++ b/accessible/src/mac/nsRoleMap.h
@@ -159,10 +159,11 @@ static const NSString* AXRoles [] = {
NSAccessibilityMenuRole, // ROLE_COMBOBOX_LIST
NSAccessibilityMenuItemRole, // ROLE_COMBOBOX_OPTION
NSAccessibilityImageRole, // ROLE_IMAGE_MAP
NSAccessibilityRowRole, // ROLE_OPTION
NSAccessibilityRowRole, // ROLE_RICH_OPTION
NSAccessibilityListRole, // ROLE_LISTBOX
NSAccessibilityUnknownRole, // ROLE_FLAT_EQUATION
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)!
};
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.cpp
@@ -34,62 +34,116 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLWin32ObjectAccessible.h"
#include "nsAccessibleWrap.h"
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLWin32ObjectOwnerAccessible
+////////////////////////////////////////////////////////////////////////////////
-nsHTMLWin32ObjectOwnerAccessible::nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell, void* aHwnd):
-nsAccessibleWrap(aNode, aShell)
+nsHTMLWin32ObjectOwnerAccessible::
+ nsHTMLWin32ObjectOwnerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell,
+ void* aHwnd) :
+ nsAccessibleWrap(aNode, aShell)
{
mHwnd = aHwnd;
}
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLWin32ObjectOwnerAccessible: nsAccessNode implementation
+
nsresult
nsHTMLWin32ObjectOwnerAccessible::Shutdown()
{
nsAccessibleWrap::Shutdown();
mNativeAccessible = nsnull;
return NS_OK;
}
-/**
- * Our only child is a nsHTMLWin32ObjectAccessible
- */
-NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetFirstChild(nsIAccessible **aFirstChild)
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLWin32ObjectOwnerAccessible: nsIAccessible implementation
+
+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 (!mHwnd) {
+ if (!mHwnd)
return NS_OK;
- }
- mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd) ;
+
+ mNativeAccessible = new nsHTMLWin32ObjectAccessible(mHwnd);
+ NS_ENSURE_TRUE(mNativeAccessible, NS_ERROR_OUT_OF_MEMORY);
+
SetFirstChild(mNativeAccessible);
- *aFirstChild = mNativeAccessible;
}
+
+ *aFirstChild = mNativeAccessible;
NS_IF_ADDREF(*aFirstChild);
+
return NS_OK;
}
-NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetLastChild(nsIAccessible **aLastChild)
+NS_IMETHODIMP
+nsHTMLWin32ObjectOwnerAccessible::GetLastChild(nsIAccessible **aLastChild)
{
return GetFirstChild(aLastChild);
}
-NS_IMETHODIMP nsHTMLWin32ObjectOwnerAccessible::GetChildCount(PRInt32 *aChildCount)
+NS_IMETHODIMP
+nsHTMLWin32ObjectOwnerAccessible::GetChildCount(PRInt32 *aChildCount)
{
+ NS_ENSURE_ARG_POINTER(aChildCount);
+
nsCOMPtr<nsIAccessible> onlyChild;
GetFirstChild(getter_AddRefs(onlyChild));
*aChildCount = onlyChild ? 1 : 0;
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):
nsLeafAccessible(nsnull, nsnull)
{
mHwnd = aHwnd;
if (mHwnd) {
// The plugin is not windowless. In this situation we use
// use its inner child owned by the plugin so that we don't get
// in an infinite loop, where the WM_GETOBJECT's get forwarded
--- a/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
+++ b/accessible/src/msaa/nsHTMLWin32ObjectAccessible.h
@@ -59,16 +59,20 @@ public:
// nsIAccessible
NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
NS_IMETHOD GetChildCount(PRInt32 *aChildCount); // Zero or one child
// nsAccessNode
virtual nsresult Shutdown();
+ // nsAccessible
+ virtual nsresult GetRoleInternal(PRUint32 *aRole);
+ virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+
protected:
void* mHwnd;
nsCOMPtr<nsIAccessible> mNativeAccessible;
};
/**
* This class is used only internally, we never! send out an IAccessible linked
* back to this object. This class is used to represent a plugin object when
--- a/accessible/src/msaa/nsRoleMap.h
+++ b/accessible/src/msaa/nsRoleMap.h
@@ -435,12 +435,15 @@ static const WindowsRoleMapItem gWindows
{ ROLE_SYSTEM_LIST, ROLE_SYSTEM_LIST },
// nsIAccessibleRole::ROLE_FLAT_EQUATION
{ ROLE_SYSTEM_EQUATION, ROLE_SYSTEM_EQUATION },
// nsIAccessibleRole::ROLE_GRID_CELL
{ ROLE_SYSTEM_CELL, ROLE_SYSTEM_CELL },
+ // nsIAccessibleRole::ROLE_EMBEDDED_OBJECT
+ { USE_ROLE_STRING, IA2_ROLE_EMBEDDED_OBJECT },
+
// nsIAccessibleRole::ROLE_LAST_ENTRY
{ ROLE_WINDOWS_LAST_ENTRY, ROLE_WINDOWS_LAST_ENTRY }
};
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -84,16 +84,17 @@ include $(topsrcdir)/config/rules.mk
test_bug420863.html \
$(warning test_childAtPoint.html temporarily disabled) \
$(warning test_childAtPoint.xul temporarily disabled) \
test_cssattrs.html \
test_descr.html \
test_elm_filectrl.html \
test_elm_listbox.xul \
$(warning test_elm_media.html temporarily disabled) \
+ test_elm_plugin.html \
test_elm_tree.xul \
test_elm_txtcntnr.html \
test_events_caretmove.html \
test_events_coalescence.html \
test_events_doc.html \
test_events_draganddrop.html \
test_events_flush.html \
test_events_focus.html \
@@ -154,16 +155,17 @@ include $(topsrcdir)/config/rules.mk
test_table_struct.html \
test_table_struct_ariagrid.html \
test_table_struct_ariatreegrid.html \
test_table_struct_listbox.xul \
test_table_struct_tree.xul \
test_textattrs.html \
test_textboxes.html \
test_textboxes.xul \
+ test_value.html \
test_value.xul \
testTextboxes.js \
treeview.css \
treeview.js \
z_states_frame.html \
z_states_framearticle.html \
z_states_framecheckbox.html \
z_states_frametextbox.html \
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -7,16 +7,17 @@ const ROLE_APP_ROOT = nsIAccessibleRole.
const ROLE_CAPTION = nsIAccessibleRole.ROLE_CAPTION;
const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
+const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC;
const ROLE_GRID_CELL = nsIAccessibleRole.ROLE_GRID_CELL;
const ROLE_GROUPING = nsIAccessibleRole.ROLE_GROUPING;
const ROLE_HEADING = nsIAccessibleRole.ROLE_HEADING;
const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP;
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -89,20 +89,22 @@ function testStates(aAccOrElmOrID, aStat
// selected/selectable
if (state & STATE_SELECTED) {
isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false,
"Selected element should be selectable!");
}
// unavailable
- if ((state & STATE_UNAVAILABLE)
- && (getRole(aAccOrElmOrID) != ROLE_GROUPING))
- isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
- "Disabled " + id + " must be focusable!");
+ if (state & STATE_UNAVAILABLE) {
+ var role = getRole(aAccOrElmOrID);
+ if (role != ROLE_GROUPING && role != ROLE_EMBEDDED_OBJECT)
+ isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
+ "Disabled " + id + " must be focusable!");
+ }
}
/**
* Tests an acessible and its sub tree for the passed in state bits.
* Used to make sure that states are propagated to descendants, for example the
* STATE_UNAVAILABLE from a container to its children.
*
* @param aAccOrElmOrID The accessible, DOM element or ID to be tested.
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_elm_plugin.html
@@ -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>
--- a/accessible/tests/mochitest/test_relations.html
+++ b/accessible/tests/mochitest/test_relations.html
@@ -44,16 +44,22 @@
// aria_owns, multiple relations
testRelation("treeitem1", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
// 'node child of' relation for outlineitem role
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
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
// direct accessible parent (fixed in bug 419770).
var iframeElmObj = {};
var iframeAcc = getAccessible("iframe", null, iframeElmObj);
var iframeDoc = iframeElmObj.value.contentDocument;
var iframeDocAcc = getAccessible(iframeDoc);
testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc);
@@ -142,16 +148,31 @@
<span role="checkbox" id="checkbox5" aria-describedby="descr2 descr3"></span>
<div role="treeitem" id="treeitem1">Yellow</div>
<div role="treeitem" id="treeitem2">Orange</div>
<div id="tree" role="tree" aria-owns="treeitem1 treeitem2">
<div role="treeitem" id="treeitem3">Blue</div>
<div role="treeitem" id="treeitem4" aria-level="1">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>
<iframe id="iframe"></iframe>
<div id="tablist" role="tablist">
<div id="tab" role="tab" aria-controls="tabpanel">tab</div>
</div>
<div id="tabpanel" role="tabpanel">tabpanel</div>
--- a/accessible/tests/mochitest/test_states.html
+++ b/accessible/tests/mochitest/test_states.html
@@ -64,16 +64,40 @@
// test disabled group and all its descendants to see if they are
// disabled, too. See bug 429285.
testStatesInSubtree("group", STATE_UNAVAILABLE);
// offscreen test
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.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
@@ -135,10 +159,29 @@
<div role="option" id="item4">Item 4</div>
</div>
<div role="slider" tabindex="0">A slider</div>
</div>
<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>
+
+ <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>
</html>
--- a/accessible/tests/mochitest/test_table_sels.html
+++ b/accessible/tests/mochitest/test_table_sels.html
@@ -17,16 +17,19 @@
src="chrome://mochikit/content/a11y/accessible/states.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/table.js"></script>
<script type="text/javascript">
function doTest()
{
+ //////////////////////////////////////////////////////////////////////////
+ // table
+
var cellsArray =
[
[false, false, false, kColSpanned, false, false, false, false],
[false, false, false, false, false, false, false, kRowSpanned],
[false, false, kColSpanned, false, false, false, false, kRowSpanned],
[false, kRowSpanned, kSpanned, false, false, kRowSpanned, false, kRowSpanned]
];
@@ -48,16 +51,30 @@
for (var colIdx = 0; colIdx < columsCount; colIdx++) {
testSelectTableColumn("table", colIdx, cellsArray);
testUnselectTableColumn("table", colIdx, cellsArray);
}
var accTable = getAccessible("table", [nsIAccessibleTable]);
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.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
@@ -72,16 +89,21 @@
title="nsHTMLTableAccessible::GetSelectedCells contains index duplicates for spanned rows or columns">
Mozilla Bug 501635
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=417929"
title="nsIAccessiblTable selectRows does not unselect previously selected rows">
Mozilla Bug 417929
</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>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<!-- Test Table -->
<br><br><b> Testing Table:</b><br><br>
@@ -117,11 +139,42 @@
<tr>
<td><br></td>
<td><br></td>
<td><br></td>
<td><br></td>
</tr>
</tbody>
</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>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_value.html
@@ -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>
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -293,19 +293,16 @@ endif
ifdef WINCE
ifdef MOZ_FASTSTART
libs::
cp -f $(DIST)/bin/faststartstub.exe $(DIST)/bin/$(MOZ_APP_NAME)faststart.exe
endif
endif
-libs::
- touch $(DIST)/bin/.autoreg
-
libs:: $(srcdir)/profile/prefs.js
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile
libs:: $(srcdir)/blocklist.xml
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -333,17 +333,16 @@ pref("browser.tabs.autoHide", false);
pref("browser.tabs.autoHide", true);
#endif
pref("browser.tabs.closeWindowWithLastTab", true);
pref("browser.tabs.insertRelatedAfterCurrent", true);
pref("browser.tabs.warnOnClose", true);
pref("browser.tabs.warnOnOpen", true);
pref("browser.tabs.maxOpenBeforeWarn", 15);
pref("browser.tabs.loadInBackground", true);
-pref("browser.tabs.loadFolderAndReplace", true);
pref("browser.tabs.opentabfor.middleclick", true);
pref("browser.tabs.loadDivertedInBackground", false);
pref("browser.tabs.loadBookmarksInBackground", false);
pref("browser.tabs.tabMinWidth", 100);
pref("browser.tabs.tabMaxWidth", 250);
pref("browser.tabs.tabClipWidth", 140);
// Where to show tab close buttons:
--- a/browser/base/content/aboutSupport.xhtml
+++ b/browser/base/content/aboutSupport.xhtml
@@ -129,36 +129,66 @@ td {
]]></style>
<script type="application/javascript;version=1.7"><![CDATA[
const Cc = Components.classes;
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 () {
// Get the FUEL Application object.
let Application = Cc["@mozilla.org/fuel/application;1"]
.getService(Ci.fuelIApplication);
// Get the support URL.
let urlFormatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Ci.nsIURLFormatter);
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.
document.getElementById("application-box").textContent = Application.name;
document.getElementById("version-box").textContent = Application.version;
- document.getElementById("profile-box").textContent = profileDir;
document.getElementById("supportLink").href = supportUrl;
// Update the other sections.
populateExtensionsSection();
populatePreferencesSection();
}
function populateExtensionsSection() {
@@ -188,39 +218,65 @@ function populatePreferencesSection() {
return 0;
}
let sortedPrefs = modifiedPrefs.sort(comparePrefs);
let trPrefs = [];
for each (let pref in sortedPrefs) {
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]);
trPrefs.push(tr);
}
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() {
// We use the low-level prefs API to identify prefs that have been
// modified, rather that Application.prefs.all since the latter is
// much, much slower. Application.prefs.all also gets slower each
// time it's called. See bug 517312.
let prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
let prefRootBranch = prefService.getBranch("");
- let prefNames = prefRootBranch.getChildList("", { value: 0 });
+ let prefNames = getWhitelistedPrefNames(prefRootBranch);
let prefs = [Application.prefs.get(prefName)
for each (prefName in prefNames)
- if (prefRootBranch.prefHasUserValue(prefName))];
+ if (prefRootBranch.prefHasUserValue(prefName)
+ && !isBlacklisted(prefName))];
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) {
let elem = document.createElement(tagName);
appendChildren(elem, childElems);
return elem;
}
function createElement(tagName, textContent, opt_class) {
let elem = document.createElement(tagName);
@@ -270,17 +326,20 @@ function createTextForElement(elem) {
// Generate the initial text.
let textFragmentAccumulator = [];
generateTextForElement(elem, "", textFragmentAccumulator);
let text = textFragmentAccumulator.join("");
// Trim extraneous whitespace before newlines, then squash extraneous
// blank lines.
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;
}
function generateTextForElement(elem, indent, textFragmentAccumulator) {
// Add a little extra spacing around most elements.
if (elem.tagName != "td")
textFragmentAccumulator.push("\n");
@@ -311,16 +370,29 @@ function generateTextForTextNode(node, i
textFragmentAccumulator.push("\n" + indent);
// Trim the text node's text content and add proper indentation after
// any internal line breaks.
let text = node.textContent.trim().replace("\n[ \t]*", "\n" + indent);
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>
</head>
<body dir="&locale.dir;">
<h1>
&aboutSupport.pageTitle;
@@ -364,20 +436,27 @@ function generateTextForTextNode(node, i
</td>
</tr>
<tr>
<th class="column">
&aboutSupport.appBasicsProfileDir;
</th>
- <td id="profile-box">
+ <td>
+ <button onclick="openProfileDirectory()">
+#ifdef XP_MACOSX
+ &aboutSupport.showMac.label;
+#else
+ &aboutSupport.show.label;
+#endif
+ </button>
</td>
</tr>
-
+
<tr>
<th class="column">
&aboutSupport.appBasicsPlugins;
</th>
<td>
<a href="about:plugins">about:plugins</a>
</td>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -215,18 +215,23 @@ function SetClickAndHoldHandlers() {
timer = setTimeout(timerCallback, 500, aEvent.currentTarget);
}
function clickHandler(aEvent) {
if (aEvent.button == 0 &&
aEvent.target == aEvent.currentTarget &&
!aEvent.currentTarget.open &&
- !aEvent.currentTarget.disabled)
- aEvent.currentTarget.doCommand();
+ !aEvent.currentTarget.disabled) {
+ 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) {
if (timer) {
clearTimeout(timer);
timer = null;
}
}
@@ -781,78 +786,76 @@ let gGestureSupport = {
*
* @param aArray
* Source array containing any number of elements
* @yield Array that is a subset of the input array from full set to empty
*/
_power: function GS__power(aArray) {
// Create a bitmask based on the length of the array
let num = 1 << aArray.length;
- while (--num >= 0)
+ while (--num >= 0) {
// 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)
aPrev.push(aCurr);
return aPrev;
}, []);
+ }
},
/**
* Determine what action to do for the gesture based on which keys are
* pressed and which commands are set
*
* @param aEvent
* The original gesture event to convert into a fake click event
* @param aGesture
* Array of gesture name parts (to be joined by periods)
* @return Name of the command found for the event's keys and gesture. If no
* command is found, no value is returned (undefined).
*/
_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
// "meta" is preferred over "ctrl" when both buttons are pressed (and a
// command for both don't exist)
let keyCombos = [];
- const keys = ["shift", "alt", "ctrl", "meta"];
- for each (let key in keys)
+ ["shift", "alt", "ctrl", "meta"].forEach(function (key) {
if (aEvent[key + "Key"])
keyCombos.push(key);
-
- try {
- // Try each combination of key presses in decreasing order for commands
- for (let subCombo in this._power(keyCombos)) {
- // Convert a gesture and pressed keys into the corresponding command
- // action where the preference has the gesture before "shift" before
- // "alt" before "ctrl" before "meta" all separated by periods
- let command = this._getPref(aGesture.concat(subCombo).join("."));
-
- // Do the command if we found one to do
- if (command) {
- 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;
+ });
+
+ // Try each combination of key presses in decreasing order for commands
+ for each (let subCombo in this._power(keyCombos)) {
+ // Convert a gesture and pressed keys into the corresponding command
+ // action where the preference has the gesture before "shift" before
+ // "alt" before "ctrl" before "meta" all separated by periods
+ let command;
+ try {
+ command = this._getPref(aGesture.concat(subCombo).join("."));
+ } catch (e) {}
+
+ if (!command)
+ continue;
+
+ 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);
}
- }
- // The generator ran out of key combinations, so just do nothing
- catch (e) {}
+
+ return command;
+ }
+ return null;
},
/**
* Convert continual motion events into an action if it exceeds a threshold
* in a given direction. This function will be set by _setupGesture to
* capture state that needs to be shared across multiple gesture updates.
*
* @param aEvent
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -284,17 +284,17 @@
icon="save" id="imagesaveasbutton"
oncommand="saveMedia();"/>
</hbox>
<vbox class="inset iframe" flex="1" pack="center">
<hbox id="theimagecontainer" pack="center">
<image id="thepreviewimage"/>
</hbox>
<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>
</vbox>
</vbox>
<hbox id="mediaSaveBox" collapsed="true">
<spacer flex="1"/>
<button label="&mediaSaveAs;" accesskey="&mediaSaveAs2.accesskey;"
icon="save" oncommand="saveMedia();"/>
</hbox>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -520,17 +520,17 @@
onLocationChange : function(aWebProgress, aRequest, aLocation)
{
// The document loaded correctly, clear the value if we should
if (this.mBrowser.userTypedClear > 0)
this.mBrowser.userTypedValue = null;
if (aWebProgress.DOMWindow == this.mBrowser.contentWindow &&
aWebProgress.isLoadingDocument)
- this.mTabBrowser.setIcon(this.mTab, null);
+ this.mTabBrowser.getBrowserForTab(this.mTab).mIconURL = null;
// changing location, clear out the missing plugins list
this.mBrowser.missingPlugins = null;
if (this.mBlank)
return;
if (this.mTabBrowser.mCurrentTab == this.mTab) {
@@ -1261,17 +1261,17 @@
// if we're adding tabs, we're past interrupt mode, ditch the owner
if (this.mCurrentTab.owner)
this.mCurrentTab.owner = null;
var t = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"tab");
- var blank = (aURI == "about:blank");
+ var blank = !aURI || (aURI == "about:blank");
if (blank)
t.setAttribute("label", this.mStringBundle.getString("tabs.untitled"));
else
t.setAttribute("label", aURI);
t.setAttribute("crop", "end");
t.maxWidth = this.mTabContainer.mTabMaxWidth;
@@ -2860,97 +2860,35 @@
<implementation>
<!-- Override scrollbox.xml method, since our scrollbox's children are
inherited from the binding parent -->
<method name="_getScrollableElements">
<body><![CDATA[
return document.getBindingParent(this).childNodes;
]]></body>
</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>
<handlers>
<handler event="underflow"><![CDATA[
if (event.detail == 0)
return; // Ignore vertical events
var tabs = document.getBindingParent(this);
tabs.removeAttribute("overflow");
-#ifdef XP_MACOSX
- this._scrollButtonDownBox.collapsed = true;
- this._scrollButtonDownBoxAnimate.collapsed = true;
-#endif
]]></handler>
<handler event="overflow"><![CDATA[
if (event.detail == 0)
return; // Ignore vertical events
var tabs = document.getBindingParent(this);
tabs.setAttribute("overflow", "true");
-#ifdef XP_MACOSX
- this._scrollButtonDownBox.collapsed = false;
- this._scrollButtonDownBoxAnimate.collapsed = false;
-#endif
this.ensureElementIsVisible(tabs.selectedItem, false);
]]></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>
-
-#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 id="tabbrowser-tabs"
extends="chrome://global/content/bindings/tabbox.xml#tabs">
<content>
<xul:stack flex="1" class="tabs-stack">
<xul:vbox>
<xul:spacer flex="1"/>
@@ -2976,25 +2914,22 @@
<children/>
<xul:toolbarbutton class="tabs-newtab-button"
command="cmd_newNavigatorTab"
tooltiptext="&newTabButton.tooltip;"/>
</xul:arrowscrollbox>
<xul:toolbarbutton class="tabs-newtab-button" anonid="newtab-button"
command="cmd_newNavigatorTab"
tooltiptext="&newTabButton.tooltip;"/>
- <xul:stack align="center" pack="end">
- <xul:hbox flex="1" class="tabs-alltabs-box-animate" anonid="alltabs-box-animate"/>
- <xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button"
- type="menu"
- tooltiptext="&listAllTabs.label;">
- <xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup"
- position="after_end"/>
- </xul:toolbarbutton>
- </xul:stack>
+ <xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button"
+ type="menu"
+ tooltiptext="&listAllTabs.label;">
+ <xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup"
+ position="after_end"/>
+ </xul:toolbarbutton>
<xul:toolbarbutton anonid="tabs-closebutton"
class="close-button tabs-closebutton"/>
</xul:hbox>
</xul:stack>
</content>
<implementation implements="nsITimerCallback, nsIDOMEventListener">
<constructor>
<![CDATA[
@@ -3163,29 +3098,23 @@
]]></body>
</method>
<field name="mAllTabsPopup">
document.getAnonymousElementByAttribute(this,
"anonid", "alltabs-popup");
</field>
- <field name="mAllTabsBoxAnimate">
- document.getAnonymousElementByAttribute(this,
- "anonid",
- "alltabs-box-animate");
+ <field name="_animateElement">
+ this.mTabstrip._scrollButtonDown;
</field>
-#ifdef XP_MACOSX
- <field name="mDownBoxAnimate">
- this.mTabstrip._scrollButtonDownBoxAnimate;
- </field>
-#endif
-
<field name="_animateTimer">null</field>
+ <field name="_animateBaseOpacity">null</field>
+ <field name="_animateBaseColor">null</field>
<field name="_animateStep">-1</field>
<field name="_animateDelay">25</field>
<field name="_animatePercents">
[1.00, 0.85, 0.80, 0.75, 0.71, 0.68, 0.65, 0.62, 0.59, 0.57,
0.54, 0.52, 0.50, 0.47, 0.45, 0.44, 0.42, 0.40, 0.38, 0.37,
0.35, 0.34, 0.32, 0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25,
0.24, 0.23, 0.23, 0.22, 0.22, 0.21, 0.21, 0.21, 0.20, 0.20,
0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.19, 0.19, 0.19, 0.18,
@@ -3194,20 +3123,18 @@
<method name="_stopAnimation">
<body><![CDATA[
if (this._animateStep != -1) {
if (this._animateTimer)
this._animateTimer.cancel();
this._animateStep = -1;
- this.mAllTabsBoxAnimate.style.opacity = 0.0;
-#ifdef XP_MACOSX
- this.mDownBoxAnimate.style.opacity = 0.0;
-#endif
+ this._animateElement.style.outlineColor = "";
+ this._animateElement.style.outlineStyle = "";
}
]]></body>
</method>
<method name="_notifyBackgroundTab">
<parameter name="aTab"/>
<body><![CDATA[
var scrollRect = this.mTabstrip.scrollClientRect;
@@ -3227,42 +3154,59 @@
return;
}
this.mTabstrip._smoothScrollByPixels(this.mTabstrip._isRTLScrollbox ?
selected.right - scrollRect.right :
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
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)
this._animateTimer =
Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
- else
- this._animateTimer.cancel();
this._animateTimer.initWithCallback(this, this._animateDelay,
this._animateTimer.TYPE_REPEATING_SLACK);
]]></body>
</method>
-
+
<method name="notify">
<parameter name="aTimer"/>
<body><![CDATA[
if (!document)
aTimer.cancel();
- var percent = this._animatePercents[this._animateStep];
- this.mAllTabsBoxAnimate.style.opacity = percent;
-#ifdef XP_MACOSX
- this.mDownBoxAnimate.style.opacity = percent;
-#endif
+ var opacity = this._animateBaseOpacity * this._animatePercents[this._animateStep];
+ this._animateElement.style.outlineColor =
+ this._animateBaseColor.replace("$opacity", opacity);
if (this._animateStep < (this._animatePercents.length - 1))
this._animateStep++;
else
this._stopAnimation();
]]></body>
</method>
</implementation>
@@ -3522,24 +3466,19 @@
<handler event="popupshowing">
<![CDATA[
// set up the menu popup
var tabcontainer = document.getBindingParent(this);
var tabs = tabcontainer.childNodes;
// Listen for changes in the tab bar.
- var tabbrowser = document.getBindingParent(tabcontainer);
- tabbrowser.addEventListener("TabOpen", this, false);
+ tabcontainer.addEventListener("TabOpen", 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++) {
this._createTabMenuItem(tabs[i]);
}
this._updateTabsVisibilityStatus();
]]></handler>
<handler event="popuphiding">
<![CDATA[
@@ -3549,17 +3488,17 @@
menuItem.removeEventListener("command", this, false);
menuItem.tab.removeEventListener("DOMAttrModified", this, false);
menuItem.tab.removeEventListener("TabClose", this, false);
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
var tabcontainer = document.getBindingParent(this);
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
- document.getBindingParent(tabcontainer).removeEventListener("TabOpen", this, false);
+ tabcontainer.removeEventListener("TabOpen", this, false);
]]></handler>
<handler event="DOMMenuItemActive">
<![CDATA[
var tab = event.target.tab;
if (tab) {
var statusText = tab.linkedBrowser.currentURI.spec;
if (statusText == "about:blank") {
--- a/browser/base/content/test/browser_bug386835.js
+++ b/browser/base/content/test/browser_bug386835.js
@@ -1,14 +1,14 @@
var gTestPage = "http://example.org/browser/browser/base/content/test/dummy_page.html";
var gTestImage = "http://example.org/browser/browser/base/content/test/moz.png";
var gTab1, gTab2, gTab3;
var gLevel;
-const kBack = 0;
-const kForward = 1;
+const BACK = 0;
+const FORWARD = 1;
function test() {
waitForExplicitFinish();
gTab1 = gBrowser.addTab(gTestPage);
gTab2 = gBrowser.addTab();
gTab3 = gBrowser.addTab();
gBrowser.selectedTab = gTab1;
@@ -54,18 +54,18 @@ function imageLoaded() {
zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background");
gBrowser.selectedTab = gTab1;
zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
executeSoon(imageZoomSwitch);
}
function imageZoomSwitch() {
- navigate(kBack, function() {
- navigate(kForward, function() {
+ navigate(BACK, function () {
+ navigate(FORWARD, function () {
zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
gBrowser.selectedTab = gTab2;
zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
// Mac OS X does not support print preview, so skip those tests
let isOSX = ("nsILocalFileMac" in Components.interfaces);
if (isOSX)
finishTest();
@@ -111,19 +111,19 @@ function testPrintPreview(aTab, aCallbac
PrintPreviewListener.onExit.apply(PrintPreviewListener, arguments);
zoomTest(aTab, level, "Toggling print preview mode should not affect zoom level");
FullZoom.reset();
aCallback();
};
- let printPreview = new Function(document.getElementById("cmd_printPreview")
- .getAttribute("oncommand"));
- executeSoon(printPreview);
+ executeSoon(function () {
+ document.getElementById("cmd_printPreview").doCommand();
+ });
}
function finishTest() {
gBrowser.selectedTab = gTab1;
FullZoom.reset();
gBrowser.removeTab(gTab1);
FullZoom.reset();
gBrowser.removeTab(gTab2);
@@ -140,17 +140,17 @@ function load(tab, url, cb) {
tab.linkedBrowser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
cb();
}, true);
tab.linkedBrowser.loadURI(url);
}
function navigate(direction, cb) {
- gBrowser.addEventListener("pageshow", function(event) {
+ gBrowser.addEventListener("pageshow", function (event) {
gBrowser.removeEventListener("pageshow", arguments.callee, true);
- setTimeout(cb, 0);
+ executeSoon(cb);
}, true);
- if (direction == kBack)
+ if (direction == BACK)
gBrowser.goBack();
- else if (direction == kForward)
+ else if (direction == FORWARD)
gBrowser.goForward();
}
--- a/browser/base/content/test/browser_bug416661.js
+++ b/browser/base/content/test/browser_bug416661.js
@@ -21,16 +21,17 @@ function continue_test_prefNotSet () {
is(ZoomManager.zoom, 1, "zoom level pref should not apply to an image");
FullZoom.reset();
content.location =
"http://localhost:8888/browser/browser/base/content/test/zoom_test.html";
}
function end_test_prefNotSet() {
+ tabElm.linkedBrowser.removeEventListener("load", end_test_prefNotSet, true);
is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted");
// Reset the zoom so that other tests have a fresh zoom level
FullZoom.reset();
gBrowser.removeCurrentTab();
finish();
}
--- a/browser/base/content/test/browser_bug427559.js
+++ b/browser/base/content/test/browser_bug427559.js
@@ -44,16 +44,17 @@
let testPage = 'data:text/html,<body><button onblur="this.parentNode.removeChild(this);"><script>document.body.firstChild.focus();</script></body>';
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
+ gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
setTimeout(function () {
var testPageWin = content;
// The test page loaded, so open an empty tab, select it, then restore
// the test tab. This causes the test page's focused element to be removed
// from its document.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.removeCurrentTab();
--- a/browser/base/content/test/browser_bug432599.js
+++ b/browser/base/content/test/browser_bug432599.js
@@ -41,16 +41,17 @@ function test() {
content.location = testURL;
}
let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
let currentInvoker = 0;
function initTest() {
+ gBrowser.selectedBrowser.removeEventListener("load", initTest, true);
// first, bookmark the page
Application.bookmarks.toolbar.addBookmark("Bug 432599 Test", makeURI(testURL));
checkBookmarksPanel(invokers[currentInvoker], 1);
}
let initialValue;
let initialRemoveHidden;
--- a/browser/base/content/test/browser_bug435035.js
+++ b/browser/base/content/test/browser_bug435035.js
@@ -1,13 +1,14 @@
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function () {
+ gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
is(document.getElementById("identity-box").className,
gIdentityHandler.IDENTITY_MODE_MIXED_CONTENT,
"identity box has class name for mixed content");
gBrowser.removeCurrentTab();
finish();
}, true);
--- a/browser/base/content/test/browser_bug477014.js
+++ b/browser/base/content/test/browser_bug477014.js
@@ -44,37 +44,35 @@ function test() {
var newWindow;
var tabToDetach;
function onPageShow(event) {
// we get here if the test is executed before the pageshow
// event for the window's first tab
if (!tabToDetach ||
- tabToDetach.linkedBrowser.contentDocument != event.target) {
- return;
- }
+ tabToDetach.linkedBrowser.contentDocument != event.target)
+ return;
if (!newWindow) {
- var pageShowFunc = arguments.callee;
- gBrowser.removeEventListener("pageshow", pageShowFunc, false);
+ gBrowser.removeEventListener("pageshow", onPageShow, false);
// prepare the tab (set icon and busy state)
// we have to set these only after onState* notification, otherwise
// they're overriden
setTimeout(function() {
gBrowser.setIcon(tabToDetach, iconURLSpec);
tabToDetach.setAttribute("busy", "true");
// detach and set the listener on the new window
newWindow = gBrowser.replaceTabWithWindow(tabToDetach);
// wait for gBrowser to come along
function onLoad(event) {
newWindow.gBrowser
- .addEventListener("pageshow", pageShowFunc, false);
+ .addEventListener("pageshow", onPageShow, false);
newWindow.removeEventListener("load", arguments.callee, false);
}
newWindow.addEventListener("load", onLoad, false);
}, 0);
return;
}
is(newWindow.gBrowser.selectedTab.hasAttribute("busy"), true);
--- a/browser/base/content/test/browser_bug521216.js
+++ b/browser/base/content/test/browser_bug521216.js
@@ -1,19 +1,19 @@
-var expected = ["TabOpen", "onLinkIconAvailable", "onLocationChange", "onStateChange"];
+var expected = ["TabOpen", "onLocationChange", "onStateChange", "onLinkIconAvailable"];
var actual = [];
var tabIndex = -1;
__defineGetter__("tab", function () gBrowser.tabContainer.childNodes[tabIndex]);
function test() {
waitForExplicitFinish();
tabIndex = gBrowser.tabContainer.childElementCount;
gBrowser.addTabsProgressListener(progressListener);
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) {
info("got " + aName);
if (actual.indexOf(aName) == -1)
actual.push(aName);
if (actual.length == expected.length) {
is(actual.toString(), expected.toString(),
--- a/browser/base/content/test/browser_discovery.js
+++ b/browser/base/content/test/browser_discovery.js
@@ -1,24 +1,21 @@
-var gBrowserHandler;
+var currentHandler;
var browser;
function doc() browser.contentDocument;
function setHandlerFunc(aResultFunc) {
- DOMLinkHandler.handleEvent = function (event) {
- gBrowserHandler.call(DOMLinkHandler, event);
- aResultFunc();
- }
+ if (currentHandler)
+ gBrowser.removeEventListener("DOMLinkAdded", currentHandler, false);
+ gBrowser.addEventListener("DOMLinkAdded", aResultFunc, false);
+ currentHandler = aResultFunc;
}
function test() {
- gBrowserHandler = DOMLinkHandler.handleEvent;
- ok(gBrowserHandler, "found browser handler");
-
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
iconDiscovery();
}, true);
@@ -115,20 +112,17 @@ function runMultipleEnginesTestAndFinali
ranOnce = true;
return;
}
ok(browser.engines, "has engines");
is(browser.engines.length, 1, "only one engine");
is(browser.engines[0].uri, "http://first.mozilla.com/search.xml", "first engine wins");
gBrowser.removeCurrentTab();
-
- // Reset the default link handler
- DOMLinkHandler.handleEvent = gBrowserHandler;
-
+ gBrowser.removeEventListener("DOMLinkAdded", currentHandler, false);
finish();
}
function searchDiscovery() {
var head = doc().getElementById("linkparent");
if (searchDiscoveryTests.length) {
setHandlerFunc(runSearchDiscoveryTest);
--- a/browser/base/content/test/browser_pageInfo.js
+++ b/browser/base/content/test/browser_pageInfo.js
@@ -1,25 +1,29 @@
+var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+
function test() {
waitForExplicitFinish();
- var pageInfo, obs, atTest = 0;
- var gTestPage = gBrowser.addTab();
- gBrowser.selectedTab = gTestPage;
- gTestPage.linkedBrowser.addEventListener("load", handleLoad, true);
+ var pageInfo, atTest = 0;
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener("load", function () {
+ gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+ pageInfo = BrowserPageInfo();
+ obs.addObserver(observer, "page-info-dialog-loaded", false);
+ }, true);
content.location =
"https://example.com/browser/browser/base/content/test/feed_tab.html";
- gTestPage.focus();
var observer = {
observe: function(win, topic, data) {
if (topic != "page-info-dialog-loaded")
return;
- switch(atTest) {
+ switch (atTest) {
case 0:
atTest++;
handlePageInfo();
break;
case 1:
atTest++;
pageInfo = win;
testLockClick();
@@ -28,24 +32,16 @@ function test() {
atTest++;
obs.removeObserver(observer, "page-info-dialog-loaded");
testLockDoubleClick();
break;
}
}
}
- 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 handlePageInfo() {
var feedTab = $("feedTab");
var feedListbox = $("feedListbox");
ok(feedListbox, "Feed list is null (feeds tab is broken)");
@@ -77,23 +73,22 @@ function test() {
var lockIcon = document.getElementById("security-button");
EventUtils.synthesizeMouse(lockIcon, 0, 0, {clickCount: 1});
EventUtils.synthesizeMouse(lockIcon, 0, 0, {clickCount: 2});
}, false);
pageInfo.close();
}
function testLockDoubleClick() {
- var pageInfoDialogs = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator)
- .getEnumerator("Browser:page-info");
+ var pageInfoDialogs = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator)
+ .getEnumerator("Browser:page-info");
var i = 0;
- while(pageInfoDialogs.hasMoreElements()) {
+ while (pageInfoDialogs.hasMoreElements()) {
i++;
pageInfo = pageInfoDialogs.getNext();
pageInfo.close();
}
is(i, 1, "When the lock is clicked twice there should be only one page info dialog");
- gTestPage.focus();
gBrowser.removeCurrentTab();
finish();
}
}
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -372,20 +372,18 @@ function openAboutDialog()
{
#ifdef XP_MACOSX
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("Browser:About");
if (win)
win.focus();
else {
- // XXXmano: define minimizable=no although it does nothing on OS X
- // (see Bug 287162); remove this comment once Bug 287162 is fixed...
- window.open("chrome://browser/content/aboutDialog.xul", "About",
- "chrome, resizable=no, minimizable=no");
+ window.openDialog("chrome://browser/content/aboutDialog.xul", "About",
+ "chrome, resizable=no, minimizable=no");
}
#else
window.openDialog("chrome://browser/content/aboutDialog.xul", "About", "centerscreen,chrome,resizable=no");
#endif
}
function openPreferences(paneID, extraArgs)
{
--- a/browser/components/migration/src/nsOperaProfileMigrator.cpp
+++ b/browser/components/migration/src/nsOperaProfileMigrator.cpp
@@ -879,17 +879,19 @@ nsOperaCookieMigrator::AddCookieOverride
nsCOMPtr<nsIURI> uri(do_CreateInstance("@mozilla.org/network/standard-url;1"));
if (!uri)
return NS_ERROR_OUT_OF_MEMORY;
uri->SetHost(domain);
rv = aManager->Add(uri, "cookie",
(mCurrHandlingInfo == 1 || mCurrHandlingInfo == 3)
? (PRUint32) nsIPermissionManager::ALLOW_ACTION
- : (PRUint32) nsIPermissionManager::DENY_ACTION);
+ : (PRUint32) nsIPermissionManager::DENY_ACTION,
+ nsIPermissionManager::EXPIRE_NEVER,
+ 0);
mCurrHandlingInfo = 0;
return rv;
}
nsresult
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -73,56 +73,67 @@ const BrowserGlueServiceFactory = {
return this._instance == null ?
this._instance = new BrowserGlue() : this._instance;
}
};
// Constructor
function BrowserGlue() {
-
XPCOMUtils.defineLazyServiceGetter(this, "_prefs",
"@mozilla.org/preferences-service;1",
"nsIPrefBranch");
XPCOMUtils.defineLazyServiceGetter(this, "_bundleService",
"@mozilla.org/intl/stringbundle;1",
"nsIStringBundleService");
XPCOMUtils.defineLazyServiceGetter(this, "_idleService",
"@mozilla.org/widget/idleservice;1",
"nsIIdleService");
- XPCOMUtils.defineLazyServiceGetter(this, "_observerService",
- "@mozilla.org/observer-service;1",
- "nsIObserverService");
-
XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() {
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();
}
#ifndef XP_MACOSX
# OS X has the concept of zero-window sessions and therefore ignores the
# browser-lastwindow-close-* topics.
#define OBSERVE_LASTWINDOW_CLOSE_TOPICS 1
#endif
BrowserGlue.prototype = {
-
_saveSession: false,
_isIdleObserver: false,
_isPlacesInitObserver: false,
_isPlacesLockedObserver: false,
_isPlacesDatabaseLocked: false,
- _setPrefToSaveSession: function()
+ _setPrefToSaveSession: function(aForce)
{
+ if (!this._saveSession && !aForce)
+ return;
+
this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
// This method can be called via [NSApplication terminate:] on Mac, which
// ends up causing prefs not to be flushed to disk, so we need to do that
// explicitly here. See bug 497652.
this._prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
},
@@ -148,37 +159,33 @@ BrowserGlue.prototype = {
getService(Ci.nsIConsoleService);
cs.logStringMessage(null); // clear the console (in case it's open)
cs.reset();
break;
case "quit-application-requested":
this._onQuitRequest(subject, data);
break;
case "quit-application-granted":
- if (this._saveSession) {
- 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 pref must be set here because SessionStore will use its value
+ // on quit-application.
+ this._setPrefToSaveSession();
this._onProfileShutdown();
break;
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
case "browser-lastwindow-close-requested":
// The application is not actually quitting, but the last full browser
// window is about to be closed.
this._onQuitRequest(subject, "lastwindow");
break;
case "browser-lastwindow-close-granted":
- if (this._saveSession)
- this._setPrefToSaveSession();
+ this._setPrefToSaveSession();
break;
#endif
case "session-save":
- this._setPrefToSaveSession();
+ this._setPrefToSaveSession(true);
subject.QueryInterface(Ci.nsISupportsPRBool);
subject.data = true;
break;
case "places-init-complete":
this._initPlaces();
this._observerService.removeObserver(this, "places-init-complete");
this._isPlacesInitObserver = false;
// no longer needed, since history was initialized completely.
@@ -186,18 +193,18 @@ BrowserGlue.prototype = {
this._isPlacesLockedObserver = false;
// Now apply distribution customized bookmarks.
// This should always run after Places initialization.
this._distributionCustomizer.applyBookmarks();
break;
case "places-database-locked":
this._isPlacesDatabaseLocked = true;
- // stop observing, so further attempts to load history service
- // do not show the prompt.
+ // Stop observing, so further attempts to load history service
+ // will not show the prompt.
this._observerService.removeObserver(this, "places-database-locked");
this._isPlacesLockedObserver = false;
break;
case "idle":
if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000)
this._backupBookmarks();
break;
case "distribution-customization-complete":
@@ -263,17 +270,17 @@ BrowserGlue.prototype = {
// apply distribution customizations (prefs)
// other customizations are applied in _onProfileStartup()
this._distributionCustomizer.applyPrefDefaults();
},
// profile startup handler (contains profile initialization routines)
_onProfileStartup: function()
{
- this.Sanitizer.onStartup();
+ this._sanitizer.onStartup();
// check if we're in safe mode
var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
if (app.inSafeMode) {
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(null, "chrome://browser/content/safeMode.xul",
"_blank", "chrome,centerscreen,modal,resizable=no", null);
@@ -297,26 +304,27 @@ BrowserGlue.prototype = {
try {
ioService.offline = this._prefs.getBoolPref("browser.offline");
}
catch (e) {
ioService.offline = false;
}
}
- this._observerService.notifyObservers(null, "browser-ui-startup-complete", "");
+ this._observerService
+ .notifyObservers(null, "browser-ui-startup-complete", "");
},
// profile shutdown handler (contains profile cleanup routines)
_onProfileShutdown: function()
{
this._shutdownPlaces();
this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
this._isIdleObserver = false;
- this.Sanitizer.onShutdown();
+ this._sanitizer.onShutdown();
},
// Browser startup complete. All initial windows have opened.
_onBrowserStartup: function()
{
// Show about:rights notification, if needed.
if (this._shouldShowRights())
this._showRightsNotification();
@@ -567,27 +575,16 @@ BrowserGlue.prototype = {
getService(Ci.nsIURLFormatter);
var updateUrl = formatter.formatURLPref(PREF_PLUGINS_UPDATEURL);
var win = this.getMostRecentBrowserWindow();
var browser = win.gBrowser;
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
* - imports the bookmarks html file if bookmarks database is empty, try to
* restore bookmarks from a JSON backup if the backend indicates that the
* database was corrupt.
*
* These prefs can be set up by the frontend:
*
@@ -902,31 +899,31 @@ BrowserGlue.prototype = {
},
// ------------------------------
// public nsIBrowserGlue members
// ------------------------------
sanitize: function(aParentWindow)
{
- this.Sanitizer.sanitize(aParentWindow);
+ this._sanitizer.sanitize(aParentWindow);
},
ensurePlacesDefaultQueriesInitialized: function() {
// This is actual version of the smart bookmarks, must be increased every
// time smart bookmarks change.
// When adding a new smart bookmark below, its newInVersion property must
// be set to the version it has been added in, we will compare its value
// to users' smartBookmarksVersion and add new smart bookmarks without
// recreating old deleted ones.
const SMART_BOOKMARKS_VERSION = 2;
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
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;
// get current smart bookmarks version
// By default, if the pref is not set up, we must create Smart Bookmarks
var smartBookmarksCurrentVersion = 0;
try {
smartBookmarksCurrentVersion = this._prefs.getIntPref(SMART_BOOKMARKS_PREF);
} catch(ex) { /* no version set, new profile */ }
deleted file mode 100644
--- a/browser/components/places/content/advancedSearch.inc
+++ /dev/null
@@ -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>
deleted file mode 100644
--- a/browser/components/places/content/demos/time.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.day1 { background-color:white; }
-.day2 { background-color:#EEE; }
-.green { background-color:green; }
-.red { background-color:red; }
-
deleted file mode 100644
--- a/browser/components/places/content/demos/time.html
+++ /dev/null
@@ -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>
-
deleted file mode 100644
--- a/browser/components/places/content/demos/time.js
+++ /dev/null
@@ -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);
- }
- }
-}
deleted file mode 100644
--- a/browser/components/places/content/demos/time.xul
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.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 *****
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/content/places/demos/time.css"?>
-
-<window
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml">
-
- <script type="application/x-javascript"
- src="chrome://browser/content/places/demos/time.js"/>
-
-<hbox>
-<vbox id="daylist" style="border-right:1px solid black;">
-</vbox>
-
-
-<browser id="theframe" width="700" height="900" src="chrome://browser/content/places/demos/time.html" onload="BW_loadiframe();">
-</browser>
-</hbox>
-
-</window>
--- a/browser/components/places/content/organizer.css
+++ b/browser/components/places/content/organizer.css
@@ -1,13 +1,7 @@
-%ifdef PLACES_QUERY_BUILDER
-.history-calendar {
- -moz-binding: url("chrome://browser/content/places/places.xml#calendar");
-}
-%endif
-
#contentTitle {
width: 0px;
}
#searchFilter {
width: 23em;
}
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -83,21 +83,16 @@ var PlacesOrganizer = {
if (view.rowCount > 0)
view.selection.select(0);
this._content.focus();
// Set up the search UI.
PlacesSearchBox.init();
-#ifdef PLACES_QUERY_BUILDER
- // Set up the advanced query builder UI
- PlacesQueryBuilder.init();
-#endif
-
window.addEventListener("AppCommand", this, true);
#ifdef XP_MACOSX
// 1. Map Edit->Find command to OrganizerCommand_find:all. Need to map
// both the menuitem and the Find key.
var findMenuItem = document.getElementById("menu_find");
findMenuItem.setAttribute("command", "OrganizerCommand_find:all");
var findKey = document.getElementById("key_find");
findKey.setAttribute("command", "OrganizerCommand_find:all");
@@ -783,22 +778,17 @@ var PlacesOrganizer = {
/**
* Save the current search (or advanced query) to the bookmarks root.
*/
saveSearch: function PO_saveSearch() {
// Get the place: uri for the query.
// If the advanced query builder is showing, use that.
var options = this.getCurrentOptions();
-
-#ifdef PLACES_QUERY_BUILDER
- var queries = PlacesQueryBuilder.queries;
-#else
var queries = this.getCurrentQueries();
-#endif
var placeSpec = PlacesUtils.history.queriesToQueryString(queries,
queries.length,
options);
var placeURI = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI(placeSpec, null, null);
@@ -992,502 +982,32 @@ var PlacesSearchBox = {
set value(value) {
return this.searchFilter.value = value;
},
showSearchUI: function PSB_showSearchUI() {
// Hide the advanced search controls when the user hasn't searched
var searchModifiers = document.getElementById("searchModifiers");
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() {
var searchModifiers = document.getElementById("searchModifiers");
searchModifiers.hidden = true;
}
};
/**
* Functions and data for advanced query builder
*/
var PlacesQueryBuilder = {
queries: [],
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.
* @param aButton
* the scope button that was selected
*/
onScopeSelected: function PQB_onScopeSelected(aButton) {
switch (aButton.id) {
case "scopeBarHistory":
deleted file mode 100644
--- a/browser/components/places/content/places.xml
+++ /dev/null
@@ -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">«</xul:label>
- <xul:label anonid="monthtitle" class="calendar-month-title" flex="1"/>
- <xul:label anonid="nextmonth" class="calendar-month-jump">»</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>
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -284,35 +284,16 @@
</toolbarbutton>
<toolbarbutton type="menu" class="tabbable"
#else
</menu>
<menu accesskey="&views.accesskey;" class="menu-iconic"
#endif
id="viewMenu" label="&views.label;">
<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"
label="&view.columns.label;" accesskey="&view.columns.accesskey;">
<menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
</menu>
<menu id="viewSort" label="&view.sort.label;"
@@ -326,24 +307,16 @@
<menuitem id="viewSortAscending" type="radio" name="direction"
label="&view.sortAscending.label;" accesskey="&view.sortAscending.accesskey;"
oncommand="ViewMenu.setSortColumn(null, 'ascending'); event.stopPropagation();"/>
<menuitem id="viewSortDescending" type="radio" name="direction"
label="&view.sortDescending.label;" accesskey="&view.sortDescending.accesskey;"
oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
</menupopup>
</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>
#ifdef XP_MACOSX
</toolbarbutton>
<toolbarbutton type="menu" class="tabbable"
#else
</menu>
<menu accesskey="&maintenance.accesskey;" class="menu-iconic"
#endif
@@ -436,28 +409,18 @@
emptytitle="&search.scopeFolder.label;" flex="1"/>
<!-- The folder scope button should flex but not take up more room
than its label needs. The only simple way to do that is to
set a really big flex on the spacer, e.g., 2^31 - 1. -->
<spacer flex="2147483647"/>
<button id="saveSearch" class="small"
label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
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>
-#include advancedSearch.inc
-#else
- </toolbar>
-#endif
+
</vbox>
<vbox flex="1">
<tree id="placeContent" class="placesTree" context="placesContext"
hidecolumnpicker="true"
flex="1" type="places"
flatList="true"
enableColumnDrag="true"
onkeypress="if (event.keyCode == KeyEvent.DOM_VK_RETURN) PlacesOrganizer.openSelectedNode(event);"
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -1135,32 +1135,36 @@
// show indicator bar and move it to the appropriate drop point.
let ind = this._dropIndicator;
let halfInd = ind.clientWidth / 2;
let translateX;
if (this._isRTL) {
halfInd = Math.ceil(halfInd);
translateX = 0 - this._scrollbox.getBoundingClientRect().right -
halfInd;
- if (dropPoint.beforeIndex == -1)
- translateX += this.lastChild.getBoundingClientRect().left;
- else if (this.childNodes.length) {
- translateX += this.childNodes[dropPoint.beforeIndex]
+ if (this.firstChild) {
+ if (dropPoint.beforeIndex == -1)
+ translateX += this.lastChild.getBoundingClientRect().left;
+ else {
+ translateX += this.childNodes[dropPoint.beforeIndex]
.getBoundingClientRect().right;
+ }
}
}
else {
halfInd = Math.floor(halfInd);
translateX = 0 - this._scrollbox.getBoundingClientRect().left +
halfInd;
- if (dropPoint.beforeIndex == -1)
- translateX += this.lastChild.getBoundingClientRect().right;
- else if (this.childNodes.length) {
- translateX += this.childNodes[dropPoint.beforeIndex]
- .getBoundingClientRect().left;
+ if (this.firstChild) {
+ if (dropPoint.beforeIndex == -1)
+ translateX += this.lastChild.getBoundingClientRect().right;
+ else {
+ translateX += this.childNodes[dropPoint.beforeIndex]
+ .getBoundingClientRect().left;
+ }
}
}
ind.style.MozTransform = "translate(" + Math.round(translateX) + "px)";
ind.style.MozMarginStart = (-ind.clientWidth) + "px";
ind.collapsed = false;
// Clear out old folder information
--- a/browser/components/places/jar.mn
+++ b/browser/components/places/jar.mn
@@ -1,30 +1,25 @@
browser.jar:
# Provide another URI for the bookmarkProperties dialog so we can persist the
# 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.js (content/places.js)
-* content/browser/places/places.xml (content/places.xml)
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.js (content/bookmarkProperties.js)
* content/browser/places/placesOverlay.xul (content/placesOverlay.xul)
* content/browser/places/toolbar.xml (content/toolbar.xml)
* content/browser/places/menu.xml (content/menu.xml)
* content/browser/places/tree.xml (content/tree.xml)
* content/browser/places/utils.js (content/utils.js)
* content/browser/places/controller.js (content/controller.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
# to prevent having to worry about between versions of the browser
* content/browser/history/history-panel.xul (content/history-panel.xul)
* content/browser/places/history-panel.js (content/history-panel.js)
# ditto for the bookmarks sidebar
* content/browser/bookmarks/bookmarksPanel.xul (content/bookmarksPanel.xul)
* content/browser/bookmarks/bookmarksPanel.js (content/bookmarksPanel.js)
* content/browser/bookmarks/sidebarUtils.js (content/sidebarUtils.js)
--- a/browser/components/places/tests/perf/Makefile.in
+++ b/browser/components/places/tests/perf/Makefile.in
@@ -43,23 +43,25 @@ relativesrcdir = browser/components/plac
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_CHROME_FILES = \
perf_large_delete.xul \
$(NULL)
-# XXX disabled tests, not working properly yet
-# browser_ui_history_menu.js
-# browser_ui_locationbar.js
-# XXX disabled tests, random failures
-# browser_ui_bookmarks_sidebar.js
+# Disabled due to bad interactions with next tests.
+# browser_ui_locationbar.js
+# Disabled due to random failures.
+# browser_ui_bookmarks_sidebar.js
_BROWSER_TEST_FILES = \
browser_ui_000_data.js \
+ browser_ui_history_menu.js \
browser_ui_history_sidebar.js \
+ browser_ui_history_sidebar_2.js \
+ browser_ui_history_sidebar_3.js \
$(NULL)
libs:: $(_CHROME_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/places/tests/perf/browser_ui_bookmarks_sidebar.js
+++ b/browser/components/places/tests/perf/browser_ui_bookmarks_sidebar.js
@@ -15,16 +15,17 @@
*
* 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
@@ -57,23 +58,23 @@ var win = wm.getMostRecentWindow("naviga
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);
function add_visit(aURI, aDate) {
- var placeID = hs.addVisit(aURI,
+ var visitId = hs.addVisit(aURI,
aDate,
null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect
0);
- return placeID;
+ return visitId;
}
function add_bookmark(aURI) {
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
return bId;
}
@@ -81,17 +82,17 @@ function make_test_report(testName, resu
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 = 10;
+const TEST_REPEAT_COUNT = 6;
// test duration of bookmarks sidebar opening
ptests.push({
name: "open_bookmarks_sidebar",
times: [],
run: function() {
var self = this;
var start = Date.now();
@@ -111,23 +112,24 @@ ptests.push({
finish: function() {
this.times.sort(); // sort the scores
this.times.pop(); // remove worst
this.times.shift(); // remove best
var totalDuration = this.times.reduce(function(time, total){ return time + total; });
var avgDuration = totalDuration/this.times.length;
var report = make_test_report("open_bookmarks_sidebar", avgDuration);
ok(true, report);
- runNextTest();
+ setTimeout(runNextTest, 0);
}
});
function test() {
// kick off tests
- runNextTest();
+ setTimeout(runNextTest, 0);
}
function runNextTest() {
- if (ptests.length > 0)
+ if (ptests.length > 0) {
ptests.shift().run();
+ }
else
finish();
}
--- a/browser/components/places/tests/perf/browser_ui_history_menu.js
+++ b/browser/components/places/tests/perf/browser_ui_history_menu.js
@@ -15,16 +15,17 @@
*
* 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
@@ -35,18 +36,16 @@
*
* ***** END LICENSE BLOCK ***** */
/*
Tests the performance of opening the history menu.
*/
/*********************** 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"].
@@ -55,24 +54,27 @@ var win = wm.getMostRecentWindow("naviga
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 historyMenu = document.getElementById("history-menu");
+var historyPopup = document.getElementById("goPopup");
+
function add_visit(aURI, aDate) {
- var placeID = hs.addVisit(aURI,
+ var visitId = hs.addVisit(aURI,
aDate,
null, // no referrer
hs.TRANSITION_TYPED, // user typed in URL bar
false, // not redirect
0);
- return placeID;
+ return visitId;
}
function add_bookmark(aURI) {
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
return bId;
}
@@ -80,48 +82,66 @@ function make_test_report(testName, resu
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 menu opening
ptests.push({
name: "open_history_menu",
+ times: [],
run: function() {
- var menu = document.getElementById("history-menu");
- ok(menu, "history menu should exist!");
+ var self = this;
var start = Date.now();
-
- var popup = document.getElementById("goPopup");
- popup.addEventListener("popupshown", function() {
- var duration = Date.now() - start;
- var report = make_test_report("open_history_menu", duration);
- ok(true, report);
-
- // clean up
- popup.removeEventListener("popupshown", arguments.callee, false);
- menu.open = false;
-
- runNextTest();
- }, false);
-
- // XXX does not work, is still open=false immediately after setting it to true
- //menu.open = true;
-
- // XXX does nada
- //EventUtils.sendMouseEvent({type:"click"}, "history-menu");
+ historyPopup.addEventListener("popupshown", function() {
+ historyPopup.removeEventListener("popupshown", arguments.callee, true);
+ executeSoon(function() {
+ var duration = Date.now() - start;
+ historyPopup.hidePopup();
+ historyMenu.open = false;
+ self.times.push(duration);
+ if (self.times.length == TEST_REPEAT_COUNT)
+ self.finish();
+ else
+ self.run();
+ });
+ }, true);
+ historyMenu.open = true;
+ historyPopup.openPopup();
+ },
+ 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() {
+ // Skip test on Mac due to native menus.
+ if (navigator.platform.toLowerCase().indexOf("mac") != -1)
+ return;
+
+ waitForExplicitFinish();
+
// kick off tests
- runNextTest();
+ setTimeout(runNextTest, 0);
}
function runNextTest() {
if (ptests.length > 0)
ptests.shift().run();
else
finish();
}
--- a/browser/components/places/tests/perf/browser_ui_history_sidebar.js
+++ b/browser/components/places/tests/perf/browser_ui_history_sidebar.js
@@ -15,16 +15,17 @@
*
* 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
@@ -82,17 +83,17 @@ function make_test_report(testName, resu
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 = 10;
+const TEST_REPEAT_COUNT = 6;
// test duration of history sidebar opening
// default: bydayandsite
ptests.push({
name: "open_history_sidebar_bydayandsite",
times: [],
run: function() {
var self = this;
@@ -108,17 +109,17 @@ ptests.push({
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
- runNextTest();
+ setTimeout(runNextTest, 0);
}
});
// bysite
ptests.push({
name: "history_sidebar_bysite",
times: [],
run: function() {
@@ -136,17 +137,17 @@ ptests.push({
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
- runNextTest();
+ setTimeout(runNextTest, 0);
}
});
// byday
ptests.push({
name: "history_sidebar_byday",
times: [],
run: function() {
@@ -164,89 +165,33 @@ ptests.push({
else
self.run();
});
}, true);
toggleSidebar("viewHistorySidebar", true);
},
finish: function() {
processTestResult(this);
- runNextTest();
- }
-});
-
-// 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();
+ 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
- runNextTest();
+ setTimeout(runNextTest, 0);
}
function runNextTest() {
if (ptests.length > 0)
ptests.shift().run();
else
finish();
}
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/perf/browser_ui_history_sidebar_2.js
@@ -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() {
<