This commit is contained in:
Richard Newman 2012-03-28 20:50:09 -07:00
Родитель fdc865b2f2 49c46154d2
Коммит 98eda6c179
926 изменённых файлов: 21010 добавлений и 11305 удалений

Просмотреть файл

@ -99,7 +99,9 @@ endif
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(topsrcdir)/other-licenses/atk-1.0 \
$(NULL)

Просмотреть файл

@ -42,12 +42,14 @@
#include "nsAccessibleWrap.h"
#include "nsAccUtils.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "nsMai.h"
#include "nsArrayUtils.h"
extern "C" {
using namespace mozilla::a11y;
extern "C" {
static AtkObject*
refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
{
@ -208,23 +210,17 @@ getRowExtentAtCB(AtkTable *aTable,
}
static AtkObject*
getCaptionCB(AtkTable *aTable)
getCaptionCB(AtkTable* aTable)
{
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return nsnull;
nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return nsnull;
nsCOMPtr<nsIAccessibleTable> accTable;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
getter_AddRefs(accTable));
NS_ENSURE_TRUE(accTable, nsnull);
TableAccessible* table = accWrap->AsTable();
NS_ENSURE_TRUE(table, nsnull);
nsCOMPtr<nsIAccessible> caption;
nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
if (NS_FAILED(rv) || !caption)
return nsnull;
return nsAccessibleWrap::GetAtkObject(caption);
nsAccessible* caption = table->Caption();
return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull;
}
static const gchar*

Просмотреть файл

@ -44,9 +44,6 @@
#include "nsApplicationAccessibleWrap.h"
#include "nsDocAccessible.h"
#include "nsIAccessibleText.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
#endif
#include "nsAccEvent.h"
#include "States.h"

Просмотреть файл

@ -104,8 +104,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/style \

Просмотреть файл

@ -58,7 +58,7 @@ using namespace mozilla::a11y;
nsARIAGridAccessible::
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsAccessibleWrap(aContent, aDoc)
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -70,21 +70,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible,
nsIAccessibleTable)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleTable
//nsAccessNode
NS_IMETHODIMP
nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption)
void
nsARIAGridAccessible::Shutdown()
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
// XXX: should be pointed by aria-labelledby on grid?
return NS_ERROR_NOT_IMPLEMENTED;
mTable = nsnull;
nsAccessibleWrap::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleTable
NS_IMETHODIMP
nsARIAGridAccessible::GetSummary(nsAString &aSummary)
{
@ -710,15 +707,6 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
return NS_OK;
}
NS_IMETHODIMP
nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// Protected

Просмотреть файл

@ -42,12 +42,16 @@
#include "nsIAccessibleTable.h"
#include "nsHyperTextAccessibleWrap.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
/**
* Accessible for ARIA grid and treegrid.
*/
class nsARIAGridAccessible : public nsAccessibleWrap,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
@ -56,7 +60,13 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable
NS_DECL_NSIACCESSIBLETABLE
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
// nsAccessNode
virtual void Shutdown();
protected:
/**

Просмотреть файл

@ -172,6 +172,15 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
kNoReqStates,
eReadonlyUntilEditable
},
{
"form",
roles::FORM,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates
},
{
"grid",
roles::TABLE,

Просмотреть файл

@ -47,9 +47,7 @@
#include "nsARIAMap.h"
#include "nsDocAccessible.h"
#include "nsHyperTextAccessible.h"
#include "nsHTMLTableAccessible.h"
#include "nsTextAccessible.h"
#include "nsXULTreeGridAccessible.h"
#include "nsIDOMXULContainerElement.h"
#include "nsIDOMXULSelectCntrlEl.h"

Просмотреть файл

@ -66,6 +66,11 @@ class nsHTMLImageMapAccessible;
class nsHTMLLIAccessible;
struct nsRoleMapEntry;
class Relation;
namespace mozilla {
namespace a11y {
class TableAccessible;
}
}
class nsTextAccessible;
struct nsRect;
@ -471,6 +476,8 @@ public:
inline bool IsRoot() const { return mFlags & eRootAccessible; }
nsRootAccessible* AsRoot();
virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
nsTextAccessible* AsTextLeaf();

Просмотреть файл

@ -41,15 +41,13 @@
#include "nsCaretAccessible.h"
#include "nsDocAccessibleWrap.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
#endif
#include "nsHashtable.h"
#include "nsCaretAccessible.h"
#include "nsIDocument.h"
#include "nsIDOMEventListener.h"
class nsXULTreeAccessible;
class Relation;
#define NS_ROOTACCESSIBLE_IMPL_CID \

Просмотреть файл

@ -0,0 +1,170 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef TABLE_ACCESSIBLE_H
#define TABLE_ACCESSIBLE_H
#include "nsString.h"
#include "nsTArray.h"
#include "prtypes.h"
class nsAccessible;
namespace mozilla {
namespace a11y {
/**
* Accessible table interface.
*/
class TableAccessible
{
public:
/**
* Return the caption accessible if any for this table.
*/
virtual nsAccessible* Caption() { return nsnull; }
/**
* Get the summary for this table.
*/
virtual void Summary(nsString& aSummary) { aSummary.Truncate(); }
/**
* Return the number of columns in the table.
*/
virtual PRUint32 ColCount() { return 0; }
/**
* Return the number of rows in the table.
*/
virtual PRUint32 RowCount() { return 0; }
/**
* Return the accessible for the cell at the given row and column indices.
*/
virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; }
/**
* Return the index of the cell at the given row and column.
*/
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
/**
* Return the column index of the cell with the given index.
*/
virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; }
/**
* Return the row index of the cell with the given index.
*/
virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; }
/**
* Get the row and column indices for the cell at the given index.
*/
virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx,
PRInt32* aColIdx) {}
/**
* Return the number of columns occupied by the cell at the given row and
* column indices.
*/
virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
/**
* Return the number of rows occupied by the cell at the given row and column
* indices.
*/
virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
/**
* Get the description of the given column.
*/
virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription)
{ aDescription.Truncate(); }
/**
* Get the description for the given row.
*/
virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription)
{ aDescription.Truncate(); }
/**
* Return true if the given column is selected.
*/
virtual bool IsColSelected(PRUint32 aColIdx) { return false; }
/**
* Return true if the given row is selected.
*/
virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; }
/**
* Return true if the given cell is selected.
*/
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; }
/**
* Return the number of selected cells.
*/
virtual PRUint32 SelectedCellCount() { return 0; }
/**
* Return the number of selected columns.
*/
virtual PRUint32 SelectedColCount() { return 0; }
/**
* Return the number of selected rows.
*/
virtual PRUint32 SelectedRowCount() { return 0; }
/**
* Get the set of selected cells.
*/
virtual void SelectedCells(nsTArray<nsAccessible*>* aCells) {}
/**
* Get the set of selected column indices.
*/
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols) {}
/**
* Get the set of selected row indices.
*/
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows) {}
/**
* Select the given column unselecting any other selected columns.
*/
virtual void SelectCol(PRUint32 aColIdx) {}
/**
* Select the given row unselecting all other previously selected rows.
*/
virtual void SelectRow(PRUint32 aRowIdx) {}
/**
* Unselect the given column leaving other selected columns selected.
*/
virtual void UnselectCol(PRUint32 aColIdx) {}
/**
* Unselect the given row leaving other selected rows selected.
*/
virtual void UnselectRow(PRUint32 aRowIdx) {}
/**
* Return true if the table is probably for layout.
*/
virtual bool IsProbablyLayoutTable() { return false; }
};
} // namespace a11y
} // namespace mozilla
#endif

Просмотреть файл

@ -73,6 +73,8 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)

Просмотреть файл

@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole()
nsHTMLTableAccessible::
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsAccessibleWrap(aContent, aDoc)
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -446,6 +446,16 @@ nsHTMLTableAccessible::
NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
nsHTMLTableAccessible, nsIAccessibleTable)
////////////////////////////////////////////////////////////////////////////////
//nsAccessNode
void
nsHTMLTableAccessible::Shutdown()
{
mTable = nsnull;
nsAccessibleWrap::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLTableAccessible: nsAccessible implementation
@ -511,9 +521,7 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
NS_ENSURE_SUCCESS(rv, rv);
bool isProbablyForLayout;
IsProbablyForLayout(&isProbablyForLayout);
if (isProbablyForLayout) {
if (IsProbablyLayoutTable()) {
nsAutoString oldValueUnused;
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
NS_LITERAL_STRING("true"), oldValueUnused);
@ -538,13 +546,11 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType)
////////////////////////////////////////////////////////////////////////////////
// nsHTMLTableAccessible: nsIAccessibleTable implementation
NS_IMETHODIMP
nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
nsAccessible*
nsHTMLTableAccessible::Caption()
{
NS_ENSURE_ARG_POINTER(aCaption);
NS_IF_ADDREF(*aCaption = Caption());
return NS_OK;
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
return child && child->Role() == roles::CAPTION ? child : nsnull;
}
NS_IMETHODIMP
@ -1307,8 +1313,7 @@ nsHTMLTableAccessible::Description(nsString& aDescription)
#ifdef SHOW_LAYOUT_HEURISTIC
if (aDescription.IsEmpty()) {
bool isProbablyForLayout;
IsProbablyForLayout(&isProbablyForLayout);
bool isProbablyForLayout = IsProbablyLayoutTable();
aDescription = mLayoutHeuristic;
}
#ifdef DEBUG_A11Y
@ -1357,8 +1362,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
return !!foundItem;
}
NS_IMETHODIMP
nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
bool
nsHTMLTableAccessible::IsProbablyLayoutTable()
{
// Implement a heuristic to determine if table is most likely used for layout
// XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
@ -1370,18 +1375,16 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
// Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
#ifdef SHOW_LAYOUT_HEURISTIC
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
{ *aIsProbablyForLayout = isLayout; \
mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
{ \
mLayoutHeuristic = isLayout ? \
NS_LITERAL_STRING("layout table: " heuristic) : \
NS_LITERAL_STRING("data table: " heuristic); \
return isLayout; \
}
#else
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; }
#endif
*aIsProbablyForLayout = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsDocAccessible* docAccessible = Document();
if (docAccessible) {
PRUint64 docState = docAccessible->State();

Просмотреть файл

@ -41,6 +41,8 @@
#include "nsHyperTextAccessibleWrap.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
class nsITableLayout;
class nsITableCellLayout;
@ -121,16 +123,28 @@ public:
}
class nsHTMLTableAccessible : public nsAccessibleWrap,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
// nsIAccessible Table
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// TableAccessible
virtual nsAccessible* Caption();
virtual bool IsProbablyLayoutTable();
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual void Description(nsString& aDescription);
virtual nsresult GetNameInternal(nsAString& aName);
virtual mozilla::a11y::role NativeRole();
@ -138,13 +152,6 @@ public:
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
virtual Relation RelationByType(PRUint32 aRelationType);
// TableAccessible
inline nsAccessible* Caption() const
{
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull;
}
// nsHTMLTableAccessible
/**

Просмотреть файл

@ -132,7 +132,7 @@ nsHyperTextAccessible::NativeRole()
return roles::FORM;
if (tag == nsGkAtoms::blockquote || tag == nsGkAtoms::div ||
tag == nsGkAtoms::nav)
tag == nsGkAtoms::section || tag == nsGkAtoms::nav)
return roles::SECTION;
if (tag == nsGkAtoms::h1 || tag == nsGkAtoms::h2 ||
@ -780,7 +780,6 @@ nsHyperTextAccessible::GetRelativeOffset(nsIPresShell *aPresShell,
}
// Ask layout for the new node and offset, after moving the appropriate amount
nsPeekOffsetStruct pos;
nsresult rv;
PRInt32 contentOffset = aFromOffset;
@ -794,9 +793,9 @@ nsHyperTextAccessible::GetRelativeOffset(nsIPresShell *aPresShell,
}
}
pos.SetData(aAmount, aDirection, contentOffset,
0, kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi,
wordMovementType);
nsPeekOffsetStruct pos(aAmount, aDirection, contentOffset,
0, kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi,
wordMovementType);
rv = aFromFrame->PeekOffset(&pos);
if (NS_FAILED(rv)) {
if (aDirection == eDirPrevious) {
@ -1240,6 +1239,9 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
if (mContent->Tag() == nsGkAtoms::nav)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("navigation"));
else if (mContent->Tag() == nsGkAtoms::section)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("region"));
else if (mContent->Tag() == nsGkAtoms::footer)
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
NS_LITERAL_STRING("contentinfo"));

Просмотреть файл

@ -114,7 +114,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../content/base/src \
-I$(srcdir)/../../../content/events/src \

Просмотреть файл

@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsAccEvent.cpp \
nsAccessibleRelation.cpp \
xpcAccessibleTable.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
@ -59,4 +60,5 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
$(NULL)

Просмотреть файл

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "xpcAccessibleTable.h"
#include "nsAccessible.h"
#include "TableAccessible.h"
nsresult
xpcAccessibleTable::GetCaption(nsIAccessible** aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
if (!mTable)
return NS_ERROR_FAILURE;
NS_IF_ADDREF(*aCaption = mTable->Caption());
return NS_OK;
}
nsresult
xpcAccessibleTable::IsProbablyForLayout(bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
if (!mTable)
return NS_ERROR_FAILURE;
*aResult = mTable->IsProbablyLayoutTable();
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
#include "nscore.h"
class nsIAccessible;
namespace mozilla {
namespace a11y {
class TableAccessible;
}
}
class xpcAccessibleTable
{
public:
xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
nsresult GetCaption(nsIAccessible** aCaption);
nsresult IsProbablyForLayout(bool* aIsForLayout);
protected:
mozilla::a11y::TableAccessible* mTable;
};
#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
{ return xpcAccessibleTable::GetCaption(aCaption); } \
NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \
NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \
NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \
NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \
NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \
NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \
NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \
NS_IMETHOD IsProbablyForLayout(bool* aResult) \
{ return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_

Просмотреть файл

@ -72,7 +72,9 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)

Просмотреть файл

@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
nsXULListboxAccessible::
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
XULSelectControlAccessible(aContent, aDoc)
XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
{
nsIContent* parentContent = mContent->GetParent();
if (parentContent) {
@ -164,6 +164,16 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
return NS_ERROR_NO_INTERFACE;
}
////////////////////////////////////////////////////////////////////////////////
//nsAccessNode
void
nsXULListboxAccessible::Shutdown()
{
mTable = nsnull;
XULSelectControlAccessible::Shutdown();
}
bool
nsXULListboxAccessible::IsMulticolumn()
{
@ -229,15 +239,6 @@ nsXULListboxAccessible::NativeRole()
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible. nsIAccessibleTable
NS_IMETHODIMP
nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSummary(nsAString &aSummary)
{
@ -820,15 +821,6 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible: Widgets

Просмотреть файл

@ -40,11 +40,12 @@
#ifndef __nsXULListboxAccessible_h__
#define __nsXULListboxAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsCOMPtr.h"
#include "nsXULMenuAccessible.h"
#include "nsBaseWidgetAccessible.h"
#include "nsIAccessibleTable.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
#include "XULSelectControlAccessible.h"
class nsIWeakReference;
@ -90,19 +91,27 @@ public:
* A class the represents the XUL Listbox widget.
*/
class nsXULListboxAccessible : public XULSelectControlAccessible,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
virtual ~nsXULListboxAccessible() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
// nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsIAccessible
NS_IMETHOD GetValue(nsAString& aValue);
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual mozilla::a11y::role NativeRole();
virtual PRUint64 NativeState();

Просмотреть файл

@ -58,7 +58,7 @@ using namespace mozilla::a11y;
nsXULTreeGridAccessible::
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
nsXULTreeAccessible(aContent, aDoc)
nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this)
{
}
@ -72,15 +72,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridAccessible: nsIAccessibleTable implementation
NS_IMETHODIMP
nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
{
@ -570,13 +561,14 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = false;
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridAccessible: nsAccessNode implementation
return NS_OK;
void
nsXULTreeGridAccessible::Shutdown()
{
mTable = nsnull;
nsXULTreeAccessible::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -39,15 +39,17 @@
#ifndef __nsXULTreeGridAccessible_h__
#define __nsXULTreeGridAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsXULTreeAccessible.h"
#include "TableAccessible.h"
#include "xpcAccessibleTable.h"
/**
* Represents accessible for XUL tree in the case when it has multiple columns.
*/
class nsXULTreeGridAccessible : public nsXULTreeAccessible,
public nsIAccessibleTable
public xpcAccessibleTable,
public nsIAccessibleTable,
public mozilla::a11y::TableAccessible
{
public:
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
@ -56,9 +58,13 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable
NS_DECL_NSIACCESSIBLETABLE
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// nsAccessNode
virtual void Shutdown();
// nsAccessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual mozilla::a11y::role NativeRole();
protected:

Просмотреть файл

@ -24,14 +24,18 @@
testRole("footer", ROLE_FOOTER);
testRole("article", ROLE_DOCUMENT);
testRole("aside", ROLE_NOTE);
testRole("section", ROLE_SECTION); // XXX bug 739612: not a landmark
testRole("main", ROLE_DOCUMENT);
testRole("form", ROLE_FORM);
// Some AT may look for this
testAttrs("nav", {"xml-roles" : "navigation"}, true);
testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
testAttrs("aside", {"xml-roles" : "complementary"}, true);
testAttrs("main", {"xml-roles" : "main"}, true); // ARIA override
testAttrs("section", {"xml-roles" : "region"}, true);
testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
testAttrs("form", {"xml-roles" : "form"}, true);
// And some AT may look for this
testAttrs("nav", {"tag" : "nav"}, true);
@ -39,7 +43,9 @@
testAttrs("footer", {"tag" : "footer"}, true);
testAttrs("article", {"tag" : "article"}, true);
testAttrs("aside", {"tag" : "aside"}, true);
testAttrs("main", {"tag" : "article"}, true); // no override expected
testAttrs("section", {"tag" : "section"}, true);
testAttrs("main", {"tag" : "article"}, true);
testAttrs("form", {"tag" : "article"}, true);
SimpleTest.finish();
}
@ -51,19 +57,29 @@
<body>
<a target="_blank"
title="Provide mappings for html5 <nav> <header> <footer> <article>"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
Mozilla Bug 593368
title="Provide mappings for html5 <nav> <header> <footer> <article>"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
Bug 593368
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
title="Map <article> like we do aria role article">
Mozilla Bug 613502
href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
title="Map <article> like we do aria role article">
Bug 613502
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
title="Change implementation of HTML5 landmark elements to conform">
Mozilla Bug 610650
href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
title="Change implementation of HTML5 landmark elements to conform">
Bug 610650
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
title="Map section to pane (like role=region)">
Mozilla Bug 614310
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
title="Map ARIA role FORM">
Bug 734982
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -74,9 +90,11 @@
<header id="header">a header</header>
<footer id="footer">a footer</footer>
<aside id="aside">by the way I am an aside</aside>
<section id="section">a section</section>
<article id="article">an article</article>
<article id="main" role="main">a main area</article>
<article id="form" role="form">a form area</article>
</body>
</html>

Просмотреть файл

@ -53,6 +53,7 @@ const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;

Просмотреть файл

@ -35,6 +35,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
// strong landmark
testRole("application", ROLE_APPLICATION);
testRole("form", ROLE_FORM);
// weak landmarks
var weak_landmarks = ["banner", "complementary", "contentinfo",
@ -93,6 +94,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 520188</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 529289</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 607219</a>
<a target="_blank"
title="Map ARIA role FORM"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645">
Bug 735645
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -108,6 +113,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
<!-- landmarks -->
<div role="application" id="application">application</div>
<div role="form" id="form">form</div>
<!-- weak landmarks -->
<div role="banner" id="banner">banner</div>
<div role="complementary" id="complementary">complementary</div>
<div role="contentinfo" id="contentinfo">contentinfo</div>

Просмотреть файл

@ -57,6 +57,7 @@ _TEST_FILES =\
test_imagemap.html \
test_list_editabledoc.html \
test_list.html \
test_listbox.xul \
test_menu.xul \
test_menubutton.xul \
test_recreation.html \

Просмотреть файл

@ -0,0 +1,180 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL listbox hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function insertListitem(aListboxID)
{
this.listboxNode = getNode(aListboxID);
this.listitemNode = document.createElement("listitem");
this.listitemNode.setAttribute("label", "item1");
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.listitemNode),
new invokerChecker(EVENT_REORDER, this.listboxNode)
];
this.invoke = function insertListitem_invoke()
{
this.listboxNode.insertBefore(this.listitemNode,
this.listboxNode.firstChild);
}
this.finalCheck = function insertListitem_finalCheck()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item1"
},
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree(this.listboxNode, tree);
}
this.getID = function insertListitem_getID()
{
return "insert listitem ";
}
}
function removeListitem(aListboxID)
{
this.listboxNode = getNode(aListboxID);
this.listitemNode = null;
this.listitem;
function getListitem(aThisObj)
{
return aThisObj.listitem;
}
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getListitem, this),
new invokerChecker(EVENT_REORDER, this.listboxNode)
];
this.invoke = function removeListitem_invoke()
{
this.listitemNode = this.listboxNode.firstChild;
this.listitem = getAccessible(this.listitemNode);
this.listboxNode.removeChild(this.listitemNode);
}
this.finalCheck = function removeListitem_finalCheck()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree(this.listboxNode, tree);
}
this.getID = function removeListitem_getID()
{
return "remove listitem ";
}
}
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
var tree =
{ LISTBOX: [
{
role: ROLE_RICH_OPTION,
name: "item2"
},
{
role: ROLE_RICH_OPTION,
name: "item3"
},
{
role: ROLE_RICH_OPTION,
name: "item4"
}
] };
testAccessibleTree("listbox", tree);
gQueue = new eventQueue();
gQueue.push(new insertListitem("listbox"));
gQueue.push(new removeListitem("listbox"));
gQueue.invoke(); // Will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=656225"
title="XUL listbox accessible tree doesn't get updated">
Mozilla Bug 656225
</a>
<br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<listbox id="listbox" rows="2">
<listitem label="item2"/>
<listitem label="item3"/>
<listitem label="item4"/>
</listbox>
</vbox>
</hbox>
</window>

Просмотреть файл

@ -438,6 +438,9 @@ pref("dom.sms.whitelist", "file://,http://homescreen.gaiamobile.org,http://sms.g
pref("dom.mozContacts.enabled", true);
pref("dom.mozContacts.whitelist", "http://dialer.gaiamobile.org,http://sms.gaiamobile.org");
// WebSettings
pref("dom.mozSettings.enabled", true);
// Ignore X-Frame-Options headers.
pref("b2g.ignoreXFrameOptions", true);

Просмотреть файл

@ -46,6 +46,7 @@ XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function() {
function addPermissions(urls) {
let permissions = [
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app',
'websettings-read', 'websettings-readwrite',
'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification',
'geolocation'
];

Просмотреть файл

@ -69,3 +69,4 @@ fi
MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
MOZ_EXTENSION_MANAGER=1
ENABLE_MARIONETTE=1

Просмотреть файл

@ -169,6 +169,7 @@
@BINPATH@/components/dom_json.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_settings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@ -401,6 +402,8 @@
@BINPATH@/components/contentAreaDropListener.js
@BINPATH@/components/messageWakeupService.js
@BINPATH@/components/messageWakeupService.manifest
@BINPATH@/components/SettingsManager.js
@BINPATH@/components/SettingsManager.manifest
@BINPATH@/components/nsFilePicker.js
@BINPATH@/components/nsFilePicker.manifest
#ifdef MOZ_B2G_RIL

Просмотреть файл

@ -56,13 +56,14 @@ DIRS = \
app \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
ifdef MAKENSISU
DIRS += installer/windows
endif
include $(topsrcdir)/config/rules.mk
ifeq ($(OS_ARCH),WINNT)
ifdef MAKENSISU
# For Windows build the uninstaller during the application build since the
# uninstaller is included with the application for mar file generation.
libs::

Просмотреть файл

@ -205,7 +205,7 @@ int main(int argc, char* argv[])
}
char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
return 255;
strcpy(++lastSlash, XPCOM_DLL);

Просмотреть файл

@ -4084,7 +4084,7 @@ var FullScreen = {
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
if (this.useLionFullScreen) {
if (!this.useLionFullScreen) {
window.removeEventListener("deactivate", this);
}
}
@ -4413,7 +4413,6 @@ var FullScreen = {
// and in tabs-on-bottom mode, move them back to the navigation toolbar.
// When there is a chance the tab bar may be collapsed, put window
// controls on nav bar.
var fullscreenflex = document.getElementById("fullscreenflex");
var fullscreenctls = document.getElementById("window-controls");
var navbar = document.getElementById("nav-bar");
var ctlsOnTabbar = window.toolbar.visible &&
@ -4421,14 +4420,12 @@ var FullScreen = {
(TabsOnTop.enabled &&
!gPrefService.getBoolPref("browser.tabs.autoHide")));
if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) {
fullscreenctls.removeAttribute("flex");
document.getElementById("TabsToolbar").appendChild(fullscreenctls);
// we don't need this space in tabs-on-top mode, so prevent it from
// being shown
fullscreenflex.removeAttribute("fullscreencontrol");
}
else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) {
fullscreenctls.setAttribute("flex", "1");
navbar.appendChild(fullscreenctls);
fullscreenflex.setAttribute("fullscreencontrol", "true");
}
var controls = document.getElementsByAttribute("fullscreencontrol", "true");
@ -8666,6 +8663,31 @@ let gPrivateBrowsingUI = {
get privateBrowsingEnabled() {
return this._privateBrowsingService.privateBrowsingEnabled;
},
/**
* These accessors are used to support per-window Private Browsing mode.
* For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
* and the setter should only be used in tests.
*/
get privateWindow() {
return window.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow)
.docShell.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing;
},
set privateWindow(val) {
return window.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow)
.docShell.QueryInterface(Ci.nsILoadContext)
.usePrivateBrowsing = val;
}
};

Просмотреть файл

@ -475,7 +475,7 @@
toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
fullscreentoolbar="true" mode="icons" customizable="true"
iconsize="large"
defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,home-button,bookmarks-menu-button-container,fullscreenflex,window-controls"
defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,home-button,bookmarks-menu-button-container,window-controls"
context="toolbar-context-menu">
<toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
@ -697,8 +697,7 @@
</toolbarbutton>
</toolbaritem>
<hbox id="fullscreenflex" flex="1" hidden="true" fullscreencontrol="true"/>
<hbox id="window-controls" hidden="true" fullscreencontrol="true">
<hbox id="window-controls" hidden="true" fullscreencontrol="true" pack="end">
<toolbarbutton id="minimize-button"
tooltiptext="&fullScreenMinimize.tooltip;"
oncommand="window.minimize();"/>

Просмотреть файл

@ -44,9 +44,8 @@ let gDrop = {
* Handles the 'drop' event.
* @param aCell The drop target cell.
* @param aEvent The 'dragexit' event.
* @param aCallback The callback to call when the drop is finished.
*/
drop: function Drop_drop(aCell, aEvent, aCallback) {
drop: function Drop_drop(aCell, aEvent) {
// The cell that is the drop target could contain a pinned site. We need
// to find out where that site has gone and re-pin it there.
if (aCell.containsPinnedSite())
@ -58,7 +57,7 @@ let gDrop = {
this._cancelDelayedArrange();
// Update the grid and move all sites to their new places.
gUpdater.updateGrid(aCallback);
gUpdater.updateGrid();
},
/**

Просмотреть файл

@ -61,13 +61,12 @@ Site.prototype = {
/**
* Unpins the site and calls the given callback when done.
* @param aCallback The callback to be called when finished.
*/
unpin: function Site_unpin(aCallback) {
unpin: function Site_unpin() {
if (this.isPinned()) {
this._updateAttributes(false);
gPinnedLinks.unpin(this._link);
gUpdater.updateGrid(aCallback);
gUpdater.updateGrid();
}
},
@ -82,15 +81,14 @@ Site.prototype = {
/**
* Blocks the site (removes it from the grid) and calls the given callback
* when done.
* @param aCallback The function to be called when finished.
*/
block: function Site_block(aCallback) {
block: function Site_block() {
if (gBlockedLinks.isBlocked(this._link)) {
if (aCallback)
aCallback();
} else {
gBlockedLinks.block(this._link);
gUpdater.updateGrid(aCallback);
gUpdater.updateGrid();
}
},

Просмотреть файл

@ -15,13 +15,13 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8");
yield blockCell(cells[4]);
yield blockCell(4);
checkGrid("0,1,2,3,5,6,7,8,9");
yield blockCell(cells[4]);
yield blockCell(4);
checkGrid("0,1,2,3,6,7,8,9,");
yield blockCell(cells[4]);
yield blockCell(4);
checkGrid("0,1,2,3,7,8,9,,");
// we removed a pinned site
@ -32,7 +32,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1p,2,3,4,5,6,7,8");
yield blockCell(cells[1]);
yield blockCell(1);
checkGrid("0,2,3,4,5,6,7,8,");
// we remove the last site on the grid (which is pinned) and expect the gap
@ -44,7 +44,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8p");
yield blockCell(cells[8]);
yield blockCell(8);
checkGrid("0,1,2,3,4,5,6,7,9");
// we remove the first site on the grid with the last one pinned. all cells
@ -56,6 +56,6 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8p");
yield blockCell(cells[0]);
yield blockCell(0);
checkGrid("1,2,3,4,5,6,7,9,8p");
}

Просмотреть файл

@ -20,21 +20,12 @@ function runTests() {
fillHistory();
yield addNewTabPageTab();
is(cells[0].site.url, URL, "first site is our fake site");
is(getCell(0).site.url, URL, "first site is our fake site");
let page = {
update: function () {
executeSoon(TestRunner.next);
},
observe: function () {}
};
NewTabUtils.allPages.register(page);
whenPagesUpdated();
yield clearHistory();
NewTabUtils.allPages.unregister(page);
ok(!cells[0].site, "the fake site is gone");
ok(!getCell(0).site, "the fake site is gone");
}
function fillHistory() {

Просмотреть файл

@ -14,5 +14,5 @@ function runTests() {
ok(NewTabUtils.allPages.enabled, true, "page is enabled");
NewTabUtils.allPages.enabled = false;
ok(cw.gGrid.node.hasAttribute("page-disabled"), "page is disabled");
ok(getGrid().node.hasAttribute("page-disabled"), "page is disabled");
}

Просмотреть файл

@ -8,41 +8,23 @@ function runTests() {
yield addNewTabPageTab();
checkGridLocked(false, "grid is unlocked");
let cell = cells[0].node;
let site = cells[0].site.node;
let cell = getCell(0).node;
let site = getCell(0).site.node;
let link = site.querySelector(".newtab-link");
sendDragEvent(link, "dragstart");
sendDragEvent("dragstart", link);
checkGridLocked(true, "grid is now locked");
sendDragEvent(link, "dragend");
sendDragEvent("dragend", link);
checkGridLocked(false, "grid isn't locked anymore");
sendDragEvent(cell, "dragstart");
sendDragEvent("dragstart", cell);
checkGridLocked(false, "grid isn't locked - dragstart was ignored");
sendDragEvent(site, "dragstart");
sendDragEvent("dragstart", site);
checkGridLocked(false, "grid isn't locked - dragstart was ignored");
}
function checkGridLocked(aLocked, aMessage) {
is(cw.gGrid.node.hasAttribute("locked"), aLocked, aMessage);
}
function sendDragEvent(aNode, aType) {
let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor);
let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
let dataTransfer = {
mozUserCancelled: false,
setData: function () null,
setDragImage: function () null,
getData: function () "about:blank"
};
let event = cw.document.createEvent("DragEvents");
event.initDragEvent(aType, true, true, cw, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
windowUtils.dispatchDOMEventViaPresShell(aNode, event, true);
is(getGrid().node.hasAttribute("locked"), aLocked, aMessage);
}

Просмотреть файл

@ -8,45 +8,16 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8");
let cell = cells[0].node;
let cell = getCell(0).node;
sendDropEvent(cell, "about:blank#99\nblank");
sendDragEvent("drop", cell, "about:blank#99\nblank");
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
"first cell is pinned and contains the dropped site");
yield whenPagesUpdated();
checkGrid("99p,0,1,2,3,4,5,6,7");
sendDropEvent(cell, "");
sendDragEvent("drop", cell, "");
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
"first cell is still pinned with the site we dropped before");
}
function sendDropEvent(aNode, aData) {
let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor);
let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
let dataTransfer = {
mozUserCancelled: false,
setData: function () null,
setDragImage: function () null,
getData: function () aData,
types: {
contains: function (aType) aType == "text/x-moz-url"
},
mozGetDataAt: function (aType, aIndex) {
if (aIndex || aType != "text/x-moz-url")
return null;
return aData;
},
};
let event = cw.document.createEvent("DragEvents");
event.initDragEvent("drop", true, true, cw, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
windowUtils.dispatchDOMEventViaPresShell(aNode, event, true);
}

Просмотреть файл

@ -9,12 +9,13 @@ function runTests() {
checkGrid("0,1,2,3,4,5,6,7,8");
let receivedError = false;
let block = cw.document.querySelector(".newtab-control-block");
let block = getContentDocument().querySelector(".newtab-control-block");
function onError() {
receivedError = true;
}
let cw = getContentWindow();
cw.addEventListener("error", onError);
for (let i = 0; i < 3; i++)

Просмотреть файл

@ -8,15 +8,15 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8");
yield simulateDrop(cells[1]);
yield simulateDrop(1);
checkGrid("0,99p,1,2,3,4,5,6,7");
yield blockCell(cells[1]);
yield blockCell(1);
checkGrid("0,1,2,3,4,5,6,7,8");
yield simulateDrop(cells[1]);
yield simulateDrop(1);
checkGrid("0,99p,1,2,3,4,5,6,7");
yield blockCell(cells[1]);
yield blockCell(1);
checkGrid("0,1,2,3,4,5,6,7,8");
}

Просмотреть файл

@ -11,14 +11,14 @@ function runTests() {
setPinnedLinks("");
yield addNewTabPageTab();
let gridNode = cw.gGrid.node;
let gridNode = getGrid().node;
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
NewTabUtils.allPages.enabled = false;
ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
let oldGridNode = cw.gGrid.node;
let oldGridNode = gridNode;
// create a second new tage page and make sure it's disabled. enable it
// again and check if the former page gets enabled as well.
@ -26,7 +26,7 @@ function runTests() {
ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
// check that no sites have been rendered
is(0, cw.document.querySelectorAll(".site").length, "no sites have been rendered");
is(0, getContentDocument().querySelectorAll(".site").length, "no sites have been rendered");
NewTabUtils.allPages.enabled = true;
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");

Просмотреть файл

@ -15,7 +15,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8");
yield simulateDrop(cells[1], cells[0]);
yield simulateDrop(1, 0);
checkGrid("1,0p,2,3,4,5,6,7,8");
// drag a cell to its current cell and make sure it's not pinned afterwards
@ -25,7 +25,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8");
yield simulateDrop(cells[0], cells[0]);
yield simulateDrop(0, 0);
checkGrid("0,1,2,3,4,5,6,7,8");
// ensure that pinned pages aren't moved if that's not necessary
@ -35,7 +35,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1p,2p,3,4,5,6,7,8");
yield simulateDrop(cells[3], cells[0]);
yield simulateDrop(3, 0);
checkGrid("3,1p,2p,0p,4,5,6,7,8");
// pinned sites should always be moved around as blocks. if a pinned site is
@ -46,7 +46,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0p,1p,2,3,4,5,6,7,8");
yield simulateDrop(cells[0], cells[2]);
yield simulateDrop(0, 2);
checkGrid("2p,0p,1p,3,4,5,6,7,8");
// pinned sites should not be pushed out of the grid (unless there are only
@ -57,7 +57,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7p,8p");
yield simulateDrop(cells[8], cells[2]);
yield simulateDrop(8, 2);
checkGrid("0,1,3,4,5,6,7p,8p,2p");
// make sure that pinned sites are re-positioned correctly
@ -67,7 +67,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0p,1p,2p,3,4,5p,6,7,8");
yield simulateDrop(cells[4], cells[0]);
yield simulateDrop(4, 0);
checkGrid("3,1p,2p,4,0p,5p,6,7,8");
// drag a new site onto the very first cell
@ -77,7 +77,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7p,8p");
yield simulateDrop(cells[0]);
yield simulateDrop(0);
checkGrid("99p,0,1,2,3,4,5,7p,8p");
// drag a new site onto the grid and make sure that pinned cells don't get
@ -88,7 +88,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7p,8p");
yield simulateDrop(cells[7]);
yield simulateDrop(7);
checkGrid("0,1,2,3,4,5,7p,99p,8p");
// drag a new site beneath a pinned cell and make sure the pinned cell is
@ -99,7 +99,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1,2,3,4,5,6,7,8p");
yield simulateDrop(cells[7]);
yield simulateDrop(7);
checkGrid("0,1,2,3,4,5,6,99p,8p");
// drag a new site onto a block of pinned sites and make sure they're shifted
@ -110,6 +110,6 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0p,1p,2p");
yield simulateDrop(cells[1]);
yield simulateDrop(1);
checkGrid("0p,99p,1p,2p,3,4,5,6,7");
}

Просмотреть файл

@ -13,8 +13,9 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0p,1p,2p,3,4,5p,6,7,8");
cw.gDrag._draggedSite = cells[0].site;
let sites = cw.gDropPreview.rearrange(cells[4]);
let cw = getContentWindow();
cw.gDrag._draggedSite = getCell(0).site;
let sites = cw.gDropPreview.rearrange(getCell(4));
cw.gDrag._draggedSite = null;
checkGrid("3,1p,2p,4,0p,5p,6,7,8", sites);

Просмотреть файл

@ -16,7 +16,7 @@ function runTests() {
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
yield addNewTabPageTab();
pinCell(cells[0]);
pinCell(0);
checkGrid("0p,1,2,3,4,5,6,7,8");
// enter private browsing mode
@ -27,10 +27,10 @@ function runTests() {
checkGrid("0p,1,2,3,4,5,6,7,8");
// modify the grid while we're in pb mode
yield blockCell(cells[1]);
yield blockCell(1);
checkGrid("0p,2,3,4,5,6,7,8");
yield unpinCell(cells[0]);
yield unpinCell(0);
checkGrid("0,2,3,4,5,6,7,8");
// exit private browsing mode

Просмотреть файл

@ -13,16 +13,16 @@ function runTests() {
setPinnedLinks("");
yield addNewTabPageTab();
let resetButton = cw.document.getElementById("toolbar-button-reset");
let resetButton = getContentDocument().getElementById("toolbar-button-reset");
checkGrid("0,1,2,3,4,5,6,7,8");
ok(!resetButton.hasAttribute("modified"), "page is not modified");
yield blockCell(cells[4]);
yield blockCell(4);
checkGrid("0,1,2,3,5,6,7,8,");
ok(resetButton.hasAttribute("modified"), "page is modified");
yield cw.gToolbar.reset(TestRunner.next);
yield getContentWindow().gToolbar.reset(TestRunner.next);
checkGrid("0,1,2,3,4,5,6,7,8");
ok(!resetButton.hasAttribute("modified"), "page is not modified");
}

Просмотреть файл

@ -17,45 +17,45 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1p,2,3,4,5,6,7,8");
let resetButton = cw.document.getElementById("toolbar-button-reset");
let resetButton = getContentDocument().getElementById("toolbar-button-reset");
ok(!resetButton.hasAttribute("modified"), "page is not modified");
let oldCw = cw;
let oldSites = getGrid().sites;
let oldResetButton = resetButton;
// create the new tab page
yield addNewTabPageTab();
checkGrid("0,1p,2,3,4,5,6,7,8");
resetButton = cw.document.getElementById("toolbar-button-reset");
resetButton = getContentDocument().getElementById("toolbar-button-reset");
ok(!resetButton.hasAttribute("modified"), "page is not modified");
// unpin a cell
yield unpinCell(cells[1]);
yield unpinCell(1);
checkGrid("0,1,2,3,4,5,6,7,8");
checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites);
checkGrid("0,1,2,3,4,5,6,7,8", oldSites);
// remove a cell
yield blockCell(cells[1]);
yield blockCell(1);
checkGrid("0,2,3,4,5,6,7,8,9");
checkGrid("0,2,3,4,5,6,7,8,9", oldCw.gGrid.sites);
checkGrid("0,2,3,4,5,6,7,8,9", oldSites);
ok(resetButton.hasAttribute("modified"), "page is modified");
ok(oldResetButton.hasAttribute("modified"), "page is modified");
// insert a new cell by dragging
yield simulateDrop(cells[1]);
yield simulateDrop(1);
checkGrid("0,99p,2,3,4,5,6,7,8");
checkGrid("0,99p,2,3,4,5,6,7,8", oldCw.gGrid.sites);
checkGrid("0,99p,2,3,4,5,6,7,8", oldSites);
// drag a cell around
yield simulateDrop(cells[1], cells[2]);
yield simulateDrop(1, 2);
checkGrid("0,2p,99p,3,4,5,6,7,8");
checkGrid("0,2p,99p,3,4,5,6,7,8", oldCw.gGrid.sites);
checkGrid("0,2p,99p,3,4,5,6,7,8", oldSites);
// reset the new tab page
yield cw.gToolbar.reset(TestRunner.next);
yield getContentWindow().gToolbar.reset(TestRunner.next);
checkGrid("0,1,2,3,4,5,6,7,8");
checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites);
checkGrid("0,1,2,3,4,5,6,7,8", oldSites);
ok(!resetButton.hasAttribute("modified"), "page is not modified");
ok(!oldResetButton.hasAttribute("modified"), "page is not modified");
}

Просмотреть файл

@ -14,7 +14,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,1p,2,3,4,5,6,7,8");
yield unpinCell(cells[1]);
yield unpinCell(1);
checkGrid("0,1,2,3,4,5,6,7,8");
// we have a pinned link that is not anymore in the list of the most-visited
@ -26,7 +26,7 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("0,99p,1,2,3,4,5,6,7");
yield unpinCell(cells[1]);
yield unpinCell(1);
checkGrid("0,1,2,3,4,5,6,7,8");
// we have a pinned link that changed its position since it was pinned. it
@ -37,10 +37,10 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("2,1p,3,4,5,6,7,,0p");
yield unpinCell(cells[1]);
yield unpinCell(1);
checkGrid("1,2,3,4,5,6,7,,0p");
yield unpinCell(cells[8]);
yield unpinCell(8);
checkGrid("0,1,2,3,4,5,6,7,");
// we have pinned link that changed its position since it was pinned. the
@ -51,6 +51,6 @@ function runTests() {
yield addNewTabPageTab();
checkGrid("9p,0,1,2,3,4,5,6,7");
yield unpinCell(cells[0]);
yield unpinCell(0);
checkGrid("0,1,2,3,4,5,6,7,8");
}

Просмотреть файл

@ -16,12 +16,6 @@ registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
});
/**
* Global variables that are accessed by tests.
*/
let cw;
let cells;
/**
* We'll want to restore the original links provider later.
*/
@ -81,6 +75,39 @@ let TestRunner = {
}
};
/**
* Returns the selected tab's content window.
* @return The content window.
*/
function getContentWindow() {
return gBrowser.selectedBrowser.contentWindow;
}
/**
* Returns the selected tab's content document.
* @return The content document.
*/
function getContentDocument() {
return gBrowser.selectedBrowser.contentDocument;
}
/**
* Returns the newtab grid of the selected tab.
* @return The newtab grid.
*/
function getGrid() {
return getContentWindow().gGrid;
}
/**
* Returns the cell at the given index of the selected tab's newtab grid.
* @param aIndex The cell index.
* @return The newtab cell.
*/
function getCell(aIndex) {
return getGrid().cells[aIndex];
}
/**
* Allows to provide a list of links that is used to construct the grid.
* @param aLinksPattern the pattern (see below)
@ -143,18 +170,14 @@ function addNewTabPageTab() {
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
cw = browser.contentWindow;
if (NewTabUtils.allPages.enabled) {
// Continue when the link cache has been populated.
NewTabUtils.links.populateCache(function () {
cells = cw.gGrid.cells;
executeSoon(TestRunner.next);
});
} else {
TestRunner.next();
}
}, true);
}
@ -169,118 +192,118 @@ function addNewTabPageTab() {
* The fourth cell contains the pinned site 'about:blank#4'.
*/
function checkGrid(aSitesPattern, aSites) {
let valid = true;
let length = aSitesPattern.split(",").length;
let sites = (aSites || getGrid().sites).slice(0, length);
let expected = sites.map(function (aSite) {
if (!aSite)
return "";
aSites = aSites || cw.gGrid.sites;
let pinned = aSite.isPinned();
let pinButton = aSite.node.querySelector(".newtab-control-pin");
let hasPinnedAttr = pinButton.hasAttribute("pinned");
aSitesPattern.split(/\s*,\s*/).forEach(function (id, index) {
let site = aSites[index];
let match = id.match(/^\d+/);
if (pinned != hasPinnedAttr)
ok(false, "invalid state (site.isPinned() != site[pinned])");
// We expect the cell to be empty.
if (!match) {
if (site) {
valid = false;
ok(false, "expected cell#" + index + " to be empty");
}
return;
}
// We expect the cell to contain a site.
if (!site) {
valid = false;
ok(false, "didn't expect cell#" + index + " to be empty");
return;
}
let num = match[0];
// Check the site's url.
if (site.url != "about:blank#" + num) {
valid = false;
is(site.url, "about:blank#" + num, "cell#" + index + " has the wrong url");
}
let shouldBePinned = /p$/.test(id);
let cellContainsPinned = site.isPinned();
let cssClassPinned = site.node && site.node.querySelector(".newtab-control-pin").hasAttribute("pinned");
// Check if the site should be and is pinned.
if (shouldBePinned) {
if (!cellContainsPinned) {
valid = false;
ok(false, "expected cell#" + index + " to be pinned");
} else if (!cssClassPinned) {
valid = false;
ok(false, "expected cell#" + index + " to have css class 'pinned'");
}
} else {
if (cellContainsPinned) {
valid = false;
ok(false, "didn't expect cell#" + index + " to be pinned");
} else if (cssClassPinned) {
valid = false;
ok(false, "didn't expect cell#" + index + " to have css class 'pinned'");
}
}
return aSite.url.replace(/^about:blank#(\d+)$/, "$1") + (pinned ? "p" : "");
});
// If every test passed, say so.
if (valid)
ok(true, "grid status = " + aSitesPattern);
is(aSitesPattern, expected, "grid status = " + aSitesPattern);
}
/**
* Blocks the given cell's site from the grid.
* @param aCell the cell that contains the site to block
* Blocks a site from the grid.
* @param aIndex The cell index.
*/
function blockCell(aCell) {
aCell.site.block(function () executeSoon(TestRunner.next));
function blockCell(aIndex) {
whenPagesUpdated();
getCell(aIndex).site.block();
}
/**
* Pins a given cell's site on a given position.
* @param aCell the cell that contains the site to pin
* @param aIndex the index the defines where the site should be pinned
* Pins a site on a given position.
* @param aIndex The cell index.
* @param aPinIndex The index the defines where the site should be pinned.
*/
function pinCell(aCell, aIndex) {
aCell.site.pin(aIndex);
function pinCell(aIndex, aPinIndex) {
getCell(aIndex).site.pin(aPinIndex);
}
/**
* Unpins the given cell's site.
* @param aCell the cell that contains the site to unpin
* @param aIndex The cell index.
*/
function unpinCell(aCell) {
aCell.site.unpin(function () executeSoon(TestRunner.next));
function unpinCell(aIndex) {
whenPagesUpdated();
getCell(aIndex).site.unpin();
}
/**
* Simulates a drop and drop operation.
* @param aDropTarget the cell that is the drop target
* @param aDragSource the cell that contains the dragged site (optional)
* @param aDropIndex The cell index of the drop target.
* @param aDragIndex The cell index containing the dragged site (optional).
*/
function simulateDrop(aDropTarget, aDragSource) {
let event = {
clientX: 0,
clientY: 0,
dataTransfer: {
mozUserCancelled: false,
setData: function () null,
setDragImage: function () null,
getData: function () "about:blank#99\nblank"
function simulateDrop(aDropIndex, aDragIndex) {
let draggedSite;
let {gDrag: drag, gDrop: drop} = getContentWindow();
let event = createDragEvent("drop", "about:blank#99\nblank");
if (typeof aDragIndex != "undefined")
draggedSite = getCell(aDragIndex).site;
if (draggedSite)
drag.start(draggedSite, event);
whenPagesUpdated();
drop.drop(getCell(aDropIndex), event);
if (draggedSite)
drag.end(draggedSite);
}
/**
* Sends a custom drag event to a given DOM element.
* @param aEventType The drag event's type.
* @param aTarget The DOM element that the event is dispatched to.
* @param aData The event's drag data (optional).
*/
function sendDragEvent(aEventType, aTarget, aData) {
let event = createDragEvent(aEventType, aData);
let ifaceReq = getContentWindow().QueryInterface(Ci.nsIInterfaceRequestor);
let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
windowUtils.dispatchDOMEventViaPresShell(aTarget, event, true);
}
/**
* Creates a custom drag event.
* @param aEventType The drag event's type.
* @param aData The event's drag data (optional).
* @return The drag event.
*/
function createDragEvent(aEventType, aData) {
let dataTransfer = {
mozUserCancelled: false,
setData: function () null,
setDragImage: function () null,
getData: function () aData,
types: {
contains: function (aType) aType == "text/x-moz-url"
},
mozGetDataAt: function (aType, aIndex) {
if (aIndex || aType != "text/x-moz-url")
return null;
return aData;
}
};
if (aDragSource)
cw.gDrag.start(aDragSource.site, event);
let event = getContentDocument().createEvent("DragEvents");
event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
cw.gDrop.drop(aDropTarget, event, function () executeSoon(TestRunner.next));
if (aDragSource)
cw.gDrag.end(aDragSource.site);
return event;
}
/**

Просмотреть файл

@ -54,10 +54,6 @@
#include "nsIStringBundle.h"
#include "nsXPCOMCID.h"
#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
#define DEFAULT_BOOKMARKS NS_LITERAL_CSTRING("resource:///defaults/profile/bookmarks.html")
void SetUnicharPref(const char* aPref, const nsAString& aValue,
nsIPrefBranch* aPrefs)
{

Просмотреть файл

@ -747,10 +747,6 @@ nsDefaultCommandLineHandler.prototype = {
return this;
},
// List of uri's that were passed via the command line without the app
// running and have already been handled. This is compared against uri's
// opened using DDE on Win32 so we only open one of the requests.
_handledURIs: [ ],
#ifdef XP_WIN
_haveProfile: false,
#endif
@ -784,25 +780,8 @@ nsDefaultCommandLineHandler.prototype = {
try {
var ar;
while ((ar = cmdLine.handleFlagWithParam("url", false))) {
var found = false;
var uri = resolveURIInternal(cmdLine, ar);
// count will never be greater than zero except on Win32.
var count = this._handledURIs.length;
for (var i = 0; i < count; ++i) {
if (this._handledURIs[i].spec == uri.spec) {
this._handledURIs.splice(i, 1);
found = true;
cmdLine.preventDefault = true;
break;
}
}
if (!found) {
urilist.push(uri);
// The requestpending command line flag is only used on Win32.
if (cmdLine.handleFlag("requestpending", false) &&
cmdLine.state == nsICommandLine.STATE_INITIAL_LAUNCH)
this._handledURIs.push(uri)
}
urilist.push(uri);
}
}
catch (e) {

Просмотреть файл

@ -65,9 +65,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
"resource://gre/modules/BookmarkHTMLUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
"resource:///modules/KeywordURLResetPrompter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
"resource:///modules/webappsUI.jsm");
@ -273,13 +270,6 @@ BrowserGlue.prototype = {
this._initPlaces();
}
break;
case "defaultURIFixup-using-keyword-pref":
if (KeywordURLResetPrompter.shouldPrompt) {
let keywordURI = subject.QueryInterface(Ci.nsIURI);
KeywordURLResetPrompter.prompt(this.getMostRecentBrowserWindow(),
keywordURI);
}
break;
case "initial-migration":
this._initialMigrationPerformed = true;
break;
@ -312,7 +302,6 @@ BrowserGlue.prototype = {
os.addObserver(this, "distribution-customization-complete", false);
os.addObserver(this, "places-shutdown", false);
this._isPlacesShutdownObserver = true;
os.addObserver(this, "defaultURIFixup-using-keyword-pref", false);
},
// cleanup (called on application shutdown)
@ -341,7 +330,6 @@ BrowserGlue.prototype = {
os.removeObserver(this, "places-database-locked");
if (this._isPlacesShutdownObserver)
os.removeObserver(this, "places-shutdown");
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
webappsUI.uninit();
},
@ -1255,13 +1243,7 @@ BrowserGlue.prototype = {
// Need to migrate only if toolbar is customized and the element is not found.
if (currentset &&
currentset.indexOf("bookmarks-menu-button-container") == -1) {
if (currentset.indexOf("fullscreenflex") != -1) {
currentset = currentset.replace(/(^|,)fullscreenflex($|,)/,
"$1bookmarks-menu-button-container,fullscreenflex$2")
}
else {
currentset += ",bookmarks-menu-button-container";
}
currentset += ",bookmarks-menu-button-container";
this._setPersist(toolbarResource, currentsetResource, currentset);
}
}

Просмотреть файл

@ -193,9 +193,9 @@ PrivateBrowsingService.prototype = {
if (!this._quitting && this._saveSession) {
let browserWindow = this._getBrowserWindow();
// if there are open browser windows, load a dummy session to get a distinct
// if there are open browser windows, load a dummy session to get a distinct
// separation between private and non-private sessions
if (browserWindow) {
if (browserWindow) {
// set an empty session to transition from/to pb mode, see bug 476463
ss.setBrowserState(blankState);
@ -217,7 +217,9 @@ PrivateBrowsingService.prototype = {
.getInterface(Ci.nsIXULWindow)
.docShell.contentViewer.resetCloseWindow();
}
}
if (!this._quitting) {
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
var window = windowsEnum.getNext();

Просмотреть файл

@ -58,21 +58,31 @@ function test() {
ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
ok(pbMenuItem, "The Private Browsing menu item exists");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
gPrivateBrowsingUI.toggleMode();
is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
// check to see if the Private Browsing mode was activated successfully
is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
gPrivateBrowsingUI.toggleMode()
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
// check to see if the Private Browsing mode was deactivated successfully
is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
// These are tests for the privateWindow setter. Note that the setter should
// not be used anywhere else for now!
gPrivateBrowsingUI.privateWindow = true;
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
gPrivateBrowsingUI.privateWindow = false;
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
// now, test using the <command> object
let cmd = document.getElementById("Tools:PrivateBrowsing");
isnot(cmd, null, "XUL command object for the private browsing service exists");

Просмотреть файл

@ -77,7 +77,10 @@
#define INITGUID
#include <shlobj.h>
#pragma comment(lib, "shlwapi.lib") // for SHDeleteKeyW
#include <mbstring.h>
#include <shlwapi.h>
#ifndef MAX_BUF
#define MAX_BUF 4096
@ -129,23 +132,17 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
//
// HKCU\SOFTWARE\Classes\FirefoxHTML\
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Windows Vista Protocol Handler
// - Windows Vista and above Protocol Handler
//
// HKCU\SOFTWARE\Classes\FirefoxURL\ (default) REG_SZ <appname> URL
// EditFlags REG_DWORD 2
// FriendlyTypeName REG_SZ <appname> URL
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Protocol Mappings
// -----------------
@ -155,13 +152,10 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
//
// HKCU\SOFTWARE\Classes\<protocol>\
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Windows Start Menu (Win2K SP2, XP SP1, and newer)
// - Windows Start Menu (XP SP1 and newer)
// -------------------------------------------------
// The following keys are set to make Firefox appear in the Start Menu as the
// browser:
@ -180,19 +174,22 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
// shell\safemode\command (default) REG_SZ <apppath> -safe-mode
//
// The values checked are all default values so the value name is not needed.
typedef struct {
char* keyName;
char* valueName;
char* valueData;
char* oldValueData;
} SETTING;
#define APP_REG_NAME L"Firefox"
#define CLS_HTML "FirefoxHTML"
#define CLS_URL "FirefoxURL"
#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
#define VAL_FILE_ICON "%APPPATH%,1"
#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
#define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
#define DI "\\DefaultIcon"
#define SOP "\\shell\\open\\command"
#define SOC "\\shell\\open\\command"
#define SOD "\\shell\\open\\ddeexec"
// Used for updating the FTP protocol handler's shell open command under HKCU.
#define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command"
#define MAKE_KEY_NAME1(PREFIX, MID) \
PREFIX MID
@ -201,19 +198,37 @@ typedef struct {
// Firefox is the default browser for file handlers since other applications
// (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
// Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
// more info.
// more info. The FTP protocol is not checked so advanced users can set the FTP
// handler to another application and still have Firefox check if it is the
// default HTTP and HTTPS handler.
static SETTING gSettings[] = {
// File Handler Class
{ MAKE_KEY_NAME1(CLS_HTML, SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("FirefoxHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME1(CLS_URL, SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("FirefoxURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
// Protocol Handlers
{ MAKE_KEY_NAME1("HTTP", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTP", SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("HTTPS", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTPS", SOP), "", VAL_OPEN }
{ MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
{ MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
};
// The settings to disable DDE are separate from the default browser settings
// since they are only checked when Firefox is the default browser and if they
// are incorrect they are fixed without notifying the user.
static SETTING gDDESettings[] = {
// File Handler Class
{ MAKE_KEY_NAME1("Software\\Classes\\FirefoxHTML", SOD) },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME1("Software\\Classes\\FirefoxURL", SOD) },
// Protocol Handlers
{ MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
{ MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
{ MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
};
nsresult
@ -245,11 +260,10 @@ LaunchHelper(nsAutoString& aPath)
STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
BOOL ok = CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi);
if (!ok)
if (!CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL, FALSE, 0, NULL,
NULL, &si, &pi)) {
return NS_ERROR_FAILURE;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@ -367,9 +381,6 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
if (aStartupCheck)
mCheckedThisSession = true;
SETTING* settings;
SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING);
*aIsDefaultBrowser = true;
PRUnichar exePath[MAX_BUF];
@ -383,40 +394,171 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
nsAutoString appLongPath(exePath);
HKEY theKey;
DWORD res;
nsresult rv;
PRUnichar currValue[MAX_BUF];
for (settings = gSettings; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData);
NS_ConvertUTF8toUTF16 key(settings->keyName);
NS_ConvertUTF8toUTF16 value(settings->valueName);
PRInt32 offset = dataLongPath.Find("%APPPATH%");
dataLongPath.Replace(offset, 9, appLongPath);
::ZeroMemory(currValue, sizeof(currValue));
HKEY theKey;
rv = OpenKeyForReading(HKEY_CLASSES_ROOT, key, &theKey);
SETTING* settings;
SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
for (settings = gSettings; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 keyName(settings->keyName);
NS_ConvertUTF8toUTF16 valueData(settings->valueData);
PRInt32 offset = valueData.Find("%APPPATH%");
valueData.Replace(offset, 9, appLongPath);
rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
if (NS_FAILED(rv)) {
*aIsDefaultBrowser = false;
return NS_OK;
}
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(),
NULL, NULL, (LPBYTE)currValue, &len);
// Close the key we opened.
res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue, &len);
// Close the key that was opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) ||
!dataLongPath.Equals(currValue, CaseInsensitiveCompare)) {
// Key wasn't set, or was set to something other than our registry entry
*aIsDefaultBrowser = false;
return NS_OK;
!valueData.Equals(currValue, CaseInsensitiveCompare)) {
// Key wasn't set or was set to something other than our registry entry.
NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData);
offset = oldValueData.Find("%APPPATH%");
oldValueData.Replace(offset, 9, appLongPath);
// The current registry value doesn't match the current or the old format.
if (!oldValueData.Equals(currValue, CaseInsensitiveCompare)) {
*aIsDefaultBrowser = false;
return NS_OK;
}
res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(),
0, KEY_SET_VALUE, &theKey);
if (REG_FAILED(res)) {
// If updating the open command fails try to update it using the helper
// application when setting Firefox as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(),
(flatValue.Length() + 1) * sizeof(PRUnichar));
// Close the key that was created.
::RegCloseKey(theKey);
if (REG_FAILED(res)) {
// If updating the open command fails try to update it using the helper
// application when setting Firefox as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
}
}
// Only check if Firefox is the default browser on Vista if the previous
// checks show that Firefox is the default browser.
if (*aIsDefaultBrowser)
// Only check if Firefox is the default browser on Vista and above if the
// previous checks show that Firefox is the default browser.
if (*aIsDefaultBrowser) {
IsDefaultBrowserVista(aIsDefaultBrowser);
}
// To handle the case where DDE isn't disabled due for a user because there
// account didn't perform a Firefox update this will check if Firefox is the
// default browser and if dde is disabled for each handler
// and if it isn't disable it. When Firefox is not the default browser the
// helper application will disable dde for each handler.
if (*aIsDefaultBrowser) {
// Check ftp settings
end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
for (settings = gDDESettings; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 keyName(settings->keyName);
rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
if (NS_FAILED(rv)) {
::RegCloseKey(theKey);
// If disabling DDE fails try to disable it using the helper
// application when setting Firefox as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue,
&len);
// Close the key that was opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) || PRUnichar('\0') != *currValue) {
// Key wasn't set or was set to something other than our registry entry.
// Delete the key along with all of its childrean and then recreate it.
const nsString &flatName = PromiseFlatString(keyName);
::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get());
res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
&theKey, NULL);
if (REG_FAILED(res)) {
// If disabling DDE fails try to disable it using the helper
// application when setting Firefox as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"",
sizeof(PRUnichar));
// Close the key that was created.
::RegCloseKey(theKey);
if (REG_FAILED(res)) {
// If disabling DDE fails try to disable it using the helper
// application when setting Firefox as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
}
}
// Update the FTP protocol handler's shell open command if it is the old
// format.
res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS,
&theKey);
// Don't update the FTP protocol handler's shell open command when opening
// its registry key fails under HKCU since it most likely doesn't exist.
if (NS_FAILED(rv)) {
return NS_OK;
}
NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN);
PRInt32 offset = oldValueOpen.Find("%APPPATH%");
oldValueOpen.Replace(offset, 9, appLongPath);
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue,
&len);
// Don't update the FTP protocol handler's shell open command when the
// current registry value doesn't exist or matches the old format.
if (REG_FAILED(res) ||
!oldValueOpen.Equals(currValue, CaseInsensitiveCompare)) {
::RegCloseKey(theKey);
return NS_OK;
}
NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
valueData.Replace(offset, 9, appLongPath);
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(),
(flatValue.Length() + 1) * sizeof(PRUnichar));
// Close the key that was created.
::RegCloseKey(theKey);
// If updating the FTP protocol handlers shell open command fails try to
// update it using the helper application when setting Firefox as the
// default browser.
if (REG_FAILED(res)) {
*aIsDefaultBrowser = false;
}
}
return NS_OK;
}

Просмотреть файл

@ -25,9 +25,6 @@ const Ci = Components.interfaces;
Cu.import("resource:///modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
@ -104,268 +101,252 @@ function Channel(aURI) {
}
Channel.prototype = {
/**
* Tracks if the channel has been opened, yet.
*/
_uri: null,
_referrer: null,
_canceled: false,
_status: Cr.NS_OK,
_isPending: false,
_wasOpened: false,
_responseText: "OK",
_responseStatus: 200,
_responseHeaders: null,
_requestMethod: "GET",
_requestStarted: false,
_allowPipelining: true,
_requestSucceeded: true,
/* :::::::: nsIChannel ::::::::::::::: */
get URI() this._uri,
owner: null,
notificationCallbacks: null,
get securityInfo() null,
contentType: PageThumbs.contentType,
contentCharset: null,
contentLength: -1,
get contentDisposition() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
get contentDispositionFilename() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
get contentDispositionHeader() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
open: function Channel_open() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_IMPLEMENTED);
},
/**
* Opens this channel asynchronously.
* @param aListener The listener that receives the channel data when available.
* @param aContext A custom context passed to the listener's methods.
*/
asyncOpen: function Channel_asyncOpen(aListener, aContext) {
if (this._isPending)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
if (this._wasOpened)
throw Cr.NS_ERROR_ALREADY_OPENED;
throw (Components.returnCode = Cr.NS_ERROR_ALREADY_OPENED);
if (this.canceled)
return;
this._listener = aListener;
this._context = aContext;
if (this._canceled)
return (Components.returnCode = this._status);
this._isPending = true;
this._wasOpened = true;
// Try to read the data from the thumbnail cache.
this._readCache(function (aData) {
let telemetryThumbnailFound = true;
this._listener = aListener;
this._context = aContext;
// Update response if there's no data.
if (!aData) {
this._responseStatus = 404;
this._responseText = "Not Found";
telemetryThumbnailFound = false;
}
if (this.loadGroup)
this.loadGroup.addRequest(this, null);
Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS")
.add(telemetryThumbnailFound);
if (this._canceled)
return;
this._startRequest();
if (!this.canceled) {
this._addToLoadGroup();
if (aData)
this._serveData(aData);
if (!this.canceled)
this._stopRequest();
}
}.bind(this));
},
/**
* Reads a data stream from the cache entry.
* @param aCallback The callback the data is passed to.
*/
_readCache: function Channel_readCache(aCallback) {
let {url} = parseURI(this._uri);
// Return early if there's no valid URL given.
if (!url) {
aCallback(null);
this._serveThumbnailNotFound();
return;
}
// Try to get a cache entry.
PageThumbsCache.getReadEntry(url, function (aEntry) {
let inputStream = aEntry && aEntry.openInputStream(0);
function closeEntryAndFinish(aData) {
if (aEntry) {
aEntry.close();
}
aCallback(aData);
}
// Check if we have a valid entry and if it has any data.
if (!inputStream || !inputStream.available()) {
closeEntryAndFinish();
if (aEntry)
aEntry.close();
this._serveThumbnailNotFound();
return;
}
try {
// Read the cache entry's data.
NetUtil.asyncFetch(inputStream, function (aData, aStatus) {
// We might have been canceled while waiting.
if (this.canceled)
return;
this._entry = aEntry;
this._pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump);
// Check if we have a valid data stream.
if (!Components.isSuccessCode(aStatus) || !aData.available())
aData = null;
this._pump.init(inputStream, -1, -1, 0, 0, true);
this._pump.asyncRead(this, null);
closeEntryAndFinish(aData);
}.bind(this));
} catch (e) {
closeEntryAndFinish();
}
this._trackThumbnailHitOrMiss(true);
}.bind(this));
},
/**
* Calls onStartRequest on the channel listener.
* Serves a "404 Not Found" if we didn't find the requested thumbnail.
*/
_startRequest: function Channel_startRequest() {
try {
this._listener.onStartRequest(this, this._context);
} catch (e) {
// The listener might throw if the request has been canceled.
this.cancel(Cr.NS_BINDING_ABORTED);
}
_serveThumbnailNotFound: function Channel_serveThumbnailNotFound() {
this._responseStatus = 404;
this._responseText = "Not Found";
this._requestSucceeded = false;
this.onStartRequest(this, null);
this.onStopRequest(this, null, Cr.NS_OK);
this._trackThumbnailHitOrMiss(false);
},
/**
* Calls onDataAvailable on the channel listener and passes the data stream.
* @param aData The data to be delivered.
* Implements telemetry tracking for thumbnail cache hits and misses.
* @param aFound Whether the thumbnail was found.
*/
_serveData: function Channel_serveData(aData) {
try {
let available = aData.available();
this._listener.onDataAvailable(this, this._context, aData, 0, available);
} catch (e) {
// The listener might throw if the request has been canceled.
this.cancel(Cr.NS_BINDING_ABORTED);
}
_trackThumbnailHitOrMiss: function Channel_trackThumbnailHitOrMiss(aFound) {
Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS")
.add(aFound);
},
/**
* Calls onStopRequest on the channel listener.
*/
_stopRequest: function Channel_stopRequest() {
try {
this._listener.onStopRequest(this, this._context, this.status);
} catch (e) {
// This might throw but is generally ignored.
}
/* :::::::: nsIStreamListener ::::::::::::::: */
// The request has finished, clean up after ourselves.
this._cleanup();
onStartRequest: function Channel_onStartRequest(aRequest, aContext) {
if (!this.canceled && Components.isSuccessCode(this._status))
this._status = aRequest.status;
this._requestStarted = true;
this._listener.onStartRequest(this, this._context);
},
/**
* Adds this request to the load group, if any.
*/
_addToLoadGroup: function Channel_addToLoadGroup() {
onDataAvailable: function Channel_onDataAvailable(aRequest, aContext,
aInStream, aOffset, aCount) {
this._listener.onDataAvailable(this, this._context, aInStream, aOffset, aCount);
},
onStopRequest: function Channel_onStopRequest(aRequest, aContext, aStatus) {
this._isPending = false;
this._status = aStatus;
this._listener.onStopRequest(this, this._context, aStatus);
this._listener = null;
this._context = null;
if (this._entry)
this._entry.close();
if (this.loadGroup)
this.loadGroup.addRequest(this, this._context);
this.loadGroup.removeRequest(this, null, aStatus);
},
/**
* Removes this request from its load group, if any.
*/
_removeFromLoadGroup: function Channel_removeFromLoadGroup() {
if (!this.loadGroup)
/* :::::::: nsIRequest ::::::::::::::: */
get status() this._status,
get name() this._uri.spec,
isPending: function Channel_isPending() this._isPending,
loadFlags: Ci.nsIRequest.LOAD_NORMAL,
loadGroup: null,
cancel: function Channel_cancel(aStatus) {
if (this._canceled)
return;
try {
this.loadGroup.removeRequest(this, this._context, this.status);
} catch (e) {
// This might throw but is ignored.
}
this._canceled = true;
this._status = aStatus;
if (this._pump)
this._pump.cancel(aStatus);
},
/**
* Cleans up the channel when the request has finished.
*/
_cleanup: function Channel_cleanup() {
this._removeFromLoadGroup();
this.loadGroup = null;
this._isPending = false;
delete this._listener;
delete this._context;
suspend: function Channel_suspend() {
if (this._pump)
this._pump.suspend();
},
/* :::::::: nsIChannel ::::::::::::::: */
contentType: PageThumbs.contentType,
contentLength: -1,
owner: null,
contentCharset: null,
notificationCallbacks: null,
get URI() this._uri,
get securityInfo() null,
/**
* Opens this channel synchronously. Not supported.
*/
open: function Channel_open() {
// Synchronous data delivery is not implemented.
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
resume: function Channel_resume() {
if (this._pump)
this._pump.resume();
},
/* :::::::: nsIHttpChannel ::::::::::::::: */
redirectionLimit: 10,
requestMethod: "GET",
allowPipelining: true,
referrer: null,
get referrer() this._referrer,
get requestSucceeded() true,
set referrer(aReferrer) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
_responseStatus: 200,
get responseStatus() this._responseStatus,
_responseText: "OK",
get responseStatusText() this._responseText,
/**
* Checks if the server sent the equivalent of a "Cache-control: no-cache"
* response header.
* @return Always false.
*/
isNoCacheResponse: function () false,
/**
* Checks if the server sent the equivalent of a "Cache-control: no-cache"
* response header.
* @return Always false.
*/
isNoStoreResponse: function () false,
/**
* Returns the value of a particular request header. Not implemented.
*/
getRequestHeader: function Channel_getRequestHeader() {
throw Cr.NS_ERROR_NOT_AVAILABLE;
this._referrer = aReferrer;
},
get requestMethod() this._requestMethod,
set requestMethod(aMethod) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
this._requestMethod = aMethod.toUpperCase();
},
get allowPipelining() this._allowPipelining,
set allowPipelining(aAllow) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_FAILURE);
this._allowPipelining = aAllow;
},
redirectionLimit: 10,
get responseStatus() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._responseStatus;
},
get responseStatusText() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._responseText;
},
get requestSucceeded() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._requestSucceeded;
},
isNoCacheResponse: function Channel_isNoCacheResponse() false,
isNoStoreResponse: function Channel_isNoStoreResponse() false,
getRequestHeader: function Channel_getRequestHeader() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
/**
* This method is called to set the value of a particular request header.
* Not implemented.
*/
setRequestHeader: function Channel_setRequestHeader() {
if (this._wasOpened)
throw Cr.NS_ERROR_IN_PROGRESS;
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
},
/**
* Call this method to visit all request headers. Not implemented.
*/
visitRequestHeaders: function () {},
visitRequestHeaders: function Channel_visitRequestHeaders() {},
/**
* Gets the value of a particular response header.
* @param aHeader The case-insensitive name of the response header to query.
* @return The header value.
*/
getResponseHeader: function Channel_getResponseHeader(aHeader) {
let name = aHeader.toLowerCase();
if (name in this._responseHeaders)
return this._responseHeaders[name];
throw Cr.NS_ERROR_NOT_AVAILABLE;
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
/**
* This method is called to set the value of a particular response header.
* @param aHeader The case-insensitive name of the response header to query.
* @param aValue The response header value to set.
*/
setResponseHeader: function Channel_setResponseHeader(aHeader, aValue, aMerge) {
let name = aHeader.toLowerCase();
if (!aValue && !aMerge)
@ -374,10 +355,6 @@ Channel.prototype = {
this._responseHeaders[name] = aValue;
},
/**
* Call this method to visit all response headers.
* @param aVisitor The header visitor.
*/
visitResponseHeaders: function Channel_visitResponseHeaders(aVisitor) {
for (let name in this._responseHeaders) {
let value = this._responseHeaders[name];
@ -391,48 +368,17 @@ Channel.prototype = {
}
},
/* :::::::: nsIRequest ::::::::::::::: */
loadFlags: Ci.nsIRequest.LOAD_NORMAL,
loadGroup: null,
get name() this._uri.spec,
_status: Cr.NS_OK,
get status() this._status,
_isPending: false,
isPending: function () this._isPending,
resume: function () {},
suspend: function () {},
/**
* Cancels this request.
* @param aStatus The reason for cancelling.
*/
cancel: function Channel_cancel(aStatus) {
if (this.canceled)
return;
this._isCanceled = true;
this._status = aStatus;
this._cleanup();
},
/* :::::::: nsIHttpChannelInternal ::::::::::::::: */
documentURI: null,
_isCanceled: false,
get canceled() this._isCanceled,
get canceled() this._canceled,
allowSpdy: false,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel,
Ci.nsIHttpChannel,
Ci.nsIHttpChannelInternal,
Ci.nsIRequest])
};
}
/**
* Parses a given URI and extracts all parameters relevant to this protocol.

Просмотреть файл

@ -11,22 +11,22 @@ ac_add_options --enable-js-diagnostics
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# PGO
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
# Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -11,22 +11,22 @@ ac_add_options --enable-js-diagnostics
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat
# PGO
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# PGO
mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
# Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

Просмотреть файл

@ -67,7 +67,8 @@ Cu.import("resource:///modules/devtools/CssLogic.jsm");
var EXPORTED_SYMBOLS = ["CssRuleView",
"_ElementStyle",
"_editableField"];
"_editableField",
"_getInplaceEditorForSpan"];
/**
* Our model looks like this:
@ -1475,6 +1476,14 @@ InplaceEditor.prototype = {
}
};
/*
* Various API consumers (especially tests) sometimes want to grab the
* inplaceEditor expando off span elements. However, when each global has its
* own compartment, those expandos live on Xray wrappers that are only visible
* within this JSM. So we provide a little workaround here.
*/
function _getInplaceEditorForSpan(aSpan) { return aSpan.inplaceEditor; };
/**
* Store of CSSStyleDeclarations mapped to properties that have been changed by
* the user.

Просмотреть файл

@ -7,6 +7,7 @@ Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let inplaceEditor = tempScope._getInplaceEditorForSpan;
let doc = content.document;
@ -43,8 +44,8 @@ function testReturnCommit()
element: span,
initial: "explicit initial",
start: function() {
is(span.inplaceEditor.input.value, "explicit initial", "Explicit initial value should be used.");
span.inplaceEditor.input.value = "Test Value";
is(inplaceEditor(span).input.value, "explicit initial", "Explicit initial value should be used.");
inplaceEditor(span).input.value = "Test Value";
EventUtils.sendKey("return");
},
done: expectDone("Test Value", true, testBlurCommit)
@ -59,9 +60,9 @@ function testBlurCommit()
_editableField({
element: span,
start: function() {
is(span.inplaceEditor.input.value, "Edit Me!", "textContent of the span used.");
span.inplaceEditor.input.value = "Test Value";
span.inplaceEditor.input.blur();
is(inplaceEditor(span).input.value, "Edit Me!", "textContent of the span used.");
inplaceEditor(span).input.value = "Test Value";
inplaceEditor(span).input.blur();
},
done: expectDone("Test Value", true, testAdvanceCharCommit)
});
@ -76,7 +77,7 @@ function testAdvanceCharCommit()
element: span,
advanceChars: ":",
start: function() {
let input = span.inplaceEditor.input;
let input = inplaceEditor(span).input;
for each (let ch in "Test:") {
EventUtils.sendChar(ch);
}
@ -94,7 +95,7 @@ function testEscapeCancel()
element: span,
initial: "initial text",
start: function() {
span.inplaceEditor.input.value = "Test Value";
inplaceEditor(span).input.value = "Test Value";
EventUtils.sendKey("escape");
},
done: expectDone("initial text", false, finishTest)

Просмотреть файл

@ -7,6 +7,7 @@ Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let inplaceEditor = tempScope._getInplaceEditorForSpan;
let doc;
let ruleDialog;
@ -15,9 +16,9 @@ let ruleView;
function waitForEditorFocus(aParent, aCallback)
{
aParent.addEventListener("focus", function onFocus(evt) {
if (evt.target.inplaceEditor) {
if (inplaceEditor(evt.target)) {
aParent.removeEventListener("focus", onFocus, true);
let editor = evt.target.inplaceEditor;
let editor = inplaceEditor(evt.target);
executeSoon(function() {
aCallback(editor);
});
@ -83,7 +84,7 @@ function testCancelNew()
let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
let input = aEditor.input;
waitForEditorBlur(aEditor, function () {
ok(!gRuleViewChanged, "Shouldn't get a change event after a cancel.");
@ -104,7 +105,7 @@ function testCreateNew()
// Create a new property.
let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
let input = aEditor.input;
input.value = "background-color";
@ -113,7 +114,7 @@ function testCreateNew()
is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property.");
is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
let textProp = elementRuleEditor.rule.textProps[0];
is(aEditor, textProp.editor.valueSpan.inplaceEditor, "Should be editing the value span now.");
is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
aEditor.input.value = "#XYZ";
waitForEditorBlur(aEditor, function() {
@ -137,12 +138,12 @@ function testEditProperty()
let idRuleEditor = ruleView.element.children[1]._ruleEditor;
let propEditor = idRuleEditor.rule.textProps[0].editor;
waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
is(propEditor.nameSpan.inplaceEditor, aEditor, "Next focused editor should be the name editor.");
is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
let input = aEditor.input;
waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
expectChange();
input = aEditor.input;
is(propEditor.valueSpan.inplaceEditor, aEditor, "Focus should have moved to the value.");
is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
waitForEditorBlur(aEditor, function() {
expectChange();

Просмотреть файл

@ -5,6 +5,9 @@
// Test that focus doesn't leave the style editor when adding a property
// (bug 719916)
let tempScope = {};
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let inplaceEditor = tempScope._getInplaceEditorForSpan;
let doc;
let stylePanel;
@ -27,9 +30,9 @@ function waitForRuleView(aCallback)
function waitForEditorFocus(aParent, aCallback)
{
aParent.addEventListener("focus", function onFocus(evt) {
if (evt.target.inplaceEditor) {
if (inplaceEditor(evt.target)) {
aParent.removeEventListener("focus", onFocus, true);
let editor = evt.target.inplaceEditor;
let editor = inplaceEditor(evt.target);
executeSoon(function() {
aCallback(editor);
});

Просмотреть файл

@ -7,6 +7,7 @@ Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let inplaceEditor = tempScope._getInplaceEditorForSpan;
let doc;
let ruleDialog;
@ -15,9 +16,9 @@ let ruleView;
function waitForEditorFocus(aParent, aCallback)
{
aParent.addEventListener("focus", function onFocus(evt) {
if (evt.target.inplaceEditor) {
if (inplaceEditor(evt.target)) {
aParent.removeEventListener("focus", onFocus, true);
let editor = evt.target.inplaceEditor;
let editor = inplaceEditor(evt.target);
executeSoon(function() {
aCallback(editor);
});
@ -83,7 +84,7 @@ function testCancelNew()
let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
let input = aEditor.input;
waitForEditorBlur(aEditor, function () {
ok(!gRuleViewChanged, "Shouldn't get a change event after a cancel.");
@ -104,7 +105,7 @@ function testCreateNew()
// Create a new property.
let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
let input = aEditor.input;
input.value = "background-color";
@ -113,7 +114,7 @@ function testCreateNew()
is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property.");
is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
let textProp = elementRuleEditor.rule.textProps[0];
is(aEditor, textProp.editor.valueSpan.inplaceEditor, "Should be editing the value span now.");
is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
aEditor.input.value = "purple";
waitForEditorBlur(aEditor, function() {
@ -137,12 +138,12 @@ function testEditProperty()
let idRuleEditor = ruleView.element.children[1]._ruleEditor;
let propEditor = idRuleEditor.rule.textProps[0].editor;
waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
is(propEditor.nameSpan.inplaceEditor, aEditor, "Next focused editor should be the name editor.");
is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
let input = aEditor.input;
waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
expectChange();
input = aEditor.input;
is(propEditor.valueSpan.inplaceEditor, aEditor, "Focus should have moved to the value.");
is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
waitForEditorBlur(aEditor, function() {
expectChange();

Просмотреть файл

@ -173,6 +173,7 @@
@BINPATH@/components/dom_json.xpt
@BINPATH@/components/dom_power.xpt
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_settings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@ -419,6 +420,8 @@
@BINPATH@/components/TelemetryPing.manifest
@BINPATH@/components/messageWakeupService.js
@BINPATH@/components/messageWakeupService.manifest
@BINPATH@/components/SettingsManager.js
@BINPATH@/components/SettingsManager.manifest
@BINPATH@/components/Webapps.js
@BINPATH@/components/Webapps.manifest

Просмотреть файл

@ -103,7 +103,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
; Must be inserted before other macros that use logging
!insertmacro _LoggingCommon
!insertmacro AddDDEHandlerValues
!insertmacro AddDisabledDDEHandlerValues
!insertmacro ChangeMUIHeaderImage
!insertmacro CheckForFilesInUse
!insertmacro CleanUpdatesDir
@ -352,17 +352,15 @@ Section "-Application" APP_IDX
${SetUninstallKeys}
; On install always add the FirefoxHTML and FirefoxURL keys.
; An empty string is used for the 5th param because FirefoxHTML and FirefoxURL
; are not protocol handlers.
; An empty string is used for the 5th param because FirefoxHTML is not a
; protocol handler.
${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
StrCpy $3 "$\"%1$\",,0,0,,,,"
StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} Document" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
"${AppRegName} Document" ""
${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \
"true"
; The following keys should only be set if we can write to HKLM
${If} $TmpVal == "HKLM"

Просмотреть файл

@ -79,7 +79,7 @@
${GetLongPath} "$0" $0
${EndIf}
${If} "$0" == "$INSTDIR"
${SetStartMenuInternet}
${SetStartMenuInternet} ; Does not use SHCTX
${EndIf}
ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
@ -156,12 +156,12 @@
!define PostUpdate "!insertmacro PostUpdate"
!macro SetAsDefaultAppGlobal
${RemoveDeprecatedKeys}
${RemoveDeprecatedKeys} ; Does not use SHCTX
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
${SetHandlers}
${SetStartMenuInternet}
${FixShellIconHandler}
${SetHandlers} ; Uses SHCTX
${SetStartMenuInternet} ; Does not use SHCTX
${FixShellIconHandler} ; Does not use SHCTX
${ShowShortcuts}
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
WriteRegStr HKLM "Software\Clients\StartMenuInternet" "" "$R9"
@ -306,7 +306,7 @@
${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
StrCpy $0 "SOFTWARE\Classes"
StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
; Associate the file handlers with FirefoxHTML
ReadRegStr $6 SHCTX "$0\.htm" ""
@ -340,25 +340,20 @@
WriteRegStr SHCTX "$0\.webm" "" "FirefoxHTML"
${EndIf}
StrCpy $3 "$\"%1$\",,0,0,,,,"
; An empty string is used for the 5th param because FirefoxHTML is not a
; protocol handler
${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
"${AppRegName} HTML Document" ""
${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \
"true"
; An empty string is used for the 4th & 5th params because the following
; protocol handlers already have a display name and the additional keys
; required for a protocol handler.
${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" ""
${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" ""
${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" ""
!macroend
!define SetHandlers "!insertmacro SetHandlers"
@ -567,8 +562,7 @@
!macro UpdateProtocolHandlers
; Store the command to open the app with an url in a register for easy access.
${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
StrCpy $3 "$\"%1$\",,0,0,,,,"
StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
; Only set the file and protocol handlers if the existing one under HKCR is
; for this install location.
@ -577,32 +571,32 @@
${If} "$R9" == "true"
; An empty string is used for the 5th param because FirefoxHTML is not a
; protocol handler.
${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
"${AppRegName} HTML Document" ""
${EndIf}
${IsHandlerForInstallDir} "FirefoxURL" $R9
${If} "$R9" == "true"
${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" \
"${AppRegName} URL" "true"
${EndIf}
; An empty string is used for the 4th & 5th params because the following
; protocol handlers already have a display name and the additional keys
; required for a protocol handler.
${IsHandlerForInstallDir} "ftp" $R9
${If} "$R9" == "true"
${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" ""
${EndIf}
${IsHandlerForInstallDir} "http" $R9
${If} "$R9" == "true"
${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" ""
${EndIf}
${IsHandlerForInstallDir} "https" $R9
${If} "$R9" == "true"
${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \
"${DDEApplication}" "$3" "WWW_OpenURL"
${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" ""
${EndIf}
!macroend
!define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers"
@ -1164,11 +1158,13 @@ Function SetAsDefaultAppUser
; b) is not a member of the administrators group and chooses to elevate
${ElevateUAC}
${SetStartMenuInternet}
${SetStartMenuInternet} ; Does not use SHCTX
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
${FixShellIconHandler}
${RemoveDeprecatedKeys}
${FixClassKeys} ; Does not use SHCTX
${FixShellIconHandler} ; Does not use SHCTX
${RemoveDeprecatedKeys} ; Does not use SHCTX
ClearErrors
${GetParameters} $0

Просмотреть файл

@ -92,7 +92,7 @@ Var MaintCertKey
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
VIAddVersionKey "OriginalFilename" "helper.exe"
!insertmacro AddDDEHandlerValues
!insertmacro AddDisabledDDEHandlerValues
!insertmacro CleanVirtualStore
!insertmacro ElevateUAC
!insertmacro GetLongPath

Просмотреть файл

@ -341,21 +341,6 @@ webapps.install.accesskey = I
#LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
# Keyword.URL reset prompt
# LOCALIZATION NOTE (keywordPrompt.message):
# - %1$S is brandShortName
# - %2$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL
# - %3$S is the name of the default search engine (e.g. "Google")
keywordPrompt.message = %1$S is using '%2$S' for searches from the location bar. Would you like to restore the default search (%3$S)?
# LOCALIZATION NOTE (keywordPrompt.yesButton): %1$S is the name of the default search engine
keywordPrompt.yesButton = Yes, use %1$S
keywordPrompt.yesButton.accessKey = Y
# LOCALIZATION NOTE (keywordPrompt.noButton): %1$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL
keywordPrompt.noButton = No, continue using '%1$S'
keywordPrompt.noButton.accessKey = N
# Telemetry opt-out prompt for Aurora and Nightly
# LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
# brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.

Просмотреть файл

@ -102,7 +102,7 @@ if [ "$MOZ_SAFE_BROWSING" ]; then
"
fi
if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
if [ "$MAKENSISU" ]; then
add_makefiles "
browser/installer/windows/Makefile
"

Просмотреть файл

@ -1,106 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
let EXPORTED_SYMBOLS = [ "KeywordURLResetPrompter" ];
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
const KEYWORD_PROMPT_REV = 1;
let KeywordURLResetPrompter = {
get shouldPrompt() {
let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
let declinedRev;
try {
declinedRev = Services.prefs.getIntPref("browser.keywordURLPromptDeclined");
} catch (ex) {}
return keywordURLUserSet && declinedRev != KEYWORD_PROMPT_REV;
},
prompt: function KeywordURLResetPrompter_prompt(win, keywordURI) {
let tabbrowser = win.gBrowser;
let notifyBox = tabbrowser.getNotificationBox();
let existingNotification = notifyBox.getNotificationWithValue("keywordURL-reset");
if (existingNotification)
return;
// Find the name/URI of this build's original default engine.
// XXX: Can't use originalDefaultEngine getter here, because that doesn't
// use the default pref branch.
let defaultURI;
let defaultEngine;
try {
let defaultPB = Services.prefs.getDefaultBranch(null);
let defaultName = defaultPB.getComplexValue("browser.search.defaultenginename",
Ci.nsIPrefLocalizedString).data;
defaultEngine = Services.search.getEngineByName(defaultName);
defaultURI = defaultEngine.getSubmission("foo").uri;
} catch (ex) {
// Something went horribly wrong! bail out
return;
}
// If the user-set value has the same base domain as the default, don't
// prompt.
let keywordBaseDomain;
try {
keywordBaseDomain = Services.eTLD.getBaseDomain(keywordURI);
if (keywordBaseDomain == Services.eTLD.getBaseDomain(defaultURI))
return;
} catch (ex) {}
if (!keywordBaseDomain)
return;
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
let brandShortName = brandBundle.GetStringFromName("brandShortName");
let browserBundle = win.gNavigatorBundle;
let msg = browserBundle.getFormattedString("keywordPrompt.message",
[brandShortName, keywordBaseDomain,
defaultEngine.name]);
let buttons = [
{
label: browserBundle.getFormattedString("keywordPrompt.yesButton",
[defaultEngine.name]),
accessKey: browserBundle.getString("keywordPrompt.yesButton.accessKey"),
popup: null,
callback: function(aNotificationBar, aButton) {
Services.prefs.clearUserPref("keyword.URL");
Services.prefs.clearUserPref("browser.search.defaultenginename");
try {
// If the currently loaded URI still has the same base domain as the
// keyword URI (this is used as a rough approximation of whether the
// user is still seeing search results as opposed to having clicked
// on a result link), load the default engine's searchForm URL so
// that they can re-do their search.
let currentBaseDomain = Services.eTLD.getBaseDomain(tabbrowser.currentURI);
if (currentBaseDomain == keywordBaseDomain)
tabbrowser.loadURI(defaultEngine.searchForm);
} catch (ex) {}
}
},
{
label: browserBundle.getFormattedString("keywordPrompt.noButton",
[keywordBaseDomain]),
accessKey: browserBundle.getString("keywordPrompt.noButton.accessKey"),
popup: null,
callback: function(aNotificationBar, aButton) {
Services.prefs.setIntPref("browser.keywordURLPromptDeclined", KEYWORD_PROMPT_REV);
}
}
];
let notification = notifyBox.appendNotification(msg, "keywordURL-reset", null, notifyBox.PRIORITY_WARNING_HIGH, buttons);
notification.setAttribute("hideclose", true);
// stick around for a few page loads in case there are redirects involved
notification.persistence = 3;
}
}

Просмотреть файл

@ -52,7 +52,6 @@ EXTRA_JS_MODULES = \
NewTabUtils.jsm \
offlineAppCache.jsm \
TelemetryTimestamps.jsm \
KeywordURLResetPrompter.jsm \
webappsUI.jsm \
$(NULL)

Просмотреть файл

@ -46,7 +46,6 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_NetworkPrioritizer.js \
browser_TelemetryTimestamps.js \
browser_keywordURLReset.js \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)

Просмотреть файл

@ -1,110 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
let newTab = gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
registerCleanupFunction(function () {
gBrowser.removeTab(newTab);
Services.prefs.clearUserPref("keyword.URL");
Services.prefs.clearUserPref("browser.search.defaultenginename");
});
function onKeywordPrefUse(cb) {
Services.obs.addObserver(function obs() {
Services.obs.removeObserver(obs, "defaultURIFixup-using-keyword-pref");
executeSoon(function () {
let nbox = gBrowser.getNotificationBox();
let notification = nbox.getNotificationWithValue("keywordURL-reset");
cb(notification);
});
}, "defaultURIFixup-using-keyword-pref", false);
}
function testQuery(cb) {
onKeywordPrefUse(cb);
gURLBar.focus();
gURLBar.value = "foo bar";
gURLBar.handleCommand();
}
function setKeywordURL(value) {
Services.prefs.setCharPref("keyword.URL", value);
let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
is(keywordURI.spec, value + "foo+bar", "keyword.URL was set to " + value);
}
// Before modifying any prefs, get a submission object for this build's
// actual default engine for verification of the "Reset" functionality.
let originalDefaultEngine = Services.search.originalDefaultEngine;
let defaultSubmission = originalDefaultEngine.getSubmission("foo bar", "application/x-moz-keywordsearch");
if (!defaultSubmission)
defaultSubmission = originalDefaultEngine.getSubmission("foo bar");
var tests = [
{
name: "similar URL that shouldn't trigger prompt",
setup: function () {
setKeywordURL(defaultSubmission.uri.prePath + "/othersearch");
},
check: function (notification) {
ok(!notification, "didn't get a search reset notification");
}
},
{
name: "URL that should trigger prompt",
setup: function () {
// First clear any values from the previous test so that we can verify
// that the dummy default engine we're adding below has an effect.
Services.prefs.clearUserPref("keyword.URL");
// Add a dummy "default engine" to verify that the "reset" actually
// resets the originalDefaultEngine too (and not just keyword.URL)
Services.search.addEngineWithDetails("TestEngine", "", "", "", "GET", "http://mochi.test/test?q={searchTerms}");
Services.prefs.setCharPref("browser.search.defaultenginename", "TestEngine");
// Check that it was added successfully
let engine = Services.search.getEngineByName("TestEngine");
ok(engine, "added engine successfully");
registerCleanupFunction(function () {
Services.search.removeEngine(engine);
});
is(Services.search.originalDefaultEngine, engine, "engine is now the originalDefaultEngine");
let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
is(keywordURI.spec, "http://mochi.test/test?q=foo+bar", "default engine affects keywordToURI");
setKeywordURL("http://invalid.foo/search/");
},
check: function (notification) {
ok(notification, "got a search reset notification");
// Press the "reset" button
notification.getElementsByTagName("button").item(0).click();
// Check that the reset worked
let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
is(keywordURI.spec, defaultSubmission.uri.spec,
"keyword.URL came from original default engine after reset");
}
}
];
function nextTest() {
let test = tests.shift();
if (!test) {
finish();
return;
}
info("Running test: " + test.name);
test.setup();
testQuery(function (notification) {
test.check(notification);
executeSoon(nextTest);
});
}
nextTest();
}

Просмотреть файл

@ -66,6 +66,10 @@
-moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
}
#navigator-toolbox:not(:-moz-lwtheme)::after {
background-color: #aabccf;
}
#navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme) {
border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3);
@ -210,7 +214,7 @@
#main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar:not(:-moz-lwtheme),
#main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme),
#main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
#main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
#main-window[sizemode=normal][disablechrome] #navigator-toolbox[tabsontop=true]:not(:-moz-lwtheme)::after {
border-top: 1px solid @toolbarShadowColor@;
border-top-left-radius: 2.5px;
border-top-right-radius: 2.5px;
@ -244,7 +248,7 @@
}
/* Rounded corners for when chrome is disabled */
#main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
#main-window[sizemode=normal][disablechrome] #navigator-toolbox[tabsontop=true]:not(:-moz-lwtheme)::after {
visibility: visible;
background-color: @customToolbarColor@;
background-image: -moz-linear-gradient(@toolbarHighlight@, @toolbarHighlight@);

Просмотреть файл

@ -1148,7 +1148,7 @@ toolbar[mode=full] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
/* ::::: fullscreen window controls ::::: */
#TabsToolbar > #window-controls {
#window-controls {
-moz-margin-start: 4px;
}

Просмотреть файл

@ -41,6 +41,7 @@ package @ANDROID_PACKAGE_NAME@;
public interface Assert {
void dumpLog(String message);
void dumpLog(String message, Throwable t);
void setLogFile(String filename);
void setTestName(String testName);

Просмотреть файл

@ -66,6 +66,11 @@ public class FennecMochitestAssert implements Assert {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
}
/** Write information to a logfile and logcat */
public void dumpLog(String message, Throwable t) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
}
/** Set the filename used for dumpLog. */
public void setLogFile(String filename) {
FennecNativeDriver.setLogFile(filename);

Просмотреть файл

@ -41,7 +41,6 @@ package @ANDROID_PACKAGE_NAME@;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileReader;
@ -49,6 +48,7 @@ import java.io.FileWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;
@ -459,41 +459,48 @@ public class FennecNativeDriver implements Driver {
}
public static void log(LogLevel level, String message) {
log(level, message, null);
}
public static void log(LogLevel level, Throwable t) {
log(level, null, t);
}
public static void log(LogLevel level, String message, Throwable t) {
if (mLogFile == null) {
assert(false);
}
if (level.isEnabled(mLogLevel)) {
File file = new File(mLogFile);
BufferedWriter bw = null;
PrintWriter pw = null;
try {
bw = new BufferedWriter(new FileWriter(mLogFile, true));
bw.write(message);
bw.newLine();
} catch(IOException e) {
pw = new PrintWriter(new FileWriter(mLogFile, true));
if (message != null) {
pw.println(message);
}
if (t != null) {
t.printStackTrace(pw);
}
} catch (IOException ioe) {
Log.e("Robocop", "exception with file writer on: " + mLogFile);
} finally {
try {
if (bw != null) {
bw.flush();
bw.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
pw.close();
}
// PrintWriter doesn't throw IOE but sets an error flag instead,
// so check for that
if (pw.checkError()) {
Log.e("Robocop", "exception with file writer on: " + mLogFile);
}
}
if (level == LogLevel.LOG_LEVEL_INFO) {
Log.i("Robocop", message);
Log.i("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_DEBUG) {
Log.d("Robocop", message);
Log.d("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_WARN) {
Log.w("Robocop", message);
Log.w("Robocop", message, t);
} else if (level == LogLevel.LOG_LEVEL_ERROR) {
Log.e("Robocop", message);
Log.e("Robocop", message, t);
}
}
}

Просмотреть файл

@ -49,6 +49,11 @@ public class FennecTalosAssert implements Assert {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
}
/** Write information to a logfile and logcat */
public void dumpLog(String message, Throwable t) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
}
/**
* Set the filename used for dumpLog.
*/

Просмотреть файл

@ -127,8 +127,8 @@ classes.dex: $(_JAVA_TESTS)
$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
robocop.ap_: AndroidManifest.xml
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./
robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
robocop.apk: robocop.ap_ classes.dex
cp $(TESTPATH)/robocop.ini robocop.ini

Просмотреть файл

@ -265,9 +265,9 @@ build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
stage1_tool_inst_dir = stage1_dir + '/inst'
stage2_dir = build_dir + '/stage2'
build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
"CXX" : stage1_tool_inst_dir + "/bin/g++",
"AR" : stage1_tool_inst_dir + "/bin/ar",
build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
"CC" : "gcc -fgnu89-inline",
"CXX" : "g++",
"RANLIB" : "true" },
stage2_dir, False)

Просмотреть файл

@ -1623,13 +1623,15 @@ if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/$ANDROID_CPU_ARCH"
STLPORT_LIBS="-lstdc++"
elif test -e "$android_ndk/sources/cxx-stl/stlport/src/iostream.cpp" ; then
if test -e "$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
else
AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
fi
STLPORT_SOURCES="$android_ndk/sources/cxx-stl/stlport"
STLPORT_CPPFLAGS="-I$_objdir/build/stlport -I$android_ndk/sources/cxx-stl/stlport/stlport"
STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
STLPORT_LIBS="-lstlport_static"
elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a" ; then
STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport"
STLPORT_LDFLAGS="-L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH"
STLPORT_LIBS="-lstlport_static"
elif test "$target" != "arm-android-eabi"; then
dnl fail if we're not building with NDKr4
@ -4967,6 +4969,15 @@ then
if test -z "$QTDIR"; then
PKG_CHECK_MODULES(MOZ_QT, QtGui QtNetwork QtCore QtOpenGL)
PKG_CHECK_MODULES(MOZ_QT5, QtWidgets QtMultimedia QtPrintSupport QtQuick1,
MOZ_ENABLE_QT5=1,
MOZ_ENABLE_QT5=)
if test "$MOZ_ENABLE_QT5"; then
echo "Using qt5"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $MOZ_QT5_CFLAGS"
MOZ_QT_LIBS="$MOZ_QT_LIBS $MOZ_QT5_LIBS"
fi
AC_CHECK_PROGS(HOST_MOC, $MOC moc, "")
AC_CHECK_PROGS(HOST_RCC, $RCC rcc, "")
else
@ -4979,8 +4990,19 @@ then
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtCore"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtNetwork"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtXml"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtDeclarative"
HOST_MOC="$QTDIR/bin/moc"
HOST_RCC="$QTDIR/bin/rcc"
# QtWidgets was introduced only in Qt5
if test -d $QTDIR/include/QtWidgets; then
echo "Using qt5"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtWidgets"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtMultimedia"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtPrintSupport"
MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtQuick1"
MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtWidgets -lQtMultimedia -lQtPrintSupport -lQtQuick1"
fi
fi
if test -z "$HOST_MOC"; then
AC_MSG_ERROR([No acceptable moc preprocessor found. Qt SDK is not installed or --with-qt is
@ -6297,29 +6319,38 @@ dnl ========================================================
dnl Installer
dnl ========================================================
dnl Abort Windows build if the required major version and
dnl minimum minor version of Unicode NSIS isn't in the path.
dnl minimum minor version of Unicode NSIS isn't in the path
dnl (unless in case of cross compiling, for which Unicode
dnl is not yet sufficient).
if test "$OS_ARCH" = "WINNT"; then
REQ_NSIS_MAJOR_VER=2
MIN_NSIS_MINOR_VER=33
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
AC_MSG_RESULT([yes])
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" || \
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
if test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
else
MAKENSISU=
fi
fi
elif test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
else
MAKENSISU=
fi
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" ||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
fi
AC_MSG_RESULT([yes])
fi
AC_MSG_CHECKING([for tar archiver])
@ -6436,14 +6467,6 @@ MOZ_ARG_DISABLE_BOOL(tests,
ENABLE_TESTS=,
ENABLE_TESTS=1 )
dnl ========================================================
dnl Marionette
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(marionette,
[ --enable-marionette Enable Marionette for remote testing and control],
ENABLE_MARIONETTE=1,
ENABLE_MARIONETTE)
dnl ========================================================
dnl parental controls (for Windows Vista)
dnl ========================================================

Просмотреть файл

@ -1421,7 +1421,11 @@ public:
* If this document is a static clone, this returns the original
* document.
*/
nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
nsIDocument* GetOriginalDocument()
{
MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
return mOriginalDocument;
}
/**
* Called by nsParser to preload images. Can be removed and code moved

Просмотреть файл

@ -19,6 +19,7 @@
* Contributor(s):
* Sid Stamm <sid@mozilla.com>
* Brandon Sterne <bsterne@mozilla.com>
* Ian Melven <imelven@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
@ -301,7 +302,7 @@ ContentSecurityPolicy.prototype = {
var failure = function(aEvt) {
if (req.readyState == 4 && req.status != 200) {
CSPError("Failed to send report to " + reportURI);
CSPError("Failed to send report to " + uris[i]);
}
};
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
@ -313,6 +314,10 @@ ContentSecurityPolicy.prototype = {
req.upload.addEventListener("error", failure, false);
req.upload.addEventListener("abort", failure, false);
// we need to set an nsIChannelEventSink on the XHR object
// so we can tell it to not follow redirects when posting the reports
req.channel.notificationCallbacks = new CSPReportRedirectSink();
req.send(JSON.stringify(report));
CSPdebug("Sent violation report to " + uris[i]);
} catch(e) {
@ -494,4 +499,54 @@ ContentSecurityPolicy.prototype = {
},
};
// The POST of the violation report (if it happens) should not follow
// redirects, per the spec. hence, we implement an nsIChannelEventSink
// with an object so we can tell XHR to abort if a redirect happens.
function CSPReportRedirectSink() {
}
CSPReportRedirectSink.prototype = {
QueryInterface: function requestor_qi(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIInterfaceRequestor) ||
iid.equals(Ci.nsIChannelEventSink))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
// nsIInterfaceRequestor
getInterface: function requestor_gi(iid) {
if (iid.equals(Ci.nsIChannelEventSink))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
// nsIChannelEventSink
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
flags, callback) {
CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
" failed, as a redirect occurred");
// cancel the old channel so XHR failure callback happens
oldChannel.cancel(Cr.NS_ERROR_ABORT);
// notify an observer that we have blocked the report POST due to a redirect,
// used in testing, do this async since we're in an async call now to begin with
Services.tm.mainThread.dispatch(
function() {
observerSubject = Cc["@mozilla.org/supports-cstring;1"]
.createInstance(Ci.nsISupportsCString);
observerSubject.data = oldChannel.URI.asciiSpec;
Services.obs.notifyObservers(observerSubject,
CSP_VIOLATION_TOPIC,
"denied redirect while sending violation report");
}, Ci.nsIThread.DISPATCH_NORMAL);
// throw to stop the redirect happening
throw Cr.NS_BINDING_REDIRECTED;
}
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]);

Просмотреть файл

@ -378,3 +378,29 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
static PLDHashOperator
TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
{
if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
JSTracer* trc = static_cast<JSTracer *>(aClosure);
JS_CALL_OBJECT_TRACER(trc, global, "active window global");
}
}
return PL_DHASH_NEXT;
}
void
mozilla::dom::TraceBlackJS(JSTracer* aTrc)
{
if (!nsCCUncollectableMarker::sGeneration) {
return;
}
// Mark globals of active windows black.
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (windowsById) {
windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
}
}

Просмотреть файл

@ -38,6 +38,8 @@
#include "nsIObserver.h"
#include "nsCycleCollectionParticipant.h"
struct JSTracer;
class nsCCUncollectableMarker : public nsIObserver
{
NS_DECL_ISUPPORTS
@ -56,10 +58,10 @@ class nsCCUncollectableMarker : public nsIObserver
return aGeneration && aGeneration == sGeneration;
}
static bool InGeneration(nsCycleCollectionTraversalCallback &cb,
static bool InGeneration(nsCycleCollectionTraversalCallback& aCb,
PRUint32 aGeneration)
{
return InGeneration(aGeneration) && !cb.WantAllTraces();
return InGeneration(aGeneration) && !aCb.WantAllTraces();
}
static PRUint32 sGeneration;
@ -68,3 +70,9 @@ private:
nsCCUncollectableMarker() {}
};
namespace mozilla {
namespace dom {
void TraceBlackJS(JSTracer* aTrc);
}
}

Просмотреть файл

@ -2547,6 +2547,7 @@ void
nsDocument::StopDocumentLoad()
{
if (mParser) {
mParserAborted = true;
mParser->Terminate();
}
}
@ -8086,9 +8087,12 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
nsCOMPtr<nsIDocument> clonedDoc;
if (NS_SUCCEEDED(rv)) {
clonedDoc = do_QueryInterface(clonedNode);
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
if (clonedDOMDoc) {
clonedDoc->mOriginalDocument = this;
if (clonedDoc) {
if (IsStaticDocument()) {
clonedDoc->mOriginalDocument = mOriginalDocument;
} else {
clonedDoc->mOriginalDocument = this;
}
PRInt32 sheetsCount = GetNumberOfStyleSheets();
for (PRInt32 i = 0; i < sheetsCount; ++i) {
nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));

Просмотреть файл

@ -1188,6 +1188,10 @@ protected:
// our presshell. This is used to handle flush reentry correctly.
bool mInFlush:1;
// Parser aborted. True if the parser of this document was forcibly
// terminated instead of letting it finish at its own pace.
bool mParserAborted:1;
PRUint8 mXMLDeclarationBits;
nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;

Просмотреть файл

@ -1935,7 +1935,8 @@ GK_ATOM(VolumeUp, "VolumeUp")
GK_ATOM(VolumeDown, "VolumeDown")
GK_ATOM(Menu, "Menu")
// Smooth scroll profiles
// Smooth scroll events origins
GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse)
GK_ATOM(pixels, "pixels")
GK_ATOM(lines, "lines")
GK_ATOM(pages, "pages")

Просмотреть файл

@ -314,42 +314,32 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
mCurrentRequestNeedsResetAnimation = false;
}
// We just loaded all the data we're going to get. If we haven't done an
// initial paint, we want to make sure the image starts decoding for 2
// reasons:
// We just loaded all the data we're going to get. If we're visible and
// haven't done an initial paint (*), we want to make sure the image starts
// decoding immediately, for two reasons:
//
// 1) This image is sitting idle but might need to be decoded as soon as we
// start painting, in which case we've wasted time.
//
// 2) We want to block onload until all visible images are decoded. We do this
// by blocking onload until all in progress decodes get at least one frame
// by blocking onload until all in-progress decodes get at least one frame
// decoded. However, if all the data comes in while painting is suppressed
// (ie, before the initial paint delay is finished), we fire onload without
// doing a paint first. This means that decode-on-draw images don't start
// decoding, so we can't wait for them to finish. See bug 512435.
//
// (*) IsPaintingSuppressed returns false if we haven't gotten the initial
// reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
// It's possible for painting to be suppressed for reasons other than the
// initial paint delay (for example, being in the bfcache), but we probably
// aren't loading images in those situations.
// We can only do this if we have a presshell
nsIDocument* doc = GetOurDocument();
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
if (shell) {
// We need to figure out whether to kick off decoding
bool doRequestDecode = false;
if (shell && shell->IsVisible() &&
(!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
// If we haven't got the initial reflow yet, IsPaintingSuppressed actually
// returns false
if (!shell->DidInitialReflow())
doRequestDecode = true;
// Figure out if painting is suppressed. Note that it's possible for painting
// to be suppressed for reasons other than the initial paint delay (for
// example - being in the bfcache), but we probably aren't loading images in
// those situations.
if (shell->IsPaintingSuppressed())
doRequestDecode = true;
// If we're requesting a decode, do it
if (doRequestDecode)
mCurrentRequest->RequestDecode();
mCurrentRequest->RequestDecode();
}
// Fire the appropriate DOM event.

Просмотреть файл

@ -2768,10 +2768,13 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
// Create our listener
nsCOMPtr<nsIStreamListener> listener = this;
if (mState & XML_HTTP_REQUEST_MULTIPART) {
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
listener = new nsMultipartProxyListener(listener);
if (!listener) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
}
// Blocking gets are common enough out of XHR that we should mark

Просмотреть файл

@ -572,6 +572,12 @@ _TEST_FILES2 = \
test_bug737612.html \
test_bug738108.html \
test_bug366944.html \
test_bug650386_redirect_301.html \
test_bug650386_redirect_302.html \
test_bug650386_redirect_303.html \
test_bug650386_redirect_307.html \
file_bug650386_content.sjs \
file_bug650386_report.sjs \
$(NULL)
_CHROME_FILES = \

Просмотреть файл

@ -0,0 +1,37 @@
// SJS file for tests for bug650386, serves file_bug650386_content.html
// with a CSP that will trigger a violation and that will report it
// to file_bug650386_report.sjs
//
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
// returned/type of redirect to do comes from the query string
// parameter passed in from the test_bug650386_* files and then also
// uses that value in the report-uri parameter of the CSP
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache", false);
// this gets used in the CSP as part of the report URI.
var redirect = request.queryString;
if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) {
// if we somehow got some bogus redirect code here,
// do a 302 redirect to the same URL as the report URI
// redirects to - this will fail the test.
var loc = "http://example.com/some/fake/path";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", loc, false);
return;
}
var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect;
response.setHeader("X-Content-Security-Policy", csp, false);
// the actual file content.
// this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
// specified by the CSP string above.
var content = "<!DOCTYPE HTML><html><body><img src = \"http://some.other.domain.example.com\"></body></html>";
response.write(content);
return;
}

Просмотреть файл

@ -0,0 +1,16 @@
// SJS file for tests for bug650386, this serves as CSP violation report target
// and issues a redirect, to make sure the browser does not post to the target
// of the redirect, per CSP spec.
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
// returned/type of redirect to do comes from the query string
// parameter
function handleRequest(request, response) {
response.setHeader("Cache-Control", "no-cache", false);
var redirect = request.queryString;
var loc = "http://example.com/some/fake/path";
response.setStatusLine("1.1", redirect, "Found");
response.setHeader("Location", loc, false);
return;
}

Просмотреть файл

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
Test that CSP violation reports are not sent when a 301 redirect is encountered
-->
<head>
<title>Test for Bug 650386</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id = "content_iframe"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 650386 **/
// This is used to watch the redirect of the report POST get blocked
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
SpecialPowers.addObserver(this, "http-on-modify-request", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "http-on-modify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
if (asciiSpec == "http://example.com/some/fake/path")
window.done(false);
}
if(topic === "csp-on-violate-policy") {
// something was blocked, but we are looking specifically for the redirect being blocked
if (data == "denied redirect while sending violation report")
window.done(true);
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
SpecialPowers.removeObserver(this, "http-on-modify-request");
}
}
window.examiner = new examiner();
// result == true if we saw the redirect blocked notify, false if we saw the post
// to the redirect target go out
window.done = function(result) {
ok(result, "a 301 redirect when posting violation report should be blocked");
// clean up observers and finish the test
window.examiner.remove();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?301';
</script>
</pre>
</body>
</html>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше