зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to electrolysis.
This commit is contained in:
Коммит
9ae75c423f
|
@ -4,6 +4,7 @@
|
|||
~$
|
||||
\.pyc$
|
||||
(^|/)TAGS$
|
||||
(^|/)ID$
|
||||
(^|/)\.DS_Store$
|
||||
|
||||
# User files that may appear at the root
|
||||
|
@ -12,7 +13,6 @@
|
|||
^configure$
|
||||
^config\.cache$
|
||||
^config\.log$
|
||||
^ID$
|
||||
|
||||
# Empty marker file that's generated when we check out NSS
|
||||
^security/manager/\.nss\.checkout$
|
||||
|
@ -27,6 +27,8 @@ _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/
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
* @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
|
||||
{
|
||||
/**
|
||||
|
@ -776,10 +776,15 @@ interface nsIAccessibleRole : nsISupports
|
|||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ static const PRUint32 atkRoleMap[] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -408,14 +408,30 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
|||
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) {
|
||||
|
@ -426,8 +442,9 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
|||
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);
|
||||
|
@ -445,19 +462,25 @@ nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem,
|
|||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
|
|
@ -548,6 +548,15 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame *aFrame,
|
|||
*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) {
|
||||
|
@ -763,15 +772,16 @@ nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame *aFrame,
|
|||
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
|
||||
|
||||
|
|
|
@ -289,7 +289,8 @@ static const char kRoleNames[][20] = {
|
|||
"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
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -2492,13 +2492,16 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -924,20 +924,12 @@ 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
|
||||
|
@ -946,8 +938,6 @@ nsHTMLTableAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aIndex);
|
||||
|
||||
NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsITableLayout *tableLayout = GetTableLayout();
|
||||
NS_ENSURE_STATE(tableLayout);
|
||||
|
||||
|
@ -970,7 +960,10 @@ nsHTMLTableAccessible::GetColumnIndexAt(PRInt32 aIndex, PRInt32 *aColumn)
|
|||
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
|
||||
|
@ -985,7 +978,10 @@ nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
|
|||
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
|
||||
|
@ -993,9 +989,6 @@ 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);
|
||||
|
||||
|
@ -1003,19 +996,18 @@ nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
|
|||
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);
|
||||
|
||||
|
@ -1023,10 +1015,12 @@ nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
|
|||
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
|
||||
|
@ -1042,51 +1036,63 @@ nsHTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString &_retval)
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -1096,9 +1102,6 @@ nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
|
|||
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);
|
||||
|
||||
|
@ -1116,22 +1119,6 @@ nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -143,20 +143,6 @@ public:
|
|||
|
||||
// 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.
|
||||
*/
|
||||
|
|
|
@ -164,5 +164,6 @@ static const NSString* AXRoles [] = {
|
|||
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)!
|
||||
};
|
||||
|
|
|
@ -39,13 +39,21 @@
|
|||
#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()
|
||||
{
|
||||
|
@ -54,37 +62,83 @@ nsHTMLWin32ObjectOwnerAccessible::Shutdown()
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,10 @@ public:
|
|||
// nsAccessNode
|
||||
virtual nsresult Shutdown();
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetRoleInternal(PRUint32 *aRole);
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
||||
protected:
|
||||
void* mHwnd;
|
||||
nsCOMPtr<nsIAccessible> mNativeAccessible;
|
||||
|
|
|
@ -440,6 +440,9 @@ static const WindowsRoleMapItem gWindowsRoleMap[] = {
|
|||
// 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 }
|
||||
};
|
||||
|
|
|
@ -89,6 +89,7 @@ _TEST_FILES =\
|
|||
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 \
|
||||
|
@ -159,6 +160,7 @@ _TEST_FILES =\
|
|||
test_textattrs.html \
|
||||
test_textboxes.html \
|
||||
test_textboxes.xul \
|
||||
test_value.html \
|
||||
test_value.xul \
|
||||
testTextboxes.js \
|
||||
treeview.css \
|
||||
|
|
|
@ -12,6 +12,7 @@ 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;
|
||||
|
|
|
@ -94,10 +94,12 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
|
|||
}
|
||||
|
||||
// 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!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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>
|
|
@ -49,6 +49,12 @@
|
|||
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).
|
||||
|
@ -147,6 +153,21 @@
|
|||
<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>
|
||||
|
|
|
@ -69,6 +69,30 @@
|
|||
// 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();
|
||||
}
|
||||
|
||||
|
@ -140,5 +164,24 @@
|
|||
<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>
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
function doTest()
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// table
|
||||
|
||||
var cellsArray =
|
||||
[
|
||||
[false, false, false, kColSpanned, false, false, false, false],
|
||||
|
@ -53,6 +56,20 @@
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -77,6 +94,11 @@
|
|||
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>
|
||||
|
@ -122,6 +144,37 @@
|
|||
</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>
|
||||
|
|
|
@ -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>
|
|
@ -298,9 +298,6 @@ libs::
|
|||
endif
|
||||
endif
|
||||
|
||||
libs::
|
||||
touch $(DIST)/bin/.autoreg
|
||||
|
||||
libs:: $(srcdir)/profile/prefs.js
|
||||
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile
|
||||
|
||||
|
|
|
@ -338,7 +338,6 @@ 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);
|
||||
|
|
|
@ -134,6 +134,43 @@ td {
|
|||
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"]
|
||||
|
@ -144,16 +181,9 @@ window.onload = function () {
|
|||
.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.
|
||||
|
@ -193,7 +223,7 @@ function populatePreferencesSection() {
|
|||
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);
|
||||
}
|
||||
|
@ -201,6 +231,18 @@ function populatePreferencesSection() {
|
|||
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
|
||||
|
@ -209,13 +251,27 @@ function getModifiedPrefs() {
|
|||
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);
|
||||
|
@ -275,7 +331,10 @@ function createTextForElement(elem) {
|
|||
// 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;
|
||||
}
|
||||
|
@ -316,6 +375,19 @@ function generateTextForTextNode(node, indent, textFragmentAccumulator) {
|
|||
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>
|
||||
|
@ -369,10 +441,17 @@ function generateTextForTextNode(node, indent, textFragmentAccumulator) {
|
|||
&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;
|
||||
|
|
|
@ -220,8 +220,13 @@ function SetClickAndHoldHandlers() {
|
|||
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) {
|
||||
|
@ -786,13 +791,14 @@ let gGestureSupport = {
|
|||
_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;
|
||||
}, []);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -807,47 +813,44 @@ let gGestureSupport = {
|
|||
* 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("."));
|
||||
// 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) {}
|
||||
|
||||
// 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);
|
||||
if (!command)
|
||||
continue;
|
||||
|
||||
return command;
|
||||
let node = document.getElementById(command);
|
||||
if (node) {
|
||||
if (node.getAttribute("disabled") != "true") {
|
||||
let cmdEvent = document.createEvent("xulcommandevent");
|
||||
cmdEvent.initCommandEvent("command", true, true, window, 0,
|
||||
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
|
||||
aEvent.metaKey, null);
|
||||
node.dispatchEvent(cmdEvent);
|
||||
}
|
||||
} else {
|
||||
goDoCommand(command);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
// The generator ran out of key combinations, so just do nothing
|
||||
catch (e) {}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -289,7 +289,7 @@
|
|||
<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>
|
||||
|
|
|
@ -525,7 +525,7 @@
|
|||
|
||||
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;
|
||||
|
@ -1266,7 +1266,7 @@
|
|||
"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"));
|
||||
|
@ -2865,14 +2865,6 @@
|
|||
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>
|
||||
|
@ -2882,10 +2874,6 @@
|
|||
|
||||
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)
|
||||
|
@ -2893,59 +2881,9 @@
|
|||
|
||||
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"
|
||||
|
@ -2981,15 +2919,12 @@
|
|||
<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>
|
||||
|
@ -3168,19 +3103,13 @@
|
|||
"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">
|
||||
|
@ -3199,10 +3128,8 @@
|
|||
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>
|
||||
|
@ -3232,32 +3159,49 @@
|
|||
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++;
|
||||
|
@ -3527,14 +3471,9 @@
|
|||
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]);
|
||||
}
|
||||
|
@ -3554,7 +3493,7 @@
|
|||
}
|
||||
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">
|
||||
|
|
|
@ -2,8 +2,8 @@ var gTestPage = "http://example.org/browser/browser/base/content/test/dummy_page
|
|||
var gTestImage = "http://example.org/browser/browser/base/content/test/moz.png";
|
||||
var gTab1, gTab2, gTab3;
|
||||
var gLevel;
|
||||
const kBack = 0;
|
||||
const kForward = 1;
|
||||
const BACK = 0;
|
||||
const FORWARD = 1;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
@ -59,8 +59,8 @@ function imageLoaded() {
|
|||
}
|
||||
|
||||
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");
|
||||
|
@ -116,9 +116,9 @@ function testPrintPreview(aTab, aCallback) {
|
|||
aCallback();
|
||||
};
|
||||
|
||||
let printPreview = new Function(document.getElementById("cmd_printPreview")
|
||||
.getAttribute("oncommand"));
|
||||
executeSoon(printPreview);
|
||||
executeSoon(function () {
|
||||
document.getElementById("cmd_printPreview").doCommand();
|
||||
});
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
|
@ -145,12 +145,12 @@ function load(tab, url, cb) {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ function continue_test_prefNotSet () {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -49,6 +49,7 @@ function test() {
|
|||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
setTimeout(function () {
|
||||
var testPageWin = content;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ 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));
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ function test() {
|
|||
|
||||
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");
|
||||
|
|
|
@ -49,13 +49,11 @@ function test() {
|
|||
// 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
|
||||
|
@ -69,7 +67,7 @@ function test() {
|
|||
// 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);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var expected = ["TabOpen", "onLinkIconAvailable", "onLocationChange", "onStateChange"];
|
||||
var expected = ["TabOpen", "onLocationChange", "onStateChange", "onLinkIconAvailable"];
|
||||
var actual = [];
|
||||
var tabIndex = -1;
|
||||
__defineGetter__("tab", function () gBrowser.tabContainer.childNodes[tabIndex]);
|
||||
|
@ -8,7 +8,7 @@ function test() {
|
|||
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) {
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
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();
|
||||
|
@ -120,10 +117,7 @@ function runMultipleEnginesTestAndFinalize() {
|
|||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
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();
|
||||
|
@ -33,14 +37,6 @@ function test() {
|
|||
}
|
||||
}
|
||||
|
||||
function handleLoad() {
|
||||
|
||||
pageInfo = BrowserPageInfo();
|
||||
obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
obs.addObserver(observer, "page-info-dialog-loaded", false);
|
||||
}
|
||||
|
||||
function $(aId) { return pageInfo.document.getElementById(aId) };
|
||||
|
||||
function handlePageInfo() {
|
||||
|
@ -82,17 +78,16 @@ function test() {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -377,10 +377,8 @@ function openAboutDialog()
|
|||
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");
|
||||
|
|
|
@ -884,7 +884,9 @@ nsOperaCookieMigrator::AddCookieOverride(nsIPermissionManager* aManager)
|
|||
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;
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ const BrowserGlueServiceFactory = {
|
|||
// Constructor
|
||||
|
||||
function BrowserGlue() {
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_prefs",
|
||||
"@mozilla.org/preferences-service;1",
|
||||
"nsIPrefBranch");
|
||||
|
@ -91,14 +90,24 @@ function BrowserGlue() {
|
|||
"@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();
|
||||
}
|
||||
|
||||
|
@ -109,15 +118,17 @@ function BrowserGlue() {
|
|||
#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
|
||||
|
@ -153,12 +164,9 @@ BrowserGlue.prototype = {
|
|||
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
|
||||
|
@ -168,12 +176,11 @@ BrowserGlue.prototype = {
|
|||
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;
|
||||
|
@ -191,8 +198,8 @@ BrowserGlue.prototype = {
|
|||
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;
|
||||
|
@ -268,7 +275,7 @@ BrowserGlue.prototype = {
|
|||
// 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);
|
||||
|
@ -302,7 +309,8 @@ BrowserGlue.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
this._observerService.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
this._observerService
|
||||
.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
},
|
||||
|
||||
// profile shutdown handler (contains profile cleanup routines)
|
||||
|
@ -311,7 +319,7 @@ BrowserGlue.prototype = {
|
|||
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.
|
||||
|
@ -572,17 +580,6 @@ BrowserGlue.prototype = {
|
|||
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
|
||||
|
@ -907,7 +904,7 @@ BrowserGlue.prototype = {
|
|||
|
||||
sanitize: function(aParentWindow)
|
||||
{
|
||||
this.Sanitizer.sanitize(aParentWindow);
|
||||
this._sanitizer.sanitize(aParentWindow);
|
||||
},
|
||||
|
||||
ensurePlacesDefaultQueriesInitialized: function() {
|
||||
|
@ -921,7 +918,7 @@ BrowserGlue.prototype = {
|
|||
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
|
||||
|
|
|
@ -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>
|
|
@ -1,5 +0,0 @@
|
|||
.day1 { background-color:white; }
|
||||
.day2 { background-color:#EEE; }
|
||||
.green { background-color:green; }
|
||||
.red { background-color:red; }
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,3 @@
|
|||
%ifdef PLACES_QUERY_BUILDER
|
||||
.history-calendar {
|
||||
-moz-binding: url("chrome://browser/content/places/places.xml#calendar");
|
||||
}
|
||||
%endif
|
||||
|
||||
#contentTitle {
|
||||
width: 0px;
|
||||
}
|
||||
|
|
|
@ -88,11 +88,6 @@ var PlacesOrganizer = {
|
|||
// 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
|
||||
|
@ -788,12 +783,7 @@ var PlacesOrganizer = {
|
|||
// 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,
|
||||
|
@ -997,12 +987,6 @@ var PlacesSearchBox = {
|
|||
// 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() {
|
||||
|
@ -1019,470 +1003,6 @@ 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
|
||||
|
|
|
@ -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>
|
|
@ -289,25 +289,6 @@
|
|||
#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;">
|
||||
|
@ -331,14 +312,6 @@
|
|||
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>
|
||||
|
@ -441,18 +414,8 @@
|
|||
<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"
|
||||
|
|
|
@ -1140,22 +1140,26 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
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)
|
||||
|
@ -16,10 +15,6 @@ browser.jar:
|
|||
* 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)
|
||||
|
|
|
@ -48,14 +48,16 @@ _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)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -62,13 +63,13 @@ 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) {
|
||||
|
@ -86,7 +87,7 @@ var ptests = [];
|
|||
|
||||
/*********************** end header **********************/
|
||||
|
||||
const TEST_REPEAT_COUNT = 10;
|
||||
const TEST_REPEAT_COUNT = 6;
|
||||
|
||||
// test duration of bookmarks sidebar opening
|
||||
ptests.push({
|
||||
|
@ -116,18 +117,19 @@ ptests.push({
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -40,8 +41,6 @@ Tests the performance of opening the history menu.
|
|||
*/
|
||||
|
||||
/*********************** begin header **********************/
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_IDENTIFIER = "ui-perf-test";
|
||||
const TEST_SUITE = "places";
|
||||
|
||||
|
@ -60,14 +59,17 @@ var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
|||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
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) {
|
||||
|
@ -85,38 +87,56 @@ 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() {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -87,7 +88,7 @@ var ptests = [];
|
|||
|
||||
/*********************** end header **********************/
|
||||
|
||||
const TEST_REPEAT_COUNT = 10;
|
||||
const TEST_REPEAT_COUNT = 6;
|
||||
|
||||
// test duration of history sidebar opening
|
||||
// default: bydayandsite
|
||||
|
@ -113,7 +114,7 @@ ptests.push({
|
|||
},
|
||||
finish: function() {
|
||||
processTestResult(this);
|
||||
runNextTest();
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -141,7 +142,7 @@ ptests.push({
|
|||
},
|
||||
finish: function() {
|
||||
processTestResult(this);
|
||||
runNextTest();
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -169,63 +170,7 @@ ptests.push({
|
|||
},
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -241,7 +186,7 @@ function processTestResult(aTest) {
|
|||
|
||||
function test() {
|
||||
// kick off tests
|
||||
runNextTest();
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
Tests the performance of opening the History
|
||||
sidebar in all the available views.
|
||||
*/
|
||||
|
||||
/*********************** begin header **********************/
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_IDENTIFIER = "ui-perf-test";
|
||||
const TEST_SUITE = "places";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
|
||||
function add_visit(aURI, aDate) {
|
||||
var visitId = hs.addVisit(aURI,
|
||||
aDate,
|
||||
null, // no referrer
|
||||
hs.TRANSITION_TYPED, // user typed in URL bar
|
||||
false, // not redirect
|
||||
0);
|
||||
return visitId;
|
||||
}
|
||||
|
||||
function add_bookmark(aURI) {
|
||||
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
|
||||
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
|
||||
return bId;
|
||||
}
|
||||
|
||||
function make_test_report(testName, result, units) {
|
||||
return [TEST_IDENTIFIER, TEST_SUITE, testName, result, units||"ms"].join(":");
|
||||
}
|
||||
|
||||
// Each test is an obj w/ a name property and run method
|
||||
var ptests = [];
|
||||
|
||||
/*********************** end header **********************/
|
||||
|
||||
const TEST_REPEAT_COUNT = 6;
|
||||
|
||||
// test duration of history sidebar opening
|
||||
// byvisited
|
||||
ptests.push({
|
||||
name: "history_sidebar_byvisited",
|
||||
times: [],
|
||||
run: function() {
|
||||
var self = this;
|
||||
var start = Date.now();
|
||||
sidebar.addEventListener("load", function() {
|
||||
sidebar.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
var duration = Date.now() - start;
|
||||
sidebar.contentDocument.getElementById("byvisited").doCommand();
|
||||
toggleSidebar("viewHistorySidebar", false);
|
||||
self.times.push(duration);
|
||||
if (self.times.length == TEST_REPEAT_COUNT)
|
||||
self.finish();
|
||||
else
|
||||
self.run();
|
||||
});
|
||||
}, true);
|
||||
toggleSidebar("viewHistorySidebar", true);
|
||||
},
|
||||
finish: function() {
|
||||
processTestResult(this);
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
});
|
||||
|
||||
function processTestResult(aTest) {
|
||||
aTest.times.sort(); // sort the scores
|
||||
aTest.times.pop(); // remove worst
|
||||
aTest.times.shift(); // remove best
|
||||
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
|
||||
var avgDuration = totalDuration/aTest.times.length;
|
||||
var report = make_test_report(aTest.name, avgDuration);
|
||||
ok(true, report);
|
||||
}
|
||||
|
||||
function test() {
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (ptests.length > 0)
|
||||
ptests.shift().run();
|
||||
else
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
Tests the performance of opening the History
|
||||
sidebar in all the available views.
|
||||
*/
|
||||
|
||||
/*********************** begin header **********************/
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_IDENTIFIER = "ui-perf-test";
|
||||
const TEST_SUITE = "places";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
|
||||
function add_visit(aURI, aDate) {
|
||||
var visitId = hs.addVisit(aURI,
|
||||
aDate,
|
||||
null, // no referrer
|
||||
hs.TRANSITION_TYPED, // user typed in URL bar
|
||||
false, // not redirect
|
||||
0);
|
||||
return visitId;
|
||||
}
|
||||
|
||||
function add_bookmark(aURI) {
|
||||
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
|
||||
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
|
||||
return bId;
|
||||
}
|
||||
|
||||
function make_test_report(testName, result, units) {
|
||||
return [TEST_IDENTIFIER, TEST_SUITE, testName, result, units||"ms"].join(":");
|
||||
}
|
||||
|
||||
// Each test is an obj w/ a name property and run method
|
||||
var ptests = [];
|
||||
|
||||
/*********************** end header **********************/
|
||||
|
||||
const TEST_REPEAT_COUNT = 6;
|
||||
|
||||
// test duration of history sidebar opening
|
||||
// bylastvisited
|
||||
ptests.push({
|
||||
name: "history_sidebar_bylastvisited",
|
||||
times: [],
|
||||
run: function() {
|
||||
var self = this;
|
||||
var start = Date.now();
|
||||
sidebar.addEventListener("load", function() {
|
||||
sidebar.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
var duration = Date.now() - start;
|
||||
sidebar.contentDocument.getElementById("bylastvisited").doCommand();
|
||||
toggleSidebar("viewHistorySidebar", false);
|
||||
self.times.push(duration);
|
||||
if (self.times.length == TEST_REPEAT_COUNT)
|
||||
self.finish();
|
||||
else
|
||||
self.run();
|
||||
});
|
||||
}, true);
|
||||
toggleSidebar("viewHistorySidebar", true);
|
||||
},
|
||||
finish: function() {
|
||||
processTestResult(this);
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
});
|
||||
|
||||
function processTestResult(aTest) {
|
||||
aTest.times.sort(); // sort the scores
|
||||
aTest.times.pop(); // remove worst
|
||||
aTest.times.shift(); // remove best
|
||||
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
|
||||
var avgDuration = totalDuration/aTest.times.length;
|
||||
var report = make_test_report(aTest.name, avgDuration);
|
||||
ok(true, report);
|
||||
}
|
||||
|
||||
function test() {
|
||||
// kick off tests
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (ptests.length > 0)
|
||||
ptests.shift().run();
|
||||
else
|
||||
finish();
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* 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
|
||||
|
@ -59,15 +60,20 @@ 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 prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
var maxResults = prefs.getIntPref("browser.urlbar.maxRichResults");
|
||||
var onSearchComplete = gURLBar.onSearchComplete;
|
||||
|
||||
function add_visit(aURI, aDate) {
|
||||
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) {
|
||||
|
@ -85,30 +91,61 @@ var ptests = [];
|
|||
|
||||
/*********************** end header **********************/
|
||||
|
||||
// test duration of history menu opening
|
||||
const TEST_REPEAT_COUNT = 6;
|
||||
|
||||
// test duration of locationbar searching
|
||||
ptests.push({
|
||||
name: "open_locationbar_default",
|
||||
times: [],
|
||||
run: function() {
|
||||
var urlbar = document.getElementById("urlbar");
|
||||
urlbar.addEventListener("onsearchcomplete", function() {
|
||||
urlbar.removeEventListener("onsearchcomplete", arguments.callee, false);
|
||||
runNextTest();
|
||||
}, false);
|
||||
|
||||
urlbar.value = "example";
|
||||
urlbar.select();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
var self = this;
|
||||
var start = Date.now();
|
||||
var acItemsCount = 1;
|
||||
gURLBar.onSearchComplete = function() {
|
||||
executeSoon(function() {
|
||||
var duration = Date.now() - start;
|
||||
self.times.push(duration);
|
||||
if (self.times.length == TEST_REPEAT_COUNT)
|
||||
self.finish();
|
||||
else
|
||||
self.run();
|
||||
});
|
||||
};
|
||||
window.focus();
|
||||
gURLBar.focus();
|
||||
var synthesizeSearch = function() {
|
||||
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
|
||||
EventUtils.synthesizeKey("e", {});
|
||||
};
|
||||
waitForFocus(synthesizeSearch);
|
||||
},
|
||||
finish: function() {
|
||||
gURLBar.value = "";
|
||||
processTestResult(this);
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
});
|
||||
|
||||
function processTestResult(aTest) {
|
||||
aTest.times.sort(); // sort the scores
|
||||
aTest.times.pop(); // remove worst
|
||||
aTest.times.shift(); // remove best
|
||||
var totalDuration = aTest.times.reduce(function(time, total){ return time + total; });
|
||||
var avgDuration = totalDuration/aTest.times.length;
|
||||
var report = make_test_report(aTest.name, avgDuration);
|
||||
ok(true, report);
|
||||
}
|
||||
|
||||
function test() {
|
||||
// kick off tests
|
||||
runNextTest();
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (ptests.length > 0)
|
||||
ptests.shift().run();
|
||||
else
|
||||
else {
|
||||
gURLBar.onSearchComplete = onSearchComplete;
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ function test()
|
|||
// Close the window if it's already open
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
let win = wm.getMostRecentWindow("Places:Orgainzier");
|
||||
let win = wm.getMostRecentWindow("Places:Organizer");
|
||||
if (win)
|
||||
win.close();
|
||||
|
||||
|
|
|
@ -329,3 +329,15 @@ function flush_main_thread_events()
|
|||
while (tm.mainThread.hasPendingEvents())
|
||||
tm.mainThread.processNextEvent(false);
|
||||
}
|
||||
|
||||
// These tests are known to randomly fail due to bug 507790 when database
|
||||
// flushes are active, so we turn off syncing for them.
|
||||
let randomFailingSyncTests = [
|
||||
"test_browserGlue_smartBookmarks.js",
|
||||
];
|
||||
let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName;
|
||||
if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) {
|
||||
print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component.");
|
||||
let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver);
|
||||
sync.observe(null, "places-debug-stop-sync", null);
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Places.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla.org
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// put cleanup of the bookmarks test here.
|
||||
|
||||
// Run the event loop to be more like the browser, which normally runs the
|
||||
// event loop long before code like this would run.
|
||||
// Not doing so could cause us to close the connection before all tasks have
|
||||
// been completed, and that would crash badly.
|
||||
flush_main_thread_events();
|
||||
|
||||
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
|
||||
// dispatch it after each test run.
|
||||
var os = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(null, "quit-application-granted", null);
|
||||
os.notifyObservers(null, "quit-application", null);
|
||||
|
||||
// Run the event loop, since we enqueue some statement finalization.
|
||||
flush_main_thread_events();
|
||||
|
||||
// try to close the connection so we can remove places.sqlite
|
||||
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService).
|
||||
QueryInterface(Ci.nsPIPlacesDatabase);
|
||||
if (pip.DBConnection.connectionReady) {
|
||||
pip.commitPendingChanges();
|
||||
pip.finalizeInternalStatements();
|
||||
pip.DBConnection.close();
|
||||
do_check_false(pip.DBConnection.connectionReady);
|
||||
}
|
|
@ -132,12 +132,15 @@ function continue_test() {
|
|||
// Check distribution prefs have been created.
|
||||
do_check_eq(ps.getCharPref(PREF_DISTRIBUTION_ID), "516444");
|
||||
|
||||
// Remove the distribution file.
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
do_register_cleanup(function() {
|
||||
// Remove the distribution file, even if the test failed, otherwise all
|
||||
// next tests will import it.
|
||||
let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile);
|
||||
iniFile.append("distribution");
|
||||
iniFile.append("distribution.ini");
|
||||
iniFile.remove(false);
|
||||
do_check_false(iniFile.exists());
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -205,15 +205,16 @@ tests.push({
|
|||
do_check_false(ps.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
|
||||
do_check_false(ps.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
|
||||
|
||||
finish_test();
|
||||
do_test_finished();
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
function finish_test() {
|
||||
// Simulate application closing to remove the idle observer and avoid leaks.
|
||||
os.notifyObservers(null, "quit-application-granted", null);
|
||||
// Clean up database from all bookmarks.
|
||||
remove_all_bookmarks();
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
|
@ -222,16 +223,13 @@ function next_test() {
|
|||
// Clean up database from all bookmarks.
|
||||
remove_all_bookmarks();
|
||||
|
||||
// Simulate application closing to remove the idle observer and avoid leaks.
|
||||
os.notifyObservers(null, "quit-application-granted", null);
|
||||
|
||||
// nsBrowserGlue stops observing topics after first notification,
|
||||
// so we add back the observer to test additional runs.
|
||||
os.addObserver(bg, TOPIC_PLACES_INIT_COMPLETE, false);
|
||||
|
||||
// Execute next test.
|
||||
let test = tests.shift();
|
||||
dump("\nTEST " + (++testIndex) + ": " + test.description);
|
||||
print("\nTEST " + (++testIndex) + ": " + test.description);
|
||||
test.exec();
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ tests.push({
|
|||
do_check_eq(profileBookmarksJSONFile.lastModifiedTime, lastMod);
|
||||
do_check_eq(profileBookmarksJSONFile.fileSize, fileSize);
|
||||
|
||||
finish_test();
|
||||
do_test_finished();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -51,26 +51,34 @@
|
|||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
#ifdef XP_MACOSX
|
||||
<title></title>
|
||||
#else
|
||||
<title>&privatebrowsingpage.title;</title>
|
||||
#endif
|
||||
<link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/>
|
||||
<script type="application/x-javascript;version=1.7"><![CDATA[
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
window.__defineGetter__("mainWindow", function() {
|
||||
delete window.mainWindow;
|
||||
return window.mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
});
|
||||
var pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
|
||||
if (!pb.privateBrowsingEnabled) {
|
||||
document.title = "]]>&privatebrowsingpage.title.normal;<![CDATA[";
|
||||
setFavIcon("chrome://global/skin/icons/question-16.png");
|
||||
} else {
|
||||
#ifndef XP_MACOSX
|
||||
document.title = "]]>&privatebrowsingpage.title;<![CDATA[";
|
||||
#endif
|
||||
setFavIcon("chrome://browser/skin/Privacy-16.png");
|
||||
}
|
||||
|
||||
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
// Focus the location bar
|
||||
mainWindow.focusAndSelectUrlBar();
|
||||
|
||||
function openSanitizeDialog() {
|
||||
let browserGlue = Cc["@mozilla.org/browser/browserglue;1"].
|
||||
|
@ -83,21 +91,17 @@
|
|||
icon.setAttribute("rel", "icon");
|
||||
icon.setAttribute("type", "image/png");
|
||||
icon.setAttribute("href", url);
|
||||
document.getElementsByTagName("head")[0].appendChild(icon);
|
||||
var head = document.getElementsByTagName("head")[0];
|
||||
head.insertBefore(icon, head.firstChild);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
let selector;
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
if (!pb.privateBrowsingEnabled) {
|
||||
document.body.setAttribute("class", "normal");
|
||||
document.title = document.body.getAttribute("normaltitle");
|
||||
setFavIcon("chrome://global/skin/icons/question-16.png");
|
||||
selector = ".showPrivate";
|
||||
}
|
||||
else {
|
||||
setFavIcon("chrome://browser/skin/Privacy-16.png");
|
||||
selector = ".showNormal";
|
||||
}
|
||||
|
||||
|
@ -113,18 +117,12 @@
|
|||
let moreInfoLink = document.getElementById("moreInfoLink");
|
||||
if (moreInfoLink)
|
||||
moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing");
|
||||
|
||||
// Focus the location bar
|
||||
if (mainWindow.gURLBar)
|
||||
mainWindow.gURLBar.focus();
|
||||
}
|
||||
}, false);
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;"
|
||||
class="private"
|
||||
onload="onLoad();"
|
||||
normaltitle="&privatebrowsingpage.title.normal;">
|
||||
class="private">
|
||||
|
||||
<!-- PAGE CONTAINER (for styling purposes only) -->
|
||||
<div id="errorPageContainer">
|
||||
|
|
|
@ -124,6 +124,9 @@ PrivateBrowsingService.prototype = {
|
|||
// List of view source window URIs for restoring later
|
||||
_viewSrcURLs: [],
|
||||
|
||||
// List of nsIXULWindows we are going to be closing during the transition
|
||||
_windowsToClose: [],
|
||||
|
||||
// XPCOM registration
|
||||
classDescription: "PrivateBrowsing Service",
|
||||
contractID: "@mozilla.org/privatebrowsing;1",
|
||||
|
@ -208,12 +211,20 @@ PrivateBrowsingService.prototype = {
|
|||
// just in case the only remaining window after setBrowserState is different.
|
||||
// it probably shouldn't be with the current sessionstore impl, but we shouldn't
|
||||
// rely on behaviour the API doesn't guarantee
|
||||
let browser = this._getBrowserWindow().gBrowser;
|
||||
browserWindow = this._getBrowserWindow();
|
||||
let browser = browserWindow.gBrowser;
|
||||
|
||||
// this ensures a clean slate from which to transition into or out of
|
||||
// private browsing
|
||||
browser.addTab();
|
||||
browser.getBrowserForTab(browser.tabContainer.firstChild).stop();
|
||||
browser.removeTab(browser.tabContainer.firstChild);
|
||||
browserWindow.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow)
|
||||
.docShell.contentViewer.resetCloseWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,6 +309,20 @@ PrivateBrowsingService.prototype = {
|
|||
getMostRecentWindow("navigator:browser");
|
||||
},
|
||||
|
||||
_ensureCanCloseWindows: function PBS__ensureCanCloseWindows() {
|
||||
let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
let windowsEnum = windowMediator.getXULWindowEnumerator("navigator:browser");
|
||||
|
||||
while (windowsEnum.hasMoreElements()) {
|
||||
let win = windowsEnum.getNext().QueryInterface(Ci.nsIXULWindow);
|
||||
if (win.docShell.contentViewer.permitUnload(true))
|
||||
this._windowsToClose.push(win);
|
||||
else
|
||||
throw Cr.NS_ERROR_ABORT;
|
||||
}
|
||||
},
|
||||
|
||||
_closePageInfoWindows: function PBS__closePageInfoWindows() {
|
||||
let pageInfoEnum = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator).
|
||||
|
@ -401,6 +426,8 @@ PrivateBrowsingService.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this._ensureCanCloseWindows();
|
||||
|
||||
this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
|
||||
this._inPrivateBrowsing = val != false;
|
||||
|
||||
|
@ -422,9 +449,16 @@ PrivateBrowsingService.prototype = {
|
|||
this._onAfterPrivateBrowsingModeChange();
|
||||
}
|
||||
} catch (ex) {
|
||||
Cu.reportError("Exception thrown while processing the " +
|
||||
"private browsing mode change request: " + ex.toString());
|
||||
// We aborted the transition to/from private browsing, we must restore the
|
||||
// beforeunload handling on all the windows for which we switched it off.
|
||||
for (let i = 0; i < this._windowsToClose.length; i++)
|
||||
this._windowsToClose[i].docShell.contentViewer.resetCloseWindow();
|
||||
// We don't log an error when the transition is canceled from beforeunload
|
||||
if (ex != Cr.NS_ERROR_ABORT)
|
||||
Cu.reportError("Exception thrown while processing the " +
|
||||
"private browsing mode change request: " + ex.toString());
|
||||
} finally {
|
||||
this._windowsToClose = [];
|
||||
this._alreadyChangingMode = false;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -80,19 +80,11 @@ function test() {
|
|||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
browser.stop();
|
||||
// ensure that the test is run after the titlebar has been updated
|
||||
let timer = null;
|
||||
let _updateTitlebar = gBrowser.updateTitlebar;
|
||||
gBrowser.updateTitlebar = function() {
|
||||
if (timer) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
timer = Cc["@mozilla.org/timer;1"].
|
||||
createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(function () {
|
||||
_updateTitlebar.apply(gBrowser, arguments);
|
||||
gBrowser.updateTitlebar = _updateTitlebar;
|
||||
browser.addEventListener("pageshow", function () {
|
||||
browser.removeEventListener("pageshow", arguments.callee, false);
|
||||
executeSoon(function () {
|
||||
is(document.title, expected_title, "The window title for " + url +
|
||||
" is correct (" + (insidePB ? "inside" : "outside") +
|
||||
" private browsing mode)");
|
||||
|
@ -115,8 +107,8 @@ function test() {
|
|||
setTimeout(funcNext, 0);
|
||||
};
|
||||
}, false);
|
||||
}, 300, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
};
|
||||
});
|
||||
}, false);
|
||||
|
||||
browser.loadURI(url);
|
||||
}
|
||||
|
|
|
@ -564,7 +564,6 @@ function test_cache_cleared()
|
|||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
os.removeObserver(observer, "cacheservice:empty-cache");
|
||||
shutdownPlaces();
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -155,6 +155,4 @@ function do_test()
|
|||
// And check our data
|
||||
for (let i = 0; i < data.length; i++)
|
||||
check_active_download(data[i].source, !data[i].removed);
|
||||
|
||||
shutdownPlaces();
|
||||
}
|
||||
|
|
|
@ -110,15 +110,6 @@ function cleanUp()
|
|||
}
|
||||
cleanUp();
|
||||
|
||||
/**
|
||||
* Finalize Places statements during quit-application in order to prevent leaks
|
||||
*/
|
||||
function shutdownPlaces() {
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(null, "quit-application", null);
|
||||
}
|
||||
|
||||
var PRIVATEBROWSING_CONTRACT_ID;
|
||||
function run_test_on_all_services() {
|
||||
var contractIDs = [
|
||||
|
|
|
@ -269,6 +269,8 @@ SessionStoreService.prototype = {
|
|||
|
||||
// make sure that at least the first window doesn't have anything hidden
|
||||
delete this._initialState.windows[0].hidden;
|
||||
// Since nothing is hidden in the first window, it cannot be a popup
|
||||
delete this._initialState.windows[0].isPopup;
|
||||
}
|
||||
catch (ex) { debug("The session file is invalid: " + ex); }
|
||||
}
|
||||
|
|
|
@ -44,12 +44,14 @@ function test() {
|
|||
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
is(doc.getElementById("storageTestItem").textContent, "PENDING",
|
||||
"sessionStorage value has been set");
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc2 = tab2.linkedBrowser.contentDocument;
|
||||
is(doc2.getElementById("storageTestItem").textContent, "SUCCESS",
|
||||
"sessionStorage value has been duplicated");
|
||||
|
|
|
@ -99,11 +99,13 @@ function test() {
|
|||
"browser/components/sessionstore/test/browser/browser_346337_sample.html";
|
||||
let tab = tabbrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
for (let xpath in fieldList)
|
||||
setFormValue(tab, xpath, fieldList[xpath]);
|
||||
|
||||
let tab2 = tabbrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
for (let xpath in fieldList)
|
||||
ok(compareFormValue(tab2, xpath, fieldList[xpath]),
|
||||
"The value for \"" + xpath + "\" was correctly restored");
|
||||
|
@ -114,6 +116,7 @@ function test() {
|
|||
|
||||
tab = undoCloseTab();
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
for (let xpath in fieldList)
|
||||
if (fieldList[xpath])
|
||||
ok(!compareFormValue(tab, xpath, fieldList[xpath]),
|
||||
|
|
|
@ -45,6 +45,7 @@ function test() {
|
|||
key = "Unique name: " + Math.random();
|
||||
value = "Unique value: " + Date.now();
|
||||
let tab = tabbrowser.addTab();
|
||||
tab.linkedBrowser.stop();
|
||||
|
||||
// test adding
|
||||
ok(test(function() ss.setTabValue(tab, key, value)), "store a tab value");
|
||||
|
@ -74,6 +75,7 @@ function test() {
|
|||
let testURL = "about:";
|
||||
tab = tabbrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// make sure that the next closed tab will increase getClosedTabCount
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
|
||||
|
||||
|
@ -89,6 +91,7 @@ function test() {
|
|||
ok(tab, "undoCloseTab doesn't throw")
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
is(this.currentURI.spec, testURL, "correct tab was reopened");
|
||||
|
||||
// clean up
|
||||
|
|
|
@ -248,6 +248,7 @@ function test() {
|
|||
// The previously closed window should be restored
|
||||
newWin = openDialog(location, "_blank", CHROME_FEATURES);
|
||||
newWin.addEventListener("load", function() {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
|
||||
"Restored window in-session with otherpopup windows around");
|
||||
|
@ -281,6 +282,7 @@ function test() {
|
|||
// The previously closed window should NOT be restored
|
||||
newWin = openDialog(location, "_blank", CHROME_FEATURES);
|
||||
newWin.addEventListener("load", function() {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
is(newWin.gBrowser.browsers.length, 1,
|
||||
"Did not restore in private browing mode");
|
||||
|
@ -293,6 +295,7 @@ function test() {
|
|||
|
||||
newWin = openDialog(location, "_blank", CHROME_FEATURES);
|
||||
newWin.addEventListener("load", function() {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
|
||||
"Restored after leaving private browsing again");
|
||||
|
@ -334,6 +337,7 @@ function test() {
|
|||
// open a new window the previously closed window should be restored to
|
||||
newWin = openDialog(location, "_blank", CHROME_FEATURES);
|
||||
newWin.addEventListener("load", function() {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
executeSoon(function() {
|
||||
is(newWin.gBrowser.browsers.length, TEST_URLS.length + 1,
|
||||
"Restored window and associated tabs in session");
|
||||
|
@ -364,6 +368,7 @@ function test() {
|
|||
// gets a chance.
|
||||
let popup = openDialog(location, "popup", POPUP_FEATURES, TEST_URLS[1]);
|
||||
popup.addEventListener("load", function() {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
is(popup.gBrowser.browsers.length, 1,
|
||||
"Did not restore the popup window (1)");
|
||||
popup.BrowserTryToCloseWindow();
|
||||
|
|
|
@ -57,6 +57,7 @@ function test() {
|
|||
|
||||
ss.setTabState(tab, "{ entries: [] }");
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
ok(history.count == 0, "the tab was restored without any history whatsoever");
|
||||
|
||||
tabbrowser.removeTab(tab);
|
||||
|
|
|
@ -21,6 +21,7 @@ function test() {
|
|||
let tab = tabbrowser.addTab(testURL);
|
||||
ss.setTabValue(tab, key, value);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// get the tab's state
|
||||
let state = ss.getTabState(tab);
|
||||
ok(state, "get the tab's state");
|
||||
|
@ -51,6 +52,7 @@ function test() {
|
|||
// set the tab's state
|
||||
ss.setTabState(tab2, state.toSource());
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// verify the correctness of the restored tab
|
||||
ok(ss.getTabValue(tab2, key2) == value2 && this.currentURI.spec == testURL,
|
||||
"the tab's state was correctly restored");
|
||||
|
@ -64,6 +66,7 @@ function test() {
|
|||
tabbrowser.removeTab(tab2);
|
||||
|
||||
duplicateTab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// verify the correctness of the duplicated tab
|
||||
ok(ss.getTabValue(duplicateTab, key2) == value2 && this.currentURI.spec == testURL,
|
||||
"correctly duplicated the tab's state");
|
||||
|
|
|
@ -63,7 +63,7 @@ function test() {
|
|||
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
executeSoon(function() {
|
||||
newWin.gBrowser.addTab();
|
||||
newWin.gBrowser.addTab().linkedBrowser.stop();
|
||||
executeSoon(function() {
|
||||
// mark the window with some unique data to be restored later on
|
||||
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
|
||||
|
@ -87,6 +87,7 @@ function test() {
|
|||
"The reopened window was removed from Recently Closed Windows");
|
||||
|
||||
newWin2.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
newWin2.gBrowser.addEventListener("SSTabRestored", function(aEvent) {
|
||||
newWin2.gBrowser.removeEventListener("SSTabRestored", arguments.callee, true);
|
||||
|
||||
|
@ -142,12 +143,14 @@ function test() {
|
|||
let url = "http://window" + windowsToOpen.length + ".example.com";
|
||||
let window = openDialog(location, "_blank", settings, url);
|
||||
window.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
window.gBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// the window _should_ have state with a tab of url, but it doesn't
|
||||
// always happend before window.close(). addTab ensure we don't treat
|
||||
// this window as a stateless window
|
||||
window.gBrowser.addTab();
|
||||
window.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
executeSoon(function() {
|
||||
window.close();
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
* Paul O’Shannessy <paul@oshannessy.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
|
||||
|
@ -39,20 +40,20 @@
|
|||
function test() {
|
||||
/** Private Browsing Test for Bug 394759 **/
|
||||
|
||||
// test setup
|
||||
waitForExplicitFinish();
|
||||
|
||||
// private browsing service
|
||||
// Setup.
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
|
||||
// Remove the sessionstore.js file before setting the interval to 0
|
||||
let profilePath = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties).
|
||||
get("ProfD", Ci.nsIFile);
|
||||
|
||||
// sessionstore service
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
// Remove the sessionstore.js file before setting the interval to 0
|
||||
let sessionStoreJS = profilePath.clone();
|
||||
sessionStoreJS.append("sessionstore.js");
|
||||
if (sessionStoreJS.exists())
|
||||
|
@ -79,93 +80,98 @@ function test() {
|
|||
let closedWindowCount = ss.getClosedWindowCount();
|
||||
is(closedWindowCount, 0, "Correctly set window count");
|
||||
|
||||
let testURL_A = "about:config";
|
||||
let testURL_B = "about:mozilla";
|
||||
// Prevent VM timers issues, cache now and increment it manually.
|
||||
const NOW = Date.now();
|
||||
|
||||
let uniqueKey_A = "bug 394759 Non-PB";
|
||||
let uniqueValue_A = "unik" + Date.now();
|
||||
let uniqueKey_B = "bug 394759 PB";
|
||||
let uniqueValue_B = "uniq" + Date.now();
|
||||
|
||||
|
||||
// Open a window
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_A);
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
newWin.gBrowser.addEventListener("load", function(aEvent) {
|
||||
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
info("Window has been loaded");
|
||||
executeSoon(function() {
|
||||
newWin.gBrowser.addTab();
|
||||
executeSoon(function() {
|
||||
// mark the window with some unique data to be restored later on
|
||||
ss.setWindowValue(newWin, uniqueKey_A, uniqueValue_A);
|
||||
|
||||
newWin.close();
|
||||
|
||||
// ensure that we incremented # of close windows
|
||||
is(ss.getClosedWindowCount(), closedWindowCount + 1,
|
||||
"The closed window was added to the list");
|
||||
|
||||
// ensure we added window to undo list
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.toSource().indexOf(uniqueValue_A) > -1,
|
||||
"The closed window data was stored correctly");
|
||||
|
||||
// enter private browsing mode
|
||||
pb.privateBrowsingEnabled = true;
|
||||
ok(pb.privateBrowsingEnabled, "private browsing enabled");
|
||||
|
||||
// ensure that we have 0 undo windows when entering PB
|
||||
is(ss.getClosedWindowCount(), 0,
|
||||
"Recently Closed Windows are removed when entering Private Browsing");
|
||||
is(ss.getClosedWindowData(), "[]",
|
||||
"Recently Closed Windows data is cleared when entering Private Browsing");
|
||||
|
||||
// open another window in PB
|
||||
let pbWin = openDialog(location, "_blank", "chrome,all,dialog=no", testURL_B);
|
||||
pbWin.addEventListener("load", function(aEvent) {
|
||||
pbWin.removeEventListener("load", arguments.callee, false);
|
||||
pbWin.gBrowser.addEventListener("load", function(aEvent) {
|
||||
pbWin.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
const TESTS = [
|
||||
{ url: "about:config",
|
||||
key: "bug 394759 Non-PB",
|
||||
value: "uniq" + (++NOW) },
|
||||
{ url: "about:mozilla",
|
||||
key: "bug 394759 PB",
|
||||
value: "uniq" + (++NOW) },
|
||||
];
|
||||
|
||||
function openWindowAndTest(aTestIndex, aRunNextTestInPBMode) {
|
||||
info("Opening new window");
|
||||
let windowObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic === "domwindowopened") {
|
||||
ww.unregisterNotification(this);
|
||||
info("New window has been opened");
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad(event) {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
info("New window has been loaded");
|
||||
win.gBrowser.addEventListener("load", function(aEvent) {
|
||||
win.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
info("New window browser has been loaded");
|
||||
executeSoon(function() {
|
||||
// Add another tab, though it's not strictly needed
|
||||
pbWin.gBrowser.addTab();
|
||||
// Add a tab.
|
||||
win.gBrowser.addTab();
|
||||
|
||||
executeSoon(function() {
|
||||
// mark the window with some unique data to be restored later on
|
||||
ss.setWindowValue(pbWin, uniqueKey_B, uniqueValue_B);
|
||||
// Mark the window with some unique data to be restored later on.
|
||||
ss.setWindowValue(win, TESTS[aTestIndex].key, TESTS[aTestIndex].value);
|
||||
|
||||
pbWin.close();
|
||||
win.close();
|
||||
|
||||
// ensure we added window to undo list
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.toSource().indexOf(uniqueValue_B) > -1,
|
||||
"The closed window data was stored correctly in PB mode");
|
||||
|
||||
// exit private browsing mode
|
||||
pb.privateBrowsingEnabled = false;
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
|
||||
|
||||
// ensure that we still have the closed windows from before
|
||||
// Ensure that we incremented # of close windows.
|
||||
is(ss.getClosedWindowCount(), closedWindowCount + 1,
|
||||
"The correct number of recently closed windows were restored " +
|
||||
"when exiting PB mode");
|
||||
"The closed window was added to the list");
|
||||
|
||||
// Ensure we added window to undo list.
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.toSource().indexOf(uniqueValue_A) > -1,
|
||||
"The data associated with the recently closed window was " +
|
||||
"restored when exiting PB mode");
|
||||
ok(data.toSource().indexOf(TESTS[aTestIndex].value) > -1,
|
||||
"The closed window data was stored correctly");
|
||||
|
||||
// cleanup
|
||||
gPrefService.clearUserPref("browser.sessionstore.interval");
|
||||
finish();
|
||||
if (aRunNextTestInPBMode) {
|
||||
// Enter private browsing mode.
|
||||
pb.privateBrowsingEnabled = true;
|
||||
ok(pb.privateBrowsingEnabled, "private browsing enabled");
|
||||
|
||||
// Ensure that we have 0 undo windows when entering PB.
|
||||
is(ss.getClosedWindowCount(), 0,
|
||||
"Recently Closed Windows are removed when entering Private Browsing");
|
||||
is(ss.getClosedWindowData(), "[]",
|
||||
"Recently Closed Windows data is cleared when entering Private Browsing");
|
||||
}
|
||||
else {
|
||||
// Exit private browsing mode.
|
||||
pb.privateBrowsingEnabled = false;
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing disabled");
|
||||
|
||||
// Ensure that we still have the closed windows from before.
|
||||
is(ss.getClosedWindowCount(), closedWindowCount + 1,
|
||||
"The correct number of recently closed windows were restored " +
|
||||
"when exiting PB mode");
|
||||
|
||||
let data = JSON.parse(ss.getClosedWindowData())[0];
|
||||
ok(data.toSource().indexOf(TESTS[aTestIndex].value) > -1,
|
||||
"The data associated with the recently closed window was " +
|
||||
"restored when exiting PB mode");
|
||||
}
|
||||
|
||||
if (aTestIndex == TESTS.length - 1) {
|
||||
// Cleanup and finish.
|
||||
gPrefService.clearUserPref("browser.sessionstore.interval");
|
||||
finish();
|
||||
}
|
||||
else {
|
||||
// Run next test.
|
||||
openWindowAndTest(aTestIndex + 1, !aRunNextTestInPBMode);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
ww.registerNotification(windowObserver);
|
||||
// Open a window.
|
||||
openDialog(location, "_blank", "chrome,all,dialog=no", TESTS[aTestIndex].url);
|
||||
}
|
||||
|
||||
openWindowAndTest(0, true);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ function test() {
|
|||
let tab = gBrowser.addTab(testUrl);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
// enable all stylesheets and verify that they're correctly persisted
|
||||
Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) {
|
||||
pendingCount++;
|
||||
|
@ -53,6 +54,7 @@ function test() {
|
|||
|
||||
let newTab = gBrowser.duplicateTab(tab);
|
||||
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets,
|
||||
function(aSS) !aSS.disabled);
|
||||
let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1;
|
||||
|
@ -72,6 +74,7 @@ function test() {
|
|||
tab.linkedBrowser.markupDocumentViewer.authorStyleDisabled = true;
|
||||
let newTab = gBrowser.duplicateTab(tab);
|
||||
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
is(newTab.linkedBrowser.markupDocumentViewer.authorStyleDisabled, true,
|
||||
"disabled all stylesheets");
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ function test() {
|
|||
|
||||
// set a unique value on a new, blank tab
|
||||
var tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.stop();
|
||||
ss.setTabValue(tab, uniqueName, uniqueValue);
|
||||
let valueWasCleaned = false;
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ function test() {
|
|||
"browser/components/sessionstore/test/browser/browser_454908_sample.html";
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
for (let id in fieldValues)
|
||||
doc.getElementById(id).value = fieldValues[id];
|
||||
|
@ -59,6 +60,7 @@ function test() {
|
|||
|
||||
tab = undoCloseTab();
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
for (let id in fieldValues) {
|
||||
let node = doc.getElementById(id);
|
||||
|
|
|
@ -46,6 +46,7 @@ function test() {
|
|||
"browser/components/sessionstore/test/browser/browser_456342_sample.xhtml";
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"]
|
||||
|
|
|
@ -60,7 +60,8 @@ function test() {
|
|||
// wait for all frames to load (and reload!) completely
|
||||
if (frameCount++ < 2)
|
||||
return;
|
||||
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let maxWait = Date.now() + 1000;
|
||||
executeSoon(function() {
|
||||
let iframes = tab2.linkedBrowser.contentWindow.frames;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
<script type="application/javascript">
|
||||
frames[0].addEventListener("DOMContentLoaded", function() {
|
||||
frames[0].removeEventListener("DOMContentLoaded", arguments.callee, false);
|
||||
frames[0].document.designMode = "on";
|
||||
frames[0].document.__defineGetter__("designMode", function() {
|
||||
// inject a cross domain file ...
|
||||
|
|
|
@ -67,6 +67,7 @@ function test() {
|
|||
// open a window and add the above closed tab list
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||
test_state.windows[0]._closedTabs.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
|
|
|
@ -48,6 +48,7 @@ function test() {
|
|||
executeSoon(function() {
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
executeSoon(function() {
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
var event = document.createEvent("MessageEvent");
|
||||
event.initMessageEvent("461743", true, false, "done", location.href, "", window);
|
||||
document.dispatchEvent(event);
|
||||
frames[0].document.removeEventListener("DOMNodeInserted", loadChrome, true);
|
||||
frames[0].document.removeEventListener("DOMNodeInserted", delay, true);
|
||||
frames[0].document.removeEventListener("DOMNodeInserted", loadExploit, true);
|
||||
frames[0].document.removeEventListener("DOMNodeInserted", done, true);
|
||||
}
|
||||
|
||||
frames[0].document.addEventListener("DOMNodeInserted", loadChrome, true);
|
||||
|
|
|
@ -69,7 +69,8 @@ function test() {
|
|||
// wait for all frames to load (and reload!) completely
|
||||
if (frameCount++ < 4)
|
||||
return;
|
||||
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let win = tab2.linkedBrowser.contentWindow;
|
||||
isnot(win.frames[0].document.getElementById("original").value, uniqueValue,
|
||||
"subframes must match URL to get text restored");
|
||||
|
|
|
@ -69,7 +69,8 @@ function test() {
|
|||
// wait for all frames to load completely
|
||||
if (frameCount++ < 5)
|
||||
return;
|
||||
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let doc = tab2.linkedBrowser.contentDocument;
|
||||
let win = tab2.linkedBrowser.contentWindow;
|
||||
isnot(doc.getElementById("out1").value,
|
||||
|
|
|
@ -75,6 +75,7 @@ function test() {
|
|||
// open a window and add the above closed tab list
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||
test_state.windows[0]._closedTabs.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
|
|
|
@ -54,6 +54,7 @@ function test() {
|
|||
frameCount = 0;
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("464620_a", function(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener("464620_a", arguments.callee, true);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
// let form restoration complete and take into account the
|
||||
|
|
|
@ -54,6 +54,7 @@ function test() {
|
|||
frameCount = 0;
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("464620_b", function(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener("464620_b", arguments.callee, true);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
// let form restoration complete and take into account the
|
||||
|
|
|
@ -49,6 +49,7 @@ function test() {
|
|||
// open a window and set a value on it
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
|
||||
|
||||
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
|
||||
|
|
|
@ -45,12 +45,14 @@ function test() {
|
|||
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
doc.getElementById("reverse_thief").value = "/home/user/secret2";
|
||||
doc.getElementById("bystander").value = testPath;
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
doc = tab2.linkedBrowser.contentDocument;
|
||||
is(doc.getElementById("thief").value, "",
|
||||
"file path wasn't set to text field value");
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
<script>
|
||||
window.addEventListener("DOMContentLoaded", function() {
|
||||
window.removeEventListener("DOMContentLoaded", arguments.callee, false);
|
||||
if (!document.location.hash) {
|
||||
document.location.hash = "#ready";
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ function test() {
|
|||
"browser/components/sessionstore/test/browser/browser_476161_sample.html";
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
|
||||
doc.getElementById("modify1").value += Math.random();
|
||||
|
@ -50,6 +51,7 @@ function test() {
|
|||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab2.linkedBrowser.contentDocument;
|
||||
let changed = doc.getElementById("changed").textContent.trim().split();
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ function test() {
|
|||
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
let newState = { windows: [{
|
||||
tabs: [{ entries: [] }],
|
||||
_closedTabs: [{
|
||||
|
|
|
@ -108,8 +108,11 @@ function test() {
|
|||
// cleanup
|
||||
this.window.close();
|
||||
// if we're all done, explicitly finish
|
||||
if (++completedTests == numTests)
|
||||
if (++completedTests == numTests) {
|
||||
this.window.removeEventListener("load", this, false);
|
||||
this.window.removeEventListener("SSTabRestoring", this, false);
|
||||
finish();
|
||||
}
|
||||
},
|
||||
|
||||
handleLoad: function (aEvent) {
|
||||
|
|
|
@ -10,7 +10,7 @@ function test() {
|
|||
|
||||
let browser = tab.linkedBrowser;
|
||||
browser.addEventListener("load", function loadListener(e) {
|
||||
browser.removeEventListener("load", arguments.callee, false);
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
// Scroll the content document
|
||||
browser.contentWindow.scrollTo(1100, 1200);
|
||||
|
@ -21,7 +21,7 @@ function test() {
|
|||
|
||||
let newTab = ss.undoCloseTab(window, 0);
|
||||
newTab.addEventListener("SSTabRestored", function tabRestored(e) {
|
||||
newTab.removeEventListener("SSTabRestored", arguments.callee, false);
|
||||
newTab.removeEventListener("SSTabRestored", arguments.callee, true);
|
||||
|
||||
let newBrowser = newTab.linkedBrowser;
|
||||
|
||||
|
|
|
@ -45,12 +45,14 @@ function test() {
|
|||
"browser/components/sessionstore/test/browser/browser_485482_sample.html";
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
doc.querySelector("input[type=text]").value = uniqueValue;
|
||||
doc.querySelector("input[type=checkbox]").checked = true;
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
doc = tab2.linkedBrowser.contentDocument;
|
||||
is(doc.querySelector("input[type=text]").value, uniqueValue,
|
||||
"generated XPath expression was valid");
|
||||
|
|
|
@ -44,6 +44,7 @@ function test() {
|
|||
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, true);
|
||||
ss.setTabValue(tab, "bug485563", uniqueValue);
|
||||
let tabState = eval("(" + ss.getTabState(tab) + ")");
|
||||
is(tabState.extData["bug485563"], uniqueValue,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче