зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i.
This commit is contained in:
Коммит
afc7a3b381
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2: */
|
||||
/* vim: set expandtab shiftwidth=2 tabstop=2: */
|
||||
/* 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/. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2: */
|
||||
/* vim: set expandtab shiftwidth=2 tabstop=2: */
|
||||
/* 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/. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2: */
|
||||
/* vim: set expandtab shiftwidth=2 tabstop=2: */
|
||||
/* 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/. */
|
||||
|
|
|
@ -238,20 +238,9 @@ ARIAGridAccessible::SelectedRowCount()
|
|||
return count;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ARIAGridAccessible::GetSelectedCells(nsIArray** aCells)
|
||||
void
|
||||
ARIAGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCells);
|
||||
*aCells = nsnull;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> selCells =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AccIterator rowIter(this, filters::GetRow);
|
||||
|
||||
Accessible* row = nsnull;
|
||||
|
@ -261,19 +250,16 @@ ARIAGridAccessible::GetSelectedCells(nsIArray** aCells)
|
|||
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
while ((cell = cellIter.Next()))
|
||||
selCells->AppendElement(static_cast<nsIAccessible *>(cell), false);
|
||||
aCells->AppendElement(cell);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((cell = cellIter.Next())) {
|
||||
if (nsAccUtils::IsARIASelected(cell))
|
||||
selCells->AppendElement(static_cast<nsIAccessible *>(cell), false);
|
||||
aCells->AppendElement(cell);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aCells = selCells);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
virtual PRUint32 SelectedCellCount();
|
||||
virtual PRUint32 SelectedColCount();
|
||||
virtual PRUint32 SelectedRowCount();
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells);
|
||||
virtual void SelectedCellIndices(nsTArray<PRUint32>* aCells);
|
||||
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols);
|
||||
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows);
|
||||
|
|
|
@ -134,7 +134,7 @@ public:
|
|||
/**
|
||||
* Get the set of selected cells.
|
||||
*/
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells) {}
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells) = 0;
|
||||
|
||||
/**
|
||||
* Get the set of selected cell indices.
|
||||
|
|
|
@ -610,54 +610,37 @@ HTMLTableAccessible::SelectedRowCount()
|
|||
return count;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTableAccessible::GetSelectedCells(nsIArray** aCells)
|
||||
void
|
||||
HTMLTableAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCells);
|
||||
*aCells = nsnull;
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
nsresult rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 columnCount = 0;
|
||||
rv = GetColumnCount(&columnCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRUint32 rowCount = RowCount(), colCount = ColCount();
|
||||
|
||||
nsITableLayout *tableLayout = GetTableLayout();
|
||||
NS_ENSURE_STATE(tableLayout);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> selCells =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!tableLayout)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> cellElement;
|
||||
PRInt32 startRowIndex = 0, startColIndex = 0,
|
||||
rowSpan, colSpan, actualRowSpan, actualColSpan;
|
||||
bool isSelected = false;
|
||||
|
||||
PRInt32 rowIndex, index;
|
||||
for (rowIndex = 0, index = 0; rowIndex < rowCount; rowIndex++) {
|
||||
PRInt32 columnIndex;
|
||||
for (columnIndex = 0; columnIndex < columnCount; columnIndex++, index++) {
|
||||
rv = tableLayout->GetCellDataAt(rowIndex, columnIndex,
|
||||
for (PRUint32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
for (PRUint32 colIdx = 0; colIdx < colCount; colIdx++) {
|
||||
nsresult rv = tableLayout->GetCellDataAt(rowIdx, colIdx,
|
||||
*getter_AddRefs(cellElement),
|
||||
startRowIndex, startColIndex,
|
||||
rowSpan, colSpan,
|
||||
actualRowSpan, actualColSpan,
|
||||
isSelected);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && startRowIndex == rowIndex &&
|
||||
startColIndex == columnIndex && isSelected) {
|
||||
if (NS_SUCCEEDED(rv) && startRowIndex == rowIdx &&
|
||||
startColIndex == colIdx && isSelected) {
|
||||
nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
|
||||
Accessible* cell = mDoc->GetAccessible(cellContent);
|
||||
selCells->AppendElement(static_cast<nsIAccessible*>(cell), false);
|
||||
aCells->AppendElement(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aCells = selCells);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
virtual PRUint32 SelectedCellCount();
|
||||
virtual PRUint32 SelectedColCount();
|
||||
virtual PRUint32 SelectedRowCount();
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells);
|
||||
virtual void SelectedCellIndices(nsTArray<PRUint32>* aCells);
|
||||
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols);
|
||||
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows);
|
||||
|
|
|
@ -260,24 +260,11 @@ AndroidPresenter.prototype = {
|
|||
|
||||
let output = [];
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// Just provide the parent for some context, no need to utter the entire
|
||||
// ancestry change since it doesn't make sense in spatial navigation.
|
||||
for (var i = aContext.newAncestry.length - 1; i >= 0; i--) {
|
||||
let utter = UtteranceGenerator.genForObject(aContext.newAncestry[i]);
|
||||
if (utter.length) {
|
||||
output.push.apply(output, utter);
|
||||
break;
|
||||
}
|
||||
aContext.newAncestry.forEach(
|
||||
function(acc) {
|
||||
output.push.apply(output, UtteranceGenerator.genForObject(acc));
|
||||
}
|
||||
} else {
|
||||
// Utter the entire context change in linear navigation.
|
||||
aContext.newAncestry.forEach(
|
||||
function(acc) {
|
||||
output.push.apply(output, UtteranceGenerator.genForObject(acc));
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
output.push.apply(output,
|
||||
UtteranceGenerator.genForObject(aContext.accessible));
|
||||
|
|
|
@ -137,7 +137,6 @@ var UtteranceGenerator = {
|
|||
'toolbar': INCLUDE_DESC,
|
||||
'table': INCLUDE_DESC | INCLUDE_NAME,
|
||||
'link': INCLUDE_DESC,
|
||||
'list': INCLUDE_DESC,
|
||||
'listitem': INCLUDE_DESC,
|
||||
'outline': INCLUDE_DESC,
|
||||
'outlineitem': INCLUDE_DESC,
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "Accessible.h"
|
||||
#include "TableAccessible.h"
|
||||
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
static const PRUint32 XPC_TABLE_DEFAULT_SIZE = 40;
|
||||
|
||||
nsresult
|
||||
|
@ -243,6 +246,33 @@ xpcAccessibleTable::GetSelectedRowCount(PRUint32* aSelectedRowCount)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetSelectedCells(nsIArray** aSelectedCells)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSelectedCells);
|
||||
*aSelectedCells = nsnull;
|
||||
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> selCells =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoTArray<Accessible*, XPC_TABLE_DEFAULT_SIZE> cellsArray;
|
||||
mTable->SelectedCells(&cellsArray);
|
||||
|
||||
PRUint32 totalCount = cellsArray.Length();
|
||||
for (PRUint32 idx = 0; idx < totalCount; idx++) {
|
||||
Accessible* cell = cellsArray.ElementAt(idx);
|
||||
selCells -> AppendElement(static_cast<nsIAccessible*>(cell), false);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aSelectedCells = selCells);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetSelectedCellIndices(PRUint32* aCellsArraySize,
|
||||
PRInt32** aCellsArray)
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#include "nsAString.h"
|
||||
#include "nscore.h"
|
||||
|
||||
|
||||
class nsIAccessible;
|
||||
class nsIArray;
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
class TableAccessible;
|
||||
|
@ -46,6 +48,7 @@ public:
|
|||
nsresult GetSelectedCellCount(PRUint32* aSelectedCellCount);
|
||||
nsresult GetSelectedColumnCount(PRUint32* aSelectedColumnCount);
|
||||
nsresult GetSelectedRowCount(PRUint32* aSelectedRowCount);
|
||||
nsresult GetSelectedCells(nsIArray** aSelectedCell);
|
||||
nsresult GetSelectedCellIndices(PRUint32* aCellsArraySize,
|
||||
PRInt32** aCellsArray);
|
||||
nsresult GetSelectedColumnIndices(PRUint32* aColsArraySize,
|
||||
|
@ -101,7 +104,8 @@ protected:
|
|||
{ return xpcAccessibleTable::GetSelectedColumnCount(aSelectedColumnCount); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32* aSelectedRowCount) \
|
||||
{ return xpcAccessibleTable::GetSelectedRowCount(aSelectedRowCount); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray** aSelectedCells) \
|
||||
{ return xpcAccessibleTable::GetSelectedCells(aSelectedCells); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32* cellsArraySize NS_OUTPARAM, \
|
||||
PRInt32** cellsArray NS_OUTPARAM) \
|
||||
{ return xpcAccessibleTable::GetSelectedCellIndices(cellsArraySize, cellsArray); } \
|
||||
|
|
|
@ -354,20 +354,9 @@ XULListboxAccessible::SelectedRowCount()
|
|||
return selectedRowCount >= 0 ? selectedRowCount : 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULListboxAccessible::GetSelectedCells(nsIArray** aCells)
|
||||
void
|
||||
XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCells);
|
||||
*aCells = nsnull;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> selCells =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
|
||||
do_QueryInterface(mContent);
|
||||
NS_ASSERTION(control,
|
||||
|
@ -376,15 +365,13 @@ XULListboxAccessible::GetSelectedCells(nsIArray** aCells)
|
|||
nsCOMPtr<nsIDOMNodeList> selectedItems;
|
||||
control->GetSelectedItems(getter_AddRefs(selectedItems));
|
||||
if (!selectedItems)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
PRUint32 selectedItemsCount = 0;
|
||||
rv = selectedItems->GetLength(&selectedItemsCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = selectedItems->GetLength(&selectedItemsCount);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
|
||||
|
||||
NS_ENSURE_TRUE(mDoc, NS_ERROR_FAILURE);
|
||||
PRUint32 index = 0;
|
||||
for (; index < selectedItemsCount; index++) {
|
||||
for (PRUint32 index = 0; index < selectedItemsCount; index++) {
|
||||
nsCOMPtr<nsIDOMNode> itemNode;
|
||||
selectedItems->Item(index, getter_AddRefs(itemNode));
|
||||
nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
|
||||
|
@ -395,13 +382,10 @@ XULListboxAccessible::GetSelectedCells(nsIArray** aCells)
|
|||
for (PRUint32 cellIdx = 0; cellIdx < cellCount; cellIdx++) {
|
||||
Accessible* cell = mChildren[cellIdx];
|
||||
if (cell->Role() == roles::CELL)
|
||||
selCells->AppendElement(static_cast<nsIAccessible*>(cell), false);
|
||||
aCells->AppendElement(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aCells = selCells);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
virtual PRUint32 SelectedCellCount();
|
||||
virtual PRUint32 SelectedColCount();
|
||||
virtual PRUint32 SelectedRowCount();
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells);
|
||||
virtual void SelectedCellIndices(nsTArray<PRUint32>* aCells);
|
||||
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols);
|
||||
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows);
|
||||
|
|
|
@ -85,48 +85,19 @@ XULTreeGridAccessible::SelectedRowCount()
|
|||
return selectedRowCount >= 0 ? selectedRowCount : 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULTreeGridAccessible::GetSelectedCells(nsIArray** aCells)
|
||||
void
|
||||
XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCells);
|
||||
*aCells = nsnull;
|
||||
PRUint32 colCount = ColCount(), rowCount = RowCount();
|
||||
|
||||
if (!mTreeView)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> selCells = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_TRUE(selCells, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 selectedrowCount = 0;
|
||||
nsresult rv = GetSelectionCount(&selectedrowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 columnCount = 0;
|
||||
rv = GetColumnCount(&columnCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
rv = mTreeView->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 rowCount = 0;
|
||||
rv = GetRowCount(&rowCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isSelected;
|
||||
for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
selection->IsSelected(rowIdx, &isSelected);
|
||||
if (isSelected) {
|
||||
for (PRInt32 colIdx = 0; colIdx < columnCount; colIdx++) {
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
GetCellAt(rowIdx, colIdx, getter_AddRefs(cell));
|
||||
selCells->AppendElement(cell, false);
|
||||
for (PRUint32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
if (IsRowSelected(rowIdx)) {
|
||||
for (PRUint32 colIdx = 0; colIdx < colCount; colIdx++) {
|
||||
Accessible* cell = CellAt(rowIdx, colIdx);
|
||||
aCells->AppendElement(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aCells = selCells);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
virtual PRUint32 SelectedCellCount();
|
||||
virtual PRUint32 SelectedColCount();
|
||||
virtual PRUint32 SelectedRowCount();
|
||||
virtual void SelectedCells(nsTArray<Accessible*>* aCells);
|
||||
virtual void SelectedCellIndices(nsTArray<PRUint32>* aCells);
|
||||
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols);
|
||||
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows);
|
||||
|
|
|
@ -451,6 +451,7 @@ var WebappsHelper = {
|
|||
init: function webapps_init() {
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
DOMApplicationRegistry.allAppsLaunchable = true;
|
||||
},
|
||||
|
||||
registerInstaller: function webapps_registerInstaller(data) {
|
||||
|
|
|
@ -41,7 +41,9 @@ let WindowEventHandler = {
|
|||
// Sends an asynchronous message when the "onMozAfterPaint" event
|
||||
// is fired.
|
||||
onMozAfterPaint: function WEH_onMozAfterPaint(event) {
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
if (event.clientRects.length > 0) {
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -29,9 +29,6 @@ XPCOMUtils.defineLazyGetter(this, "gPrefBranch", function() {
|
|||
return Services.prefs.getBranch("browser.panorama.");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsing",
|
||||
"@mozilla.org/privatebrowsing;1", "nsIPrivateBrowsingService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gPageThumbnails",
|
||||
"resource:///modules/PageThumbs.jsm", "PageThumbs");
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ let Telemetry = {
|
|||
* Observes for gather telemetry topic.
|
||||
*/
|
||||
observe: function Telemetry_observe(aSubject, aTopic, aData) {
|
||||
if (!gPrivateBrowsing.privateBrowsingEnabled)
|
||||
if (!("gPrivateBrowsingUI" in gWindow) || !gWindow.gPrivateBrowsingUI.privateWindow)
|
||||
this._collect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159219"},
|
||||
{"clang_version": "r159409"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 73555568,
|
||||
"digest": "29102005216bfd719561ce1920f4cddd3c34c5581ed4cebc3abdc30d8d3f2b4705344cd4a2571ac05b11ff35fc1e0a9584568de89cc19ba6599311adccf5397b",
|
||||
"size": 74004324,
|
||||
"digest": "c5bb558a5958458b11da385d57897a1f7e57a7be2f452438f6813cf1e9f2a4ce93769c36e304126f97dbd753732b70446c7fa3c779267e80152d7ac0175057fc",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159219"},
|
||||
{"clang_version": "r159409"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 72267837,
|
||||
"digest": "15d0f9e3f1c897d06a7808edb931cdd23d82b38d271454e52740e23bd890338e204857bc87bfe3dde242fa62b38e01f15c19b814cab55e84874f0c6c5b4187e8",
|
||||
"size": 72533541,
|
||||
"digest": "f092080caed28db1ed7d9f0612aef1d885d2587b4e069d3662af5c241950ee772b6bc249d766a47b4fe2c170a46cfe05010269a3cbc1123d1f4126bc182b7b40",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159219"},
|
||||
{"clang_version": "r159409"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 63318129,
|
||||
"digest": "cf1dbc9221ff5f751ef9b8a3b93106585eb0955e648429359feb14a02892774538f7a19d0cf949b26549dae933a9a56dbb138e3cb2d1a883e6bfc47de27c16bb",
|
||||
"size": 63604770,
|
||||
"digest": "c664beadb01a4e8ba7f32698b3ef694ade9044a9117d90d57f1475f2cefea82d74d1b0f3da89dcb9932ba90e048ae3d908bff05ab09d0ce2c82731e949e62a47",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1012,7 +1012,7 @@ HUD_SERVICE.prototype =
|
|||
strings.push("[" + timestampString + "] " + item.clipboardText);
|
||||
}
|
||||
}
|
||||
clipboardHelper.copyString(strings.join("\n"), this.doc);
|
||||
clipboardHelper.copyString(strings.join("\n"), aOutputNode.ownerDocument);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,9 @@ import java.net.InetAddress;
|
|||
import org.apache.http.conn.util.InetAddressUtils;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
|
||||
|
@ -122,19 +124,26 @@ public class SUTAgentAndroid extends Activity
|
|||
if (getLocalIpAddress() == null)
|
||||
setUpNetwork(sIniFile);
|
||||
|
||||
WifiInfo wifi;
|
||||
WifiManager wifiMan = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
||||
String macAddress = "Unknown";
|
||||
if (wifiMan != null)
|
||||
{
|
||||
wifi = wifiMan.getConnectionInfo();
|
||||
if (wifi != null)
|
||||
try {
|
||||
NetworkInterface iface = NetworkInterface.getByInetAddress(InetAddress.getAllByName(getLocalIpAddress())[0]);
|
||||
if (iface != null)
|
||||
{
|
||||
macAddress = wifi.getMacAddress();
|
||||
if (macAddress != null)
|
||||
sUniqueID = macAddress;
|
||||
byte[] mac = iface.getHardwareAddress();
|
||||
if (mac != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter f = new Formatter(sb);
|
||||
for (int i = 0; i < mac.length; i++)
|
||||
{
|
||||
f.format("%02x%s", mac[i], (i < mac.length - 1) ? ":" : "");
|
||||
}
|
||||
macAddress = sUniqueID = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnknownHostException ex) {}
|
||||
catch (SocketException ex) {}
|
||||
|
||||
if (sUniqueID == null)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# 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/.
|
||||
|
||||
llvm_revision = "159219"
|
||||
llvm_revision = "159409"
|
||||
moz_version = "moz0"
|
||||
|
||||
##############################################
|
||||
|
|
|
@ -1830,6 +1830,11 @@ public:
|
|||
*/
|
||||
static bool IsRequestFullScreenAllowed();
|
||||
|
||||
/**
|
||||
* Returns true if the idle observers API is enabled.
|
||||
*/
|
||||
static bool IsIdleObserverAPIEnabled() { return sIsIdleObserverAPIEnabled; }
|
||||
|
||||
/**
|
||||
* Returns true if the doc tree branch which contains aDoc contains any
|
||||
* plugins which we don't control event dispatch for, i.e. do any plugins
|
||||
|
@ -2013,6 +2018,19 @@ public:
|
|||
static void SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
nsString& aParams);
|
||||
|
||||
/**
|
||||
* Function checks if the user is idle.
|
||||
*
|
||||
* @param aRequestedIdleTimeInMS The idle observer's requested idle time.
|
||||
* @param aUserIsIdle boolean indicating if the user
|
||||
* is currently idle or not. *
|
||||
* @return NS_OK NS_OK returned if the requested idle service and
|
||||
* the current idle time were successfully obtained.
|
||||
* NS_ERROR_FAILURE returned if the the requested
|
||||
* idle service or the current idle were not obtained.
|
||||
*/
|
||||
static nsresult IsUserIdle(PRUint32 aRequestedIdleTimeInMS, bool* aUserIsIdle);
|
||||
|
||||
/**
|
||||
* Takes a window and a string to check prefs against. Assumes that
|
||||
* the window is an app window, and that the pref is a comma
|
||||
|
@ -2139,6 +2157,7 @@ private:
|
|||
static bool sIsFullScreenApiEnabled;
|
||||
static bool sTrustedFullScreenOnly;
|
||||
static PRUint32 sHandlingInputTimeout;
|
||||
static bool sIsIdleObserverAPIEnabled;
|
||||
|
||||
static nsHtml5StringParser* sHTMLFragmentParser;
|
||||
static nsIParser* sXMLFragmentParser;
|
||||
|
|
|
@ -10,11 +10,19 @@
|
|||
* separate file for testing purposes.
|
||||
*/
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
// Module stuff
|
||||
var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", "CSPHost",
|
||||
"CSPWarning", "CSPError", "CSPdebug",
|
||||
"CSPViolationReportListener"];
|
||||
"CSPViolationReportListener", "CSPLocalizer"];
|
||||
|
||||
var STRINGS_URI = "chrome://global/locale/security/csp.properties";
|
||||
|
||||
// these are not exported
|
||||
var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
|
@ -222,7 +230,7 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
else if (opt === "eval-script")
|
||||
aCSPR._allowEval = true;
|
||||
else
|
||||
CSPWarning("don't understand option '" + opt + "'. Ignoring it.");
|
||||
CSPWarning(CSPLocalizer.getFormatStr("doNotUnderstandOption", [opt]));
|
||||
}
|
||||
continue directive;
|
||||
}
|
||||
|
@ -275,18 +283,18 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
if (self) {
|
||||
if (gETLDService.getBaseDomain(uri) !==
|
||||
gETLDService.getBaseDomain(selfUri)) {
|
||||
CSPWarning("can't use report URI from non-matching eTLD+1: "
|
||||
+ gETLDService.getBaseDomain(uri));
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notETLDPlus1",
|
||||
[gETLDService.getBaseDomain(uri)]));
|
||||
continue;
|
||||
}
|
||||
if (!uri.schemeIs(selfUri.scheme)) {
|
||||
CSPWarning("can't use report URI with different scheme from "
|
||||
+ "originating document: " + uri.asciiSpec);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notSameScheme",
|
||||
[uri.asciiSpec]));
|
||||
continue;
|
||||
}
|
||||
if (uri.port && uri.port !== selfUri.port) {
|
||||
CSPWarning("can't use report URI with different port from "
|
||||
+ "originating document: " + uri.asciiSpec);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("notSamePort",
|
||||
[uri.asciiSpec]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -295,14 +303,14 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
case Components.results.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS:
|
||||
case Components.results.NS_ERROR_HOST_IS_IP_ADDRESS:
|
||||
if (uri.host !== selfUri.host) {
|
||||
CSPWarning("page on " + selfUri.host
|
||||
+ " cannot send reports to " + uri.host);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("pageCannotSendReportsTo",
|
||||
[selfUri.host, uri.host]));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CSPWarning("couldn't parse report URI: " + uriStrings[i]);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("couldNotParseReportURI", [uriStrings[i]]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -317,13 +325,13 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
if (dirname === UD.POLICY_URI) {
|
||||
// POLICY_URI can only be alone
|
||||
if (aCSPR._directives.length > 0 || dirs.length > 1) {
|
||||
CSPError("policy-uri directive can only appear alone");
|
||||
CSPError(CSPLocalizer.getStr("policyURINotAlone"));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
// if we were called without a reference to the parent document request
|
||||
// we won't be able to suspend it while we fetch the policy -> fail closed
|
||||
if (!docRequest || !csp) {
|
||||
CSPError("The policy-uri cannot be fetched without a parent request and a CSP.");
|
||||
CSPError(CSPLocalizer.getStr("noParentRequest"));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
|
@ -331,22 +339,22 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
try {
|
||||
uri = gIoService.newURI(dirvalue, null, selfUri);
|
||||
} catch(e) {
|
||||
CSPError("could not parse URI in policy URI: " + dirvalue);
|
||||
CSPError(CSPLocalizer.getFormatStr("policyURIParseError", [dirvalue]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
// Verify that policy URI comes from the same origin
|
||||
if (selfUri) {
|
||||
if (selfUri.host !== uri.host){
|
||||
CSPError("can't fetch policy uri from non-matching hostname: " + uri.host);
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingHost", [uri.host]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
if (selfUri.port !== uri.port){
|
||||
CSPError("can't fetch policy uri from non-matching port: " + uri.port);
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingPort", [uri.port.toString()]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
if (selfUri.scheme !== uri.scheme){
|
||||
CSPError("can't fetch policy uri from non-matching scheme: " + uri.scheme);
|
||||
CSPError(CSPLocalizer.getFormatStr("nonMatchingScheme", [uri.scheme]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +371,7 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
catch (e) {
|
||||
// resume the document request and apply most restrictive policy
|
||||
docRequest.resume();
|
||||
CSPError("Error fetching policy-uri: " + e);
|
||||
CSPError(CSPLocalizer.getFormatStr("errorFetchingPolicy", [e.toString()]));
|
||||
return CSPRep.fromString("default-src 'none'");
|
||||
}
|
||||
|
||||
|
@ -373,7 +381,7 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
|
|||
}
|
||||
|
||||
// UNIDENTIFIED DIRECTIVE /////////////////////////////////////////////
|
||||
CSPWarning("Couldn't process unknown directive '" + dirname + "'");
|
||||
CSPWarning(CSPLocalizer.getFormatStr("couldNotProcessUnknownDirective", [dirname]));
|
||||
|
||||
} // end directive: loop
|
||||
|
||||
|
@ -516,7 +524,7 @@ CSPRep.prototype = {
|
|||
var SD = CSPRep.SRC_DIRECTIVES;
|
||||
var defaultSrcDir = this._directives[SD.DEFAULT_SRC];
|
||||
if (!defaultSrcDir) {
|
||||
CSPWarning("'allow' or 'default-src' directive required but not present. Reverting to \"default-src 'none'\"");
|
||||
CSPWarning(CSPLocalizer.getStr("allowOrDefaultSrcRequired"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -606,7 +614,7 @@ CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (tokens[i] === "") continue;
|
||||
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
|
||||
if (!src) {
|
||||
CSPWarning("Failed to parse unrecoginzied source " + tokens[i]);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
|
||||
continue;
|
||||
}
|
||||
slObj._sources.push(src);
|
||||
|
@ -832,12 +840,12 @@ CSPSource.create = function(aData, self, enforceSelfChecks) {
|
|||
*/
|
||||
CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
||||
if (!(aURI instanceof Components.interfaces.nsIURI)){
|
||||
CSPError("Provided argument is not an nsIURI");
|
||||
CSPError(CSPLocalizer.getStr("cspSourceNotURI"));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!self && enforceSelfChecks) {
|
||||
CSPError("Can't use 'self' if self data is not provided");
|
||||
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -856,7 +864,7 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
|
|||
sObj._scheme = aURI.scheme;
|
||||
} catch(e) {
|
||||
sObj._scheme = undefined;
|
||||
CSPError("can't parse a URI without a scheme: " + aURI.asciiSpec);
|
||||
CSPError(CSPLocalizer.getFormatStr("uriWithoutScheme", [aURI.asciiSpec]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -912,12 +920,12 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
return null;
|
||||
|
||||
if (!(typeof aStr === 'string')) {
|
||||
CSPError("Provided argument is not a string");
|
||||
CSPError(CSPLocalizer.getStr("argumentIsNotString"));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!self && enforceSelfChecks) {
|
||||
CSPError("Can't use 'self' if self data is not provided");
|
||||
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -931,7 +939,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
// take care of 'self' keyword
|
||||
if (aStr === "'self'") {
|
||||
if (!self) {
|
||||
CSPError("self keyword used, but no self data specified");
|
||||
CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
|
||||
return null;
|
||||
}
|
||||
sObj._self = self.clone();
|
||||
|
@ -950,7 +958,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (chunks.length == 1) {
|
||||
sObj._host = CSPHost.fromString(chunks[0]);
|
||||
if (!sObj._host) {
|
||||
CSPError("Couldn't parse invalid source " + aStr);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -958,7 +966,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.port) {
|
||||
CSPError("Can't create host-only source " + aStr + " without 'self' data");
|
||||
CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -977,7 +985,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (chunks[0] !== "") {
|
||||
sObj._host = CSPHost.fromString(chunks[0]);
|
||||
if (!sObj._host) {
|
||||
CSPError("Couldn't parse invalid source " + aStr);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -987,7 +995,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.host || !sObj.port) {
|
||||
CSPError("Can't create source " + aStr + " without 'self' data");
|
||||
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1009,7 +1017,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
// ... and parse
|
||||
sObj._host = CSPHost.fromString(cleanHost);
|
||||
if (!sObj._host) {
|
||||
CSPError("Couldn't parse invalid host " + cleanHost);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1019,14 +1027,14 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.host || !sObj.port) {
|
||||
CSPError("Can't create source " + aStr + " without 'self' data");
|
||||
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// AAAH! Don't know what to do! No valid scheme or port!
|
||||
CSPError("Couldn't parse invalid source " + aStr);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1035,12 +1043,12 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
|||
|
||||
// If there are three chunks, we got 'em all!
|
||||
if (!CSPSource.validSchemeName(chunks[0])) {
|
||||
CSPError("Couldn't parse scheme in " + aStr);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
|
||||
return null;
|
||||
}
|
||||
sObj._scheme = chunks[0];
|
||||
if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
|
||||
CSPError("Couldn't parse port in " + aStr);
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1202,8 +1210,7 @@ CSPSource.prototype = {
|
|||
else if (that._port === this._port)
|
||||
newSource._port = this._port;
|
||||
else {
|
||||
CSPError("Could not intersect " + this + " with " + that
|
||||
+ " due to port problems.");
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1219,8 +1226,7 @@ CSPSource.prototype = {
|
|||
else if (that._scheme === this._scheme)
|
||||
newSource._scheme = this._scheme;
|
||||
else {
|
||||
CSPError("Could not intersect " + this + " with " + that
|
||||
+ " due to scheme problems.");
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1236,14 +1242,13 @@ CSPSource.prototype = {
|
|||
if (this._host && that._host) {
|
||||
newSource._host = this._host.intersectWith(that._host);
|
||||
} else if (this._host) {
|
||||
CSPError("intersecting source with undefined host: " + that.toString());
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
|
||||
newSource._host = this._host.clone();
|
||||
} else if (that._host) {
|
||||
CSPError("intersecting source with undefined host: " + this.toString());
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
|
||||
newSource._host = that._host.clone();
|
||||
} else {
|
||||
CSPError("intersecting two sources with undefined hosts: " +
|
||||
this.toString() + " and " + that.toString());
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
|
||||
newSource._host = CSPHost.fromString("*");
|
||||
}
|
||||
|
||||
|
@ -1486,3 +1491,55 @@ CSPViolationReportListener.prototype = {
|
|||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CSPLocalizer = {
|
||||
/**
|
||||
* Retrieve a localized string.
|
||||
*
|
||||
* @param string aName
|
||||
* The string name you want from the CSP string bundle.
|
||||
* @return string
|
||||
* The localized string.
|
||||
*/
|
||||
getStr: function CSPLoc_getStr(aName)
|
||||
{
|
||||
let result;
|
||||
try {
|
||||
result = this.stringBundle.GetStringFromName(aName);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Failed to get string: " + aName);
|
||||
throw ex;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a localized string formatted with values coming from the given
|
||||
* array.
|
||||
*
|
||||
* @param string aName
|
||||
* The string name you want from the CSP string bundle.
|
||||
* @param array aArray
|
||||
* The array of values you want in the formatted string.
|
||||
* @return string
|
||||
* The formatted local string.
|
||||
*/
|
||||
getFormatStr: function CSPLoc_getFormatStr(aName, aArray)
|
||||
{
|
||||
let result;
|
||||
try {
|
||||
result = this.stringBundle.formatStringFromName(aName, aArray, aArray.length);
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Failed to format string: " + aName);
|
||||
throw ex;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(CSPLocalizer, "stringBundle", function() {
|
||||
return Services.strings.createBundle(STRINGS_URI);
|
||||
});
|
||||
|
|
|
@ -284,8 +284,13 @@ ContentSecurityPolicy.prototype = {
|
|||
var reportString = JSON.stringify(report);
|
||||
CSPdebug("Constructed violation report:\n" + reportString);
|
||||
|
||||
CSPWarning("Directive \"" + violatedDirective + "\" violated"
|
||||
+ (blockedUri['asciiSpec'] ? " by " + blockedUri.asciiSpec : ""),
|
||||
var violationMessage = null;
|
||||
if(blockedUri["asciiSpec"]){
|
||||
violationMessage = CSPLocalizer.getFormatStr("directiveViolatedWithURI", [violatedDirective, blockedUri.asciiSpec]);
|
||||
} else {
|
||||
violationMessage = CSPLocalizer.getFormatStr("directiveViolated", [violatedDirective]);
|
||||
}
|
||||
CSPWarning(violationMessage,
|
||||
this.innerWindowID,
|
||||
(aSourceFile) ? aSourceFile : null,
|
||||
(aScriptSample) ? decodeURIComponent(aScriptSample) : null,
|
||||
|
@ -347,8 +352,8 @@ ContentSecurityPolicy.prototype = {
|
|||
} catch(e) {
|
||||
// it's possible that the URI was invalid, just log a
|
||||
// warning and skip over that.
|
||||
CSPWarning("Tried to send report to invalid URI: \"" + uris[i] + "\"", this.innerWindowID);
|
||||
CSPWarning("error was: \"" + e + "\"", this.innerWindowID);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]]), this.innerWindowID);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("errorWas", [e.toString()]), this.innerWindowID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -550,8 +555,7 @@ CSPReportRedirectSink.prototype = {
|
|||
// nsIChannelEventSink
|
||||
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
|
||||
flags, callback) {
|
||||
CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
|
||||
" failed, as a redirect occurred", this.innerWindowID);
|
||||
CSPWarning(CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec]));
|
||||
|
||||
// cancel the old channel so XHR failure callback happens
|
||||
oldChannel.cancel(Cr.NS_ERROR_ABORT);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIIdleService.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMNode.h"
|
||||
|
@ -243,6 +244,7 @@ nsString* nsContentUtils::sModifierSeparator = nsnull;
|
|||
bool nsContentUtils::sInitialized = false;
|
||||
bool nsContentUtils::sIsFullScreenApiEnabled = false;
|
||||
bool nsContentUtils::sTrustedFullScreenOnly = true;
|
||||
bool nsContentUtils::sIsIdleObserverAPIEnabled = false;
|
||||
|
||||
PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
|
||||
|
||||
|
@ -418,6 +420,8 @@ nsContentUtils::Init()
|
|||
Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
|
||||
"full-screen-api.allow-trusted-requests-only");
|
||||
|
||||
sIsIdleObserverAPIEnabled = Preferences::GetBool("dom.idle-observers-api.enabled", true);
|
||||
|
||||
Preferences::AddUintVarCache(&sHandlingInputTimeout,
|
||||
"dom.event.handling-user-input-time-limit",
|
||||
1000);
|
||||
|
@ -869,6 +873,22 @@ nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
|
|||
aType.StripWhitespace();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentUtils::IsUserIdle(PRUint32 aRequestedIdleTimeInMS, bool* aUserIsIdle)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIIdleService> idleService =
|
||||
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 idleTimeInMS;
|
||||
rv = idleService->GetIdleTime(&idleTimeInMS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aUserIsIdle = idleTimeInMS >= aRequestedIdleTimeInMS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access a cached parser service. Don't addref. We need only one
|
||||
* reference to it and this class has that one.
|
||||
|
|
|
@ -108,14 +108,6 @@ public:
|
|||
nsRefPtr<nsIDocShell> mDocShell;
|
||||
};
|
||||
|
||||
static void InvalidateFrame(nsIFrame* aFrame, PRUint32 aFlags)
|
||||
{
|
||||
if (!aFrame)
|
||||
return;
|
||||
nsRect rect = nsRect(nsPoint(0, 0), aFrame->GetRect().Size());
|
||||
aFrame->InvalidateWithFlags(rect, aFlags);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
|
||||
|
||||
bool
|
||||
|
@ -150,13 +142,6 @@ nsContentView::Update(const ViewConfig& aConfig)
|
|||
rfp->ContentViewScaleChanged(this);
|
||||
}
|
||||
|
||||
// XXX could be clever here and compute a smaller invalidation
|
||||
// rect
|
||||
// NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
|
||||
// semantics the same for both in-process and out-of-process
|
||||
// <browser>. This is just a transform of the layer subtree in
|
||||
// both.
|
||||
InvalidateFrame(mFrameLoader->GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -622,7 +607,7 @@ SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
|
|||
|
||||
/**
|
||||
* Set the type of the treeitem and hook it up to the treeowner.
|
||||
* @param aItem the treeitem we're wrking working with
|
||||
* @param aItem the treeitem we're working with
|
||||
* @param aOwningContent the content node that owns aItem
|
||||
* @param aTreeOwner the relevant treeowner; might be null
|
||||
* @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell
|
||||
|
@ -643,6 +628,8 @@ AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
|
|||
|
||||
if (aOwningContent->IsXUL()) {
|
||||
aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
||||
} else {
|
||||
aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozframetype, value);
|
||||
}
|
||||
|
||||
// we accept "content" and "content-xxx" values.
|
||||
|
@ -1743,11 +1730,6 @@ nsFrameLoader::SetRenderMode(PRUint32 aRenderMode)
|
|||
}
|
||||
|
||||
mRenderMode = aRenderMode;
|
||||
// NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
|
||||
// semantics the same for both in-process and out-of-process
|
||||
// <browser>. This is just a transform of the layer subtree in
|
||||
// both.
|
||||
InvalidateFrame(GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1778,7 +1760,7 @@ nsFrameLoader::SetClipSubdocument(bool aClip)
|
|||
mClipSubdocument = aClip;
|
||||
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
||||
if (frame) {
|
||||
InvalidateFrame(frame, 0);
|
||||
frame->InvalidateFrame();
|
||||
frame->PresContext()->PresShell()->
|
||||
FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
||||
nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
GK_ATOM(_empty, "")
|
||||
GK_ATOM(moz, "_moz")
|
||||
GK_ATOM(mozframetype, "mozframetype")
|
||||
GK_ATOM(mozallowfullscreen, "mozallowfullscreen")
|
||||
GK_ATOM(moztype, "_moz-type")
|
||||
GK_ATOM(mozdirty, "_moz_dirty")
|
||||
|
|
|
@ -1100,7 +1100,7 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
|
|||
|
||||
// Set up new frame to draw.
|
||||
objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
|
||||
objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
|
||||
objFrame->InvalidateFrame();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,14 @@ protected:
|
|||
nsRefPtr<nsHTMLCanvasElement> mCanvasElement;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
extern bool AzureCanvasEnabled();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
|
||||
NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
|
||||
|
||||
|
|
|
@ -9,17 +9,19 @@
|
|||
#include "imgIRequest.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHTMLCanvasElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
struct ImageCacheKey {
|
||||
ImageCacheKey(nsIDOMElement* aImage, nsHTMLCanvasElement* aCanvas)
|
||||
ImageCacheKey(Element* aImage, nsHTMLCanvasElement* aCanvas)
|
||||
: mImage(aImage), mCanvas(aCanvas) {}
|
||||
nsIDOMElement* mImage;
|
||||
Element* mImage;
|
||||
nsHTMLCanvasElement* mCanvas;
|
||||
};
|
||||
|
||||
|
@ -41,7 +43,7 @@ struct ImageCacheEntryData {
|
|||
nsExpirationState* GetExpirationState() { return &mState; }
|
||||
|
||||
// Key
|
||||
nsCOMPtr<nsIDOMElement> mImage;
|
||||
nsRefPtr<Element> mImage;
|
||||
nsIImageLoadingContent* mILC;
|
||||
nsRefPtr<nsHTMLCanvasElement> mCanvas;
|
||||
// Value
|
||||
|
@ -110,7 +112,7 @@ public:
|
|||
};
|
||||
|
||||
void
|
||||
CanvasImageCache::NotifyDrawImage(nsIDOMElement* aImage,
|
||||
CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
gfxASurface* aSurface,
|
||||
|
@ -141,7 +143,7 @@ CanvasImageCache::NotifyDrawImage(nsIDOMElement* aImage,
|
|||
}
|
||||
|
||||
gfxASurface*
|
||||
CanvasImageCache::Lookup(nsIDOMElement* aImage,
|
||||
CanvasImageCache::Lookup(Element* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
#ifndef CANVASIMAGECACHE_H_
|
||||
#define CANVASIMAGECACHE_H_
|
||||
|
||||
class nsIDOMElement;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
class nsHTMLCanvasElement;
|
||||
class imgIRequest;
|
||||
class gfxASurface;
|
||||
|
@ -22,7 +26,7 @@ public:
|
|||
* using the first frame of aRequest's image. The data for the surface is
|
||||
* in aSurface, and the image size is in aSize.
|
||||
*/
|
||||
static void NotifyDrawImage(nsIDOMElement* aImage,
|
||||
static void NotifyDrawImage(dom::Element* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
gfxASurface* aSurface,
|
||||
|
@ -34,7 +38,7 @@ public:
|
|||
* (with the same image request) and the returned surface contains the image
|
||||
* data, and the image size will be returned in aSize.
|
||||
*/
|
||||
static gfxASurface* Lookup(nsIDOMElement* aImage,
|
||||
static gfxASurface* Lookup(dom::Element* aImage,
|
||||
nsHTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ public:
|
|||
{
|
||||
return mHeight;
|
||||
}
|
||||
JSObject* GetData(JSContext* cx)
|
||||
{
|
||||
return GetDataObject();
|
||||
}
|
||||
JSObject* GetDataObject()
|
||||
{
|
||||
xpc_UnmarkGrayObject(mData);
|
||||
|
|
|
@ -77,6 +77,7 @@ INCLUDES += \
|
|||
-I$(srcdir)/../../../layout/generic \
|
||||
-I$(srcdir)/../../base/src \
|
||||
-I$(srcdir)/../../html/content/src \
|
||||
-I$(srcdir)/../../../js/xpconnect/src \
|
||||
-I$(srcdir)/../../../dom/base \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1422,7 +1422,7 @@ nsCanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
|
|||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Save()
|
||||
nsCanvasRenderingContext2D::MozSave()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1435,7 +1435,7 @@ nsCanvasRenderingContext2D::Save()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Restore()
|
||||
nsCanvasRenderingContext2D::MozRestore()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1951,7 +1951,7 @@ nsCanvasRenderingContext2D::GetShadowBlur(float *blur)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetShadowColor(const nsAString& aColor)
|
||||
nsCanvasRenderingContext2D:: SetMozShadowColor(const nsAString& aColor)
|
||||
{
|
||||
nscolor color;
|
||||
if (!ParseColor(aColor, &color)) {
|
||||
|
@ -1966,7 +1966,7 @@ nsCanvasRenderingContext2D::SetShadowColor(const nsAString& aColor)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetShadowColor(nsAString& color)
|
||||
nsCanvasRenderingContext2D::GetMozShadowColor(nsAString& color)
|
||||
{
|
||||
StyleColorToString(CurrentState().colorStyles[STYLE_SHADOW], color);
|
||||
|
||||
|
@ -2217,7 +2217,7 @@ nsCanvasRenderingContext2D::StrokeRect(float x, float y, float w, float h)
|
|||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::BeginPath()
|
||||
nsCanvasRenderingContext2D::MozBeginPath()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2228,7 +2228,7 @@ nsCanvasRenderingContext2D::BeginPath()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::ClosePath()
|
||||
nsCanvasRenderingContext2D::MozClosePath()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2238,7 +2238,7 @@ nsCanvasRenderingContext2D::ClosePath()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Fill()
|
||||
nsCanvasRenderingContext2D::MozFill()
|
||||
{
|
||||
gfxRect dirty;
|
||||
nsresult rv = DrawPath(STYLE_FILL, &dirty);
|
||||
|
@ -2248,7 +2248,7 @@ nsCanvasRenderingContext2D::Fill()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Stroke()
|
||||
nsCanvasRenderingContext2D::MozStroke()
|
||||
{
|
||||
gfxRect dirty;
|
||||
nsresult rv = DrawPath(STYLE_STROKE, &dirty);
|
||||
|
@ -2258,7 +2258,7 @@ nsCanvasRenderingContext2D::Stroke()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Clip()
|
||||
nsCanvasRenderingContext2D::MozClip()
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2487,7 +2487,7 @@ CreateFontStyleRule(const nsAString& aFont,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
nsCanvasRenderingContext2D::SetMozFont(const nsAString& font)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -2616,7 +2616,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetFont(nsAString& font)
|
||||
nsCanvasRenderingContext2D::GetMozFont(nsAString& font)
|
||||
{
|
||||
/* will initilize the value if not set, else does nothing */
|
||||
GetCurrentFontStyle();
|
||||
|
@ -2626,7 +2626,7 @@ nsCanvasRenderingContext2D::GetFont(nsAString& font)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetTextAlign(const nsAString& ta)
|
||||
nsCanvasRenderingContext2D::SetMozTextAlign(const nsAString& ta)
|
||||
{
|
||||
if (ta.EqualsLiteral("start"))
|
||||
CurrentState().textAlign = TEXT_ALIGN_START;
|
||||
|
@ -2643,7 +2643,7 @@ nsCanvasRenderingContext2D::SetTextAlign(const nsAString& ta)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetTextAlign(nsAString& ta)
|
||||
nsCanvasRenderingContext2D::GetMozTextAlign(nsAString& ta)
|
||||
{
|
||||
switch (CurrentState().textAlign)
|
||||
{
|
||||
|
@ -2668,7 +2668,7 @@ nsCanvasRenderingContext2D::GetTextAlign(nsAString& ta)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetTextBaseline(const nsAString& tb)
|
||||
nsCanvasRenderingContext2D::SetMozTextBaseline(const nsAString& tb)
|
||||
{
|
||||
if (tb.EqualsLiteral("top"))
|
||||
CurrentState().textBaseline = TEXT_BASELINE_TOP;
|
||||
|
@ -2687,7 +2687,7 @@ nsCanvasRenderingContext2D::SetTextBaseline(const nsAString& tb)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetTextBaseline(nsAString& tb)
|
||||
nsCanvasRenderingContext2D::GetMozTextBaseline(nsAString& tb)
|
||||
{
|
||||
switch (CurrentState().textBaseline)
|
||||
{
|
||||
|
@ -3114,17 +3114,17 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozTextStyle(const nsAString& textStyle)
|
||||
nsCanvasRenderingContext2D::SetTextStyle(const nsAString& textStyle)
|
||||
{
|
||||
// font and mozTextStyle are the same value
|
||||
return SetFont(textStyle);
|
||||
return SetMozFont(textStyle);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozTextStyle(nsAString& textStyle)
|
||||
nsCanvasRenderingContext2D::GetTextStyle(nsAString& textStyle)
|
||||
{
|
||||
// font and mozTextStyle are the same value
|
||||
return GetFont(textStyle);
|
||||
return GetMozFont(textStyle);
|
||||
}
|
||||
|
||||
gfxFontGroup*
|
||||
|
@ -3132,7 +3132,7 @@ nsCanvasRenderingContext2D::GetCurrentFontStyle()
|
|||
{
|
||||
// use lazy initilization for the font group since it's rather expensive
|
||||
if(!CurrentState().fontGroup) {
|
||||
nsresult rv = SetMozTextStyle(kDefaultFontStyle);
|
||||
nsresult rv = SetTextStyle(kDefaultFontStyle);
|
||||
if (NS_FAILED(rv)) {
|
||||
gfxFontStyle style;
|
||||
style.size = kDefaultFontSize;
|
||||
|
@ -3197,7 +3197,7 @@ nsCanvasRenderingContext2D::GetLineWidth(float *width)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
|
||||
nsCanvasRenderingContext2D::SetMozLineCap(const nsAString& capstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3219,7 +3219,7 @@ nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
|
||||
nsCanvasRenderingContext2D::GetMozLineCap(nsAString& capstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3239,7 +3239,7 @@ nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
|
||||
nsCanvasRenderingContext2D::SetMozLineJoin(const nsAString& joinstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3261,7 +3261,7 @@ nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle)
|
||||
nsCanvasRenderingContext2D::GetMozLineJoin(nsAString& joinstyle)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3422,7 +3422,7 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
nsRefPtr<gfxPattern> pattern;
|
||||
gfxIntSize imgSize;
|
||||
nsRefPtr<gfxASurface> imgsurf =
|
||||
CanvasImageCache::Lookup(imgElt, mCanvasElement, &imgSize);
|
||||
CanvasImageCache::Lookup(content->AsElement(), mCanvasElement, &imgSize);
|
||||
|
||||
if (!imgsurf) {
|
||||
// The canvas spec says that drawImage should draw the first frame
|
||||
|
@ -3456,7 +3456,7 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
}
|
||||
|
||||
if (res.mImageRequest) {
|
||||
CanvasImageCache::NotifyDrawImage(imgElt, mCanvasElement,
|
||||
CanvasImageCache::NotifyDrawImage(content->AsElement(), mCanvasElement,
|
||||
res.mImageRequest, imgsurf, imgSize);
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,943 @@
|
|||
/* 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 nsCanvasRenderingContext2DAzure_h
|
||||
#define nsCanvasRenderingContext2DAzure_h
|
||||
|
||||
#include <vector>
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsHTMLCanvasElement.h"
|
||||
#include "CanvasUtils.h"
|
||||
#include "nsHTMLImageElement.h"
|
||||
#include "nsHTMLVideoElement.h"
|
||||
#include "gfxFont.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
template<typename T> class Optional;
|
||||
}
|
||||
namespace gfx {
|
||||
struct Rect;
|
||||
class SourceSurface;
|
||||
}
|
||||
}
|
||||
|
||||
extern const mozilla::gfx::Float SIGMA_MAX;
|
||||
|
||||
/**
|
||||
** nsCanvasGradientAzure
|
||||
**/
|
||||
#define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
|
||||
{0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
|
||||
class nsCanvasGradientAzure : public nsIDOMCanvasGradient
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENTAZURE_PRIVATE_IID)
|
||||
|
||||
enum Type
|
||||
{
|
||||
LINEAR = 0,
|
||||
RADIAL
|
||||
};
|
||||
|
||||
Type GetType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
|
||||
mozilla::gfx::GradientStops *
|
||||
GetGradientStopsForTarget(mozilla::gfx::DrawTarget *aRT)
|
||||
{
|
||||
if (mStops && mStops->GetBackendType() == aRT->GetType()) {
|
||||
return mStops;
|
||||
}
|
||||
|
||||
mStops = aRT->CreateGradientStops(mRawStops.Elements(), mRawStops.Length());
|
||||
|
||||
return mStops;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/* nsIDOMCanvasGradient */
|
||||
NS_IMETHOD AddColorStop(float offset, const nsAString& colorstr);
|
||||
|
||||
protected:
|
||||
nsCanvasGradientAzure(Type aType) : mType(aType)
|
||||
{}
|
||||
|
||||
nsTArray<mozilla::gfx::GradientStop> mRawStops;
|
||||
mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
|
||||
Type mType;
|
||||
virtual ~nsCanvasGradientAzure() {}
|
||||
};
|
||||
|
||||
/**
|
||||
** nsCanvasPatternAzure
|
||||
**/
|
||||
#define NS_CANVASPATTERNAZURE_PRIVATE_IID \
|
||||
{0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
|
||||
class nsCanvasPatternAzure MOZ_FINAL : public nsIDOMCanvasPattern
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERNAZURE_PRIVATE_IID)
|
||||
|
||||
enum RepeatMode
|
||||
{
|
||||
REPEAT,
|
||||
REPEATX,
|
||||
REPEATY,
|
||||
NOREPEAT
|
||||
};
|
||||
|
||||
nsCanvasPatternAzure(mozilla::gfx::SourceSurface* aSurface,
|
||||
RepeatMode aRepeat,
|
||||
nsIPrincipal* principalForSecurityCheck,
|
||||
bool forceWriteOnly,
|
||||
bool CORSUsed)
|
||||
: mSurface(aSurface)
|
||||
, mRepeat(aRepeat)
|
||||
, mPrincipal(principalForSecurityCheck)
|
||||
, mForceWriteOnly(forceWriteOnly)
|
||||
, mCORSUsed(CORSUsed)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::SourceSurface> mSurface;
|
||||
const RepeatMode mRepeat;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
const bool mForceWriteOnly;
|
||||
const bool mCORSUsed;
|
||||
};
|
||||
|
||||
struct nsCanvasBidiProcessorAzure;
|
||||
class CanvasRenderingContext2DUserDataAzure;
|
||||
|
||||
/**
|
||||
** nsCanvasRenderingContext2DAzure
|
||||
**/
|
||||
class nsCanvasRenderingContext2DAzure :
|
||||
public nsIDOMCanvasRenderingContext2D,
|
||||
public nsICanvasRenderingContextInternal,
|
||||
public nsWrapperCache
|
||||
{
|
||||
typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
|
||||
HTMLImageOrCanvasOrVideoElement;
|
||||
|
||||
public:
|
||||
nsCanvasRenderingContext2DAzure();
|
||||
virtual ~nsCanvasRenderingContext2DAzure();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
|
||||
bool *triedToWrap);
|
||||
|
||||
nsHTMLCanvasElement* GetCanvas() const
|
||||
{
|
||||
return mCanvasElement;
|
||||
}
|
||||
|
||||
void Save();
|
||||
void Restore();
|
||||
void Scale(double x, double y, mozilla::ErrorResult& error);
|
||||
void Rotate(double angle, mozilla::ErrorResult& error);
|
||||
void Translate(double x, double y, mozilla::ErrorResult& error);
|
||||
void Transform(double m11, double m12, double m21, double m22, double dx,
|
||||
double dy, mozilla::ErrorResult& error);
|
||||
void SetTransform(double m11, double m12, double m21, double m22, double dx,
|
||||
double dy, mozilla::ErrorResult& error);
|
||||
|
||||
double GetGlobalAlpha()
|
||||
{
|
||||
return CurrentState().globalAlpha;
|
||||
}
|
||||
|
||||
void SetGlobalAlpha(double globalAlpha)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(globalAlpha) &&
|
||||
globalAlpha >= 0.0 && globalAlpha <= 1.0) {
|
||||
CurrentState().globalAlpha = globalAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
|
||||
void SetGlobalCompositeOperation(const nsAString& op,
|
||||
mozilla::ErrorResult& error);
|
||||
JS::Value GetStrokeStyle(JSContext* cx, mozilla::ErrorResult& error);
|
||||
|
||||
void SetStrokeStyle(JSContext* cx, JS::Value& value)
|
||||
{
|
||||
SetStyleFromJSValue(cx, value, STYLE_STROKE);
|
||||
}
|
||||
|
||||
JS::Value GetFillStyle(JSContext* cx, mozilla::ErrorResult& error);
|
||||
|
||||
void SetFillStyle(JSContext* cx, JS::Value& value)
|
||||
{
|
||||
SetStyleFromJSValue(cx, value, STYLE_FILL);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMCanvasGradient>
|
||||
CreateLinearGradient(double x0, double y0, double x1, double y1,
|
||||
mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMCanvasGradient>
|
||||
CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
|
||||
double r1, mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMCanvasPattern>
|
||||
CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
|
||||
const nsAString& repeat, mozilla::ErrorResult& error);
|
||||
|
||||
double GetShadowOffsetX()
|
||||
{
|
||||
return CurrentState().shadowOffset.x;
|
||||
}
|
||||
|
||||
void SetShadowOffsetX(double shadowOffsetX)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(shadowOffsetX)) {
|
||||
CurrentState().shadowOffset.x = shadowOffsetX;
|
||||
}
|
||||
}
|
||||
|
||||
double GetShadowOffsetY()
|
||||
{
|
||||
return CurrentState().shadowOffset.y;
|
||||
}
|
||||
|
||||
void SetShadowOffsetY(double shadowOffsetY)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(shadowOffsetY)) {
|
||||
CurrentState().shadowOffset.y = shadowOffsetY;
|
||||
}
|
||||
}
|
||||
|
||||
double GetShadowBlur()
|
||||
{
|
||||
return CurrentState().shadowBlur;
|
||||
}
|
||||
|
||||
void SetShadowBlur(double shadowBlur)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(shadowBlur) && shadowBlur >= 0.0) {
|
||||
CurrentState().shadowBlur = shadowBlur;
|
||||
}
|
||||
}
|
||||
|
||||
void GetShadowColor(nsAString& shadowColor)
|
||||
{
|
||||
StyleColorToString(CurrentState().shadowColor, shadowColor);
|
||||
}
|
||||
|
||||
void SetShadowColor(const nsAString& shadowColor);
|
||||
void ClearRect(double x, double y, double w, double h);
|
||||
void FillRect(double x, double y, double w, double h);
|
||||
void StrokeRect(double x, double y, double w, double h);
|
||||
void BeginPath();
|
||||
void Fill();
|
||||
void Stroke();
|
||||
void Clip();
|
||||
bool IsPointInPath(double x, double y);
|
||||
void FillText(const nsAString& text, double x, double y,
|
||||
const mozilla::dom::Optional<double>& maxWidth,
|
||||
mozilla::ErrorResult& error);
|
||||
void StrokeText(const nsAString& text, double x, double y,
|
||||
const mozilla::dom::Optional<double>& maxWidth,
|
||||
mozilla::ErrorResult& error);
|
||||
already_AddRefed<nsIDOMTextMetrics>
|
||||
MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
|
||||
|
||||
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
||||
double dx, double dy, mozilla::ErrorResult& error)
|
||||
{
|
||||
if (!mozilla::CanvasUtils::FloatValidate(dx, dy)) {
|
||||
return;
|
||||
}
|
||||
DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
|
||||
}
|
||||
|
||||
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
||||
double dx, double dy, double dw, double dh,
|
||||
mozilla::ErrorResult& error)
|
||||
{
|
||||
if (!mozilla::CanvasUtils::FloatValidate(dx, dy, dw, dh)) {
|
||||
return;
|
||||
}
|
||||
DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, dw, dh, 2, error);
|
||||
}
|
||||
|
||||
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
||||
double sx, double sy, double sw, double sh, double dx,
|
||||
double dy, double dw, double dh, mozilla::ErrorResult& error)
|
||||
{
|
||||
if (!mozilla::CanvasUtils::FloatValidate(sx, sy, sw, sh) ||
|
||||
!mozilla::CanvasUtils::FloatValidate(dx, dy, dw, dh)) {
|
||||
return;
|
||||
}
|
||||
DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::ImageData>
|
||||
CreateImageData(JSContext* cx, double sw, double sh,
|
||||
mozilla::ErrorResult& error);
|
||||
already_AddRefed<mozilla::dom::ImageData>
|
||||
CreateImageData(JSContext* cx, mozilla::dom::ImageData* imagedata,
|
||||
mozilla::ErrorResult& error);
|
||||
already_AddRefed<mozilla::dom::ImageData>
|
||||
GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
|
||||
mozilla::ErrorResult& error);
|
||||
void PutImageData(JSContext* cx, mozilla::dom::ImageData* imageData,
|
||||
double dx, double dy, mozilla::ErrorResult& error);
|
||||
void PutImageData(JSContext* cx, mozilla::dom::ImageData* imageData,
|
||||
double dx, double dy, double dirtyX, double dirtyY,
|
||||
double dirtyWidth, double dirtyHeight,
|
||||
mozilla::ErrorResult& error);
|
||||
|
||||
double GetLineWidth()
|
||||
{
|
||||
return CurrentState().lineWidth;
|
||||
}
|
||||
|
||||
void SetLineWidth(double width)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(width) && width > 0.0) {
|
||||
CurrentState().lineWidth = width;
|
||||
}
|
||||
}
|
||||
void GetLineCap(nsAString& linecap);
|
||||
void SetLineCap(const nsAString& linecap);
|
||||
void GetLineJoin(nsAString& linejoin, mozilla::ErrorResult& error);
|
||||
void SetLineJoin(const nsAString& linejoin);
|
||||
|
||||
double GetMiterLimit()
|
||||
{
|
||||
return CurrentState().miterLimit;
|
||||
}
|
||||
|
||||
void SetMiterLimit(double miter)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(miter) && miter > 0.0) {
|
||||
CurrentState().miterLimit = miter;
|
||||
}
|
||||
}
|
||||
|
||||
void GetFont(nsAString& font)
|
||||
{
|
||||
font = GetFont();
|
||||
}
|
||||
|
||||
void SetFont(const nsAString& font, mozilla::ErrorResult& error);
|
||||
void GetTextAlign(nsAString& textAlign);
|
||||
void SetTextAlign(const nsAString& textAlign);
|
||||
void GetTextBaseline(nsAString& textBaseline);
|
||||
void SetTextBaseline(const nsAString& textBaseline);
|
||||
|
||||
void ClosePath()
|
||||
{
|
||||
EnsureWritablePath();
|
||||
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->Close();
|
||||
} else {
|
||||
mDSPathBuilder->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTo(double x, double y)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(x, y)) {
|
||||
EnsureWritablePath();
|
||||
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->MoveTo(mozilla::gfx::Point(x, y));
|
||||
} else {
|
||||
mDSPathBuilder->MoveTo(mTarget->GetTransform() *
|
||||
mozilla::gfx::Point(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LineTo(double x, double y)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(x, y)) {
|
||||
EnsureWritablePath();
|
||||
|
||||
LineTo(mozilla::gfx::Point(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
void QuadraticCurveTo(double cpx, double cpy, double x, double y)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(cpx, cpy, x, y)) {
|
||||
EnsureWritablePath();
|
||||
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(cpx, cpy),
|
||||
mozilla::gfx::Point(x, y));
|
||||
} else {
|
||||
mozilla::gfx::Matrix transform = mTarget->GetTransform();
|
||||
mDSPathBuilder->QuadraticBezierTo(transform *
|
||||
mozilla::gfx::Point(cpx, cpy),
|
||||
transform *
|
||||
mozilla::gfx::Point(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y)
|
||||
{
|
||||
if (mozilla::CanvasUtils::FloatValidate(cp1x, cp1y, cp2x, cp2y, x, y)) {
|
||||
EnsureWritablePath();
|
||||
|
||||
BezierTo(mozilla::gfx::Point(cp1x, cp1y),
|
||||
mozilla::gfx::Point(cp2x, cp2y),
|
||||
mozilla::gfx::Point(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
void ArcTo(double x1, double y1, double x2, double y2, double radius,
|
||||
mozilla::ErrorResult& error);
|
||||
void Rect(double x, double y, double w, double h);
|
||||
void Arc(double x, double y, double radius, double startAngle,
|
||||
double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
|
||||
|
||||
JSObject* GetMozCurrentTransform(JSContext* cx,
|
||||
mozilla::ErrorResult& error) const;
|
||||
void SetMozCurrentTransform(JSContext* cx, JSObject& currentTransform,
|
||||
mozilla::ErrorResult& error);
|
||||
JSObject* GetMozCurrentTransformInverse(JSContext* cx,
|
||||
mozilla::ErrorResult& error) const;
|
||||
void SetMozCurrentTransformInverse(JSContext* cx, JSObject& currentTransform,
|
||||
mozilla::ErrorResult& error);
|
||||
void GetFillRule(nsAString& fillRule);
|
||||
void SetFillRule(const nsAString& fillRule);
|
||||
JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
|
||||
void SetMozDash(JSContext* cx, const JS::Value& mozDash,
|
||||
mozilla::ErrorResult& error);
|
||||
|
||||
double GetMozDashOffset()
|
||||
{
|
||||
return CurrentState().dashOffset;
|
||||
}
|
||||
|
||||
void SetMozDashOffset(double mozDashOffset, mozilla::ErrorResult& error);
|
||||
|
||||
void GetMozTextStyle(nsAString& mozTextStyle)
|
||||
{
|
||||
GetFont(mozTextStyle);
|
||||
}
|
||||
|
||||
void SetMozTextStyle(const nsAString& mozTextStyle,
|
||||
mozilla::ErrorResult& error)
|
||||
{
|
||||
SetFont(mozTextStyle, error);
|
||||
}
|
||||
|
||||
bool GetImageSmoothingEnabled()
|
||||
{
|
||||
return CurrentState().imageSmoothingEnabled;
|
||||
}
|
||||
|
||||
void SetImageSmoothingEnabled(bool imageSmoothingEnabled)
|
||||
{
|
||||
if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
|
||||
CurrentState().imageSmoothingEnabled = imageSmoothingEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h,
|
||||
const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w,
|
||||
double h, const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
|
||||
nsresult Redraw();
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
nsIInputStream **aStream);
|
||||
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
|
||||
|
||||
mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot()
|
||||
{ return mTarget ? mTarget->Snapshot() : nsnull; }
|
||||
|
||||
NS_IMETHOD SetIsOpaque(bool isOpaque);
|
||||
NS_IMETHOD Reset();
|
||||
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager);
|
||||
void MarkContextClean();
|
||||
NS_IMETHOD SetIsIPC(bool isIPC);
|
||||
// this rect is in canvas device space
|
||||
void Redraw(const mozilla::gfx::Rect &r);
|
||||
NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
|
||||
|
||||
// this rect is in mTarget's current user space
|
||||
void RedrawUser(const gfxRect &r);
|
||||
|
||||
// nsISupports interface + CC
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsCanvasRenderingContext2DAzure,
|
||||
nsIDOMCanvasRenderingContext2D)
|
||||
|
||||
// nsIDOMCanvasRenderingContext2D interface
|
||||
NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
|
||||
|
||||
enum Style {
|
||||
STYLE_STROKE = 0,
|
||||
STYLE_FILL,
|
||||
STYLE_MAX
|
||||
};
|
||||
|
||||
nsINode* GetParentObject()
|
||||
{
|
||||
return mCanvasElement;
|
||||
}
|
||||
|
||||
void LineTo(const mozilla::gfx::Point& aPoint)
|
||||
{
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->LineTo(aPoint);
|
||||
} else {
|
||||
mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void BezierTo(const mozilla::gfx::Point& aCP1,
|
||||
const mozilla::gfx::Point& aCP2,
|
||||
const mozilla::gfx::Point& aCP3)
|
||||
{
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
|
||||
} else {
|
||||
mozilla::gfx::Matrix transform = mTarget->GetTransform();
|
||||
mDSPathBuilder->BezierTo(transform * aCP1,
|
||||
transform * aCP2,
|
||||
transform * aCP3);
|
||||
}
|
||||
}
|
||||
|
||||
friend class CanvasRenderingContext2DUserDataAzure;
|
||||
|
||||
protected:
|
||||
nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
|
||||
uint32_t aWidth, uint32_t aHeight,
|
||||
JSObject** aRetval);
|
||||
|
||||
nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
|
||||
PRInt32 width, PRInt32 height);
|
||||
|
||||
/**
|
||||
* The number of living nsCanvasRenderingContexts. When this goes down to
|
||||
* 0, we free the premultiply and unpremultiply tables, if they exist.
|
||||
*/
|
||||
static PRUint32 sNumLivingContexts;
|
||||
|
||||
/**
|
||||
* Lookup table used to speed up GetImageData().
|
||||
*/
|
||||
static PRUint8 (*sUnpremultiplyTable)[256];
|
||||
|
||||
/**
|
||||
* Lookup table used to speed up PutImageData().
|
||||
*/
|
||||
static PRUint8 (*sPremultiplyTable)[256];
|
||||
|
||||
// Some helpers. Doesn't modify a color on failure.
|
||||
void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle);
|
||||
void SetStyleFromString(const nsAString& str, Style whichStyle);
|
||||
|
||||
void SetStyleFromGradient(nsCanvasGradientAzure *gradient, Style whichStyle)
|
||||
{
|
||||
CurrentState().SetGradientStyle(whichStyle, gradient);
|
||||
}
|
||||
|
||||
void SetStyleFromPattern(nsCanvasPatternAzure *pattern, Style whichStyle)
|
||||
{
|
||||
CurrentState().SetPatternStyle(whichStyle, pattern);
|
||||
}
|
||||
|
||||
void SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
|
||||
nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
|
||||
|
||||
// Returns whether a color was successfully parsed.
|
||||
bool ParseColor(const nsAString& aString, nscolor* aColor);
|
||||
|
||||
static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
|
||||
|
||||
/**
|
||||
* Creates the unpremultiply lookup table, if it doesn't exist.
|
||||
*/
|
||||
void EnsureUnpremultiplyTable();
|
||||
|
||||
/**
|
||||
* Creates the premultiply lookup table, if it doesn't exist.
|
||||
*/
|
||||
void EnsurePremultiplyTable();
|
||||
|
||||
/* This function ensures there is a writable pathbuilder available, this
|
||||
* pathbuilder may be working in user space or in device space or
|
||||
* device space.
|
||||
*/
|
||||
void EnsureWritablePath();
|
||||
|
||||
// Ensures a path in UserSpace is available.
|
||||
void EnsureUserSpacePath();
|
||||
|
||||
void TransformWillUpdate();
|
||||
|
||||
// Report the fillRule has changed.
|
||||
void FillRuleChanged();
|
||||
|
||||
/**
|
||||
* Returns the surface format this canvas should be allocated using. Takes
|
||||
* into account mOpaque, platform requirements, etc.
|
||||
*/
|
||||
mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
|
||||
|
||||
void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
|
||||
double sx, double sy, double sw, double sh,
|
||||
double dx, double dy, double dw, double dh,
|
||||
PRUint8 optional_argc, mozilla::ErrorResult& error);
|
||||
|
||||
nsString& GetFont()
|
||||
{
|
||||
/* will initilize the value if not set, else does nothing */
|
||||
GetCurrentFontStyle();
|
||||
|
||||
return CurrentState().font;
|
||||
}
|
||||
|
||||
static bool
|
||||
ToHTMLImageOrCanvasOrVideoElement(nsIDOMElement* html,
|
||||
HTMLImageOrCanvasOrVideoElement& element)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(html);
|
||||
if (content) {
|
||||
if (content->IsHTML(nsGkAtoms::canvas)) {
|
||||
element.SetAsHTMLCanvasElement() =
|
||||
static_cast<nsHTMLCanvasElement*>(html);
|
||||
return true;
|
||||
}
|
||||
if (content->IsHTML(nsGkAtoms::img)) {
|
||||
element.SetAsHTMLImageElement() =
|
||||
static_cast<nsHTMLImageElement*>(html);
|
||||
return true;
|
||||
}
|
||||
if (content->IsHTML(nsGkAtoms::video)) {
|
||||
element.SetAsHTMLVideoElement() =
|
||||
static_cast<nsHTMLVideoElement*>(html);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Member vars
|
||||
PRInt32 mWidth, mHeight;
|
||||
|
||||
// This is true when the canvas is valid, false otherwise, this occurs when
|
||||
// for some reason initialization of the drawtarget fails. If the canvas
|
||||
// is invalid certain behavior is expected.
|
||||
bool mValid;
|
||||
// This is true when the canvas is valid, but of zero size, this requires
|
||||
// specific behavior on some operations.
|
||||
bool mZero;
|
||||
|
||||
bool mOpaque;
|
||||
|
||||
// This is true when the next time our layer is retrieved we need to
|
||||
// recreate it (i.e. our backing surface changed)
|
||||
bool mResetLayer;
|
||||
// This is needed for drawing in drawAsyncXULElement
|
||||
bool mIPC;
|
||||
|
||||
nsTArray<CanvasRenderingContext2DUserDataAzure*> mUserDatas;
|
||||
|
||||
// If mCanvasElement is not provided, then a docshell is
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
|
||||
// our drawing surfaces, contexts, and layers
|
||||
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
|
||||
|
||||
/**
|
||||
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
|
||||
* Redraw is called, reset to false when Render is called.
|
||||
*/
|
||||
bool mIsEntireFrameInvalid;
|
||||
/**
|
||||
* When this is set, the first call to Redraw(gfxRect) should set
|
||||
* mIsEntireFrameInvalid since we expect it will be followed by
|
||||
* many more Redraw calls.
|
||||
*/
|
||||
bool mPredictManyRedrawCalls;
|
||||
|
||||
// This is stored after GetThebesSurface has been called once to avoid
|
||||
// excessive ThebesSurface initialization overhead.
|
||||
nsRefPtr<gfxASurface> mThebesSurface;
|
||||
|
||||
/**
|
||||
* We also have a device space pathbuilder. The reason for this is as
|
||||
* follows, when a path is being built, but the transform changes, we
|
||||
* can no longer keep a single path in userspace, considering there's
|
||||
* several 'user spaces' now. We therefore transform the current path
|
||||
* into device space, and add all operations to this path in device
|
||||
* space.
|
||||
*
|
||||
* When then finally executing a render, the Azure drawing API expects
|
||||
* the path to be in userspace. We could then set an identity transform
|
||||
* on the DrawTarget and do all drawing in device space. This is
|
||||
* undesirable because it requires transforming patterns, gradients,
|
||||
* clips, etc. into device space and it would not work for stroking.
|
||||
* What we do instead is convert the path back to user space when it is
|
||||
* drawn, and draw it with the current transform. This makes all drawing
|
||||
* occur correctly.
|
||||
*
|
||||
* There's never both a device space path builder and a user space path
|
||||
* builder present at the same time. There is also never a path and a
|
||||
* path builder present at the same time. When writing proceeds on an
|
||||
* existing path the Path is cleared and a new builder is created.
|
||||
*
|
||||
* mPath is always in user-space.
|
||||
*/
|
||||
mozilla::RefPtr<mozilla::gfx::Path> mPath;
|
||||
mozilla::RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
|
||||
mozilla::RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
|
||||
bool mPathTransformWillUpdate;
|
||||
mozilla::gfx::Matrix mPathToDS;
|
||||
|
||||
/**
|
||||
* Number of times we've invalidated before calling redraw
|
||||
*/
|
||||
PRUint32 mInvalidateCount;
|
||||
static const PRUint32 kCanvasMaxInvalidateCount = 100;
|
||||
|
||||
/**
|
||||
* Returns true if a shadow should be drawn along with a
|
||||
* drawing operation.
|
||||
*/
|
||||
bool NeedToDrawShadow()
|
||||
{
|
||||
const ContextState& state = CurrentState();
|
||||
|
||||
// The spec says we should not draw shadows if the operator is OVER.
|
||||
// If it's over and the alpha value is zero, nothing needs to be drawn.
|
||||
return NS_GET_A(state.shadowColor) != 0 &&
|
||||
(state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
|
||||
}
|
||||
|
||||
mozilla::gfx::CompositionOp UsedOperation()
|
||||
{
|
||||
if (NeedToDrawShadow()) {
|
||||
// In this case the shadow rendering will use the operator.
|
||||
return mozilla::gfx::OP_OVER;
|
||||
}
|
||||
|
||||
return CurrentState().op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
*/
|
||||
nsIPresShell *GetPresShell() {
|
||||
if (mCanvasElement) {
|
||||
return mCanvasElement->OwnerDoc()->GetShell();
|
||||
}
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
mDocShell->GetPresShell(getter_AddRefs(shell));
|
||||
return shell.get();
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// text
|
||||
enum TextAlign {
|
||||
TEXT_ALIGN_START,
|
||||
TEXT_ALIGN_END,
|
||||
TEXT_ALIGN_LEFT,
|
||||
TEXT_ALIGN_RIGHT,
|
||||
TEXT_ALIGN_CENTER
|
||||
};
|
||||
|
||||
enum TextBaseline {
|
||||
TEXT_BASELINE_TOP,
|
||||
TEXT_BASELINE_HANGING,
|
||||
TEXT_BASELINE_MIDDLE,
|
||||
TEXT_BASELINE_ALPHABETIC,
|
||||
TEXT_BASELINE_IDEOGRAPHIC,
|
||||
TEXT_BASELINE_BOTTOM
|
||||
};
|
||||
|
||||
gfxFontGroup *GetCurrentFontStyle();
|
||||
|
||||
enum TextDrawOperation {
|
||||
TEXT_DRAW_OPERATION_FILL,
|
||||
TEXT_DRAW_OPERATION_STROKE,
|
||||
TEXT_DRAW_OPERATION_MEASURE
|
||||
};
|
||||
|
||||
/*
|
||||
* Implementation of the fillText, strokeText, and measure functions with
|
||||
* the operation abstracted to a flag.
|
||||
*/
|
||||
nsresult DrawOrMeasureText(const nsAString& text,
|
||||
float x,
|
||||
float y,
|
||||
const mozilla::dom::Optional<double>& maxWidth,
|
||||
TextDrawOperation op,
|
||||
float* aWidth);
|
||||
|
||||
// state stack handling
|
||||
class ContextState {
|
||||
public:
|
||||
ContextState() : textAlign(TEXT_ALIGN_START),
|
||||
textBaseline(TEXT_BASELINE_ALPHABETIC),
|
||||
lineWidth(1.0f),
|
||||
miterLimit(10.0f),
|
||||
globalAlpha(1.0f),
|
||||
shadowBlur(0.0),
|
||||
dashOffset(0.0f),
|
||||
op(mozilla::gfx::OP_OVER),
|
||||
fillRule(mozilla::gfx::FILL_WINDING),
|
||||
lineCap(mozilla::gfx::CAP_BUTT),
|
||||
lineJoin(mozilla::gfx::JOIN_MITER_OR_BEVEL),
|
||||
imageSmoothingEnabled(true)
|
||||
{ }
|
||||
|
||||
ContextState(const ContextState& other)
|
||||
: fontGroup(other.fontGroup),
|
||||
font(other.font),
|
||||
textAlign(other.textAlign),
|
||||
textBaseline(other.textBaseline),
|
||||
shadowColor(other.shadowColor),
|
||||
transform(other.transform),
|
||||
shadowOffset(other.shadowOffset),
|
||||
lineWidth(other.lineWidth),
|
||||
miterLimit(other.miterLimit),
|
||||
globalAlpha(other.globalAlpha),
|
||||
shadowBlur(other.shadowBlur),
|
||||
dash(other.dash),
|
||||
dashOffset(other.dashOffset),
|
||||
op(other.op),
|
||||
fillRule(other.fillRule),
|
||||
lineCap(other.lineCap),
|
||||
lineJoin(other.lineJoin),
|
||||
imageSmoothingEnabled(other.imageSmoothingEnabled)
|
||||
{
|
||||
for (int i = 0; i < STYLE_MAX; i++) {
|
||||
colorStyles[i] = other.colorStyles[i];
|
||||
gradientStyles[i] = other.gradientStyles[i];
|
||||
patternStyles[i] = other.patternStyles[i];
|
||||
}
|
||||
}
|
||||
|
||||
void SetColorStyle(Style whichStyle, nscolor color) {
|
||||
colorStyles[whichStyle] = color;
|
||||
gradientStyles[whichStyle] = nsnull;
|
||||
patternStyles[whichStyle] = nsnull;
|
||||
}
|
||||
|
||||
void SetPatternStyle(Style whichStyle, nsCanvasPatternAzure* pat) {
|
||||
gradientStyles[whichStyle] = nsnull;
|
||||
patternStyles[whichStyle] = pat;
|
||||
}
|
||||
|
||||
void SetGradientStyle(Style whichStyle, nsCanvasGradientAzure* grad) {
|
||||
gradientStyles[whichStyle] = grad;
|
||||
patternStyles[whichStyle] = nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true iff the given style is a solid color.
|
||||
*/
|
||||
bool StyleIsColor(Style whichStyle) const
|
||||
{
|
||||
return !(patternStyles[whichStyle] || gradientStyles[whichStyle]);
|
||||
}
|
||||
|
||||
|
||||
std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup;
|
||||
nsRefPtr<nsCanvasGradientAzure> gradientStyles[STYLE_MAX];
|
||||
nsRefPtr<nsCanvasPatternAzure> patternStyles[STYLE_MAX];
|
||||
|
||||
nsString font;
|
||||
TextAlign textAlign;
|
||||
TextBaseline textBaseline;
|
||||
|
||||
nscolor colorStyles[STYLE_MAX];
|
||||
nscolor shadowColor;
|
||||
|
||||
mozilla::gfx::Matrix transform;
|
||||
mozilla::gfx::Point shadowOffset;
|
||||
mozilla::gfx::Float lineWidth;
|
||||
mozilla::gfx::Float miterLimit;
|
||||
mozilla::gfx::Float globalAlpha;
|
||||
mozilla::gfx::Float shadowBlur;
|
||||
FallibleTArray<mozilla::gfx::Float> dash;
|
||||
mozilla::gfx::Float dashOffset;
|
||||
|
||||
mozilla::gfx::CompositionOp op;
|
||||
mozilla::gfx::FillRule fillRule;
|
||||
mozilla::gfx::CapStyle lineCap;
|
||||
mozilla::gfx::JoinStyle lineJoin;
|
||||
|
||||
bool imageSmoothingEnabled;
|
||||
};
|
||||
|
||||
nsAutoTArray<ContextState, 3> mStyleStack;
|
||||
|
||||
inline ContextState& CurrentState() {
|
||||
return mStyleStack[mStyleStack.Length() - 1];
|
||||
}
|
||||
|
||||
friend class CanvasGeneralPattern;
|
||||
friend class AdjustedTarget;
|
||||
|
||||
// other helpers
|
||||
void GetAppUnitsValues(PRUint32 *perDevPixel, PRUint32 *perCSSPixel) {
|
||||
// If we don't have a canvas element, we just return something generic.
|
||||
PRUint32 devPixel = 60;
|
||||
PRUint32 cssPixel = 60;
|
||||
|
||||
nsIPresShell *ps = GetPresShell();
|
||||
nsPresContext *pc;
|
||||
|
||||
if (!ps) goto FINISH;
|
||||
pc = ps->GetPresContext();
|
||||
if (!pc) goto FINISH;
|
||||
devPixel = pc->AppUnitsPerDevPixel();
|
||||
cssPixel = pc->AppUnitsPerCSSPixel();
|
||||
|
||||
FINISH:
|
||||
if (perDevPixel)
|
||||
*perDevPixel = devPixel;
|
||||
if (perCSSPixel)
|
||||
*perCSSPixel = cssPixel;
|
||||
}
|
||||
|
||||
friend struct nsCanvasBidiProcessorAzure;
|
||||
};
|
||||
|
||||
#endif /* nsCanvasRenderingContext2DAzure_h */
|
|
@ -19548,7 +19548,11 @@ ok(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.p
|
|||
window.CanvasRenderingContext2D.prototype.fill = 1;
|
||||
ok(window.CanvasRenderingContext2D.prototype.fill === 1, "window.CanvasRenderingContext2D.prototype.fill === 1");
|
||||
delete window.CanvasRenderingContext2D.prototype.fill;
|
||||
todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
if (IsAzureEnabled()) {
|
||||
ok(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
} else {
|
||||
todo(window.CanvasRenderingContext2D.prototype.fill === undefined, "window.CanvasRenderingContext2D.prototype.fill === undefined");
|
||||
}
|
||||
|
||||
//restore the original method to ensure that other tests can run successfully
|
||||
window.CanvasRenderingContext2D.prototype.fill = fill;
|
||||
|
|
|
@ -181,40 +181,51 @@ function continueTestPart1() {
|
|||
}
|
||||
|
||||
function continueTestPart2() {
|
||||
testPassed("read-pixels-test continueTestPart2: " + (new Date().getTime()));
|
||||
testPassed("read-pixels-test continueTestPart2: " + (new Date().getTime()));
|
||||
gl.viewport(0, 0, 1024, 1024);
|
||||
testPassed("read-pixels-test before setupTexturedQuad: " + (new Date().getTime()));
|
||||
var program = wtu.setupTexturedQuad(gl);
|
||||
testPassed("read-pixels-test after setupTexturedQuad: " + (new Date().getTime()));
|
||||
var loc = gl.getUniformLocation(program, "tex");
|
||||
gl.disable(gl.BLEND);
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
var colors = [[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255]];
|
||||
var textures = [];
|
||||
var results = [];
|
||||
testPassed("read-pixels-test before first loop: " + (new Date().getTime()));
|
||||
for (var ii = 0; ii < colors.length; ++ii) {
|
||||
gl.activeTexture(gl.TEXTURE0 + ii);
|
||||
var tex = gl.createTexture();
|
||||
testPassed("read-pixels-test first loop, ii = " + ii + ", before fillTexture: " + (new Date().getTime()));
|
||||
wtu.fillTexture(gl, tex, 1, 1, colors[ii]);
|
||||
testPassed("read-pixels-test first loop, ii = " + ii + ", after fillTexture: " + (new Date().getTime()));
|
||||
textures.push(tex);
|
||||
}
|
||||
for (var ii = 0; ii < colors.length; ++ii) {
|
||||
testPassed("read-pixels-test second loop, ii = " + ii + ": " + (new Date().getTime()));
|
||||
for (var jj = 0; jj < 300 + ii + 1; ++jj) {
|
||||
gl.uniform1i(loc, jj % 3);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
}
|
||||
var buf = new Uint8Array(4);
|
||||
testPassed("read-pixels-test second loop, before readpixels: " + (new Date().getTime()));
|
||||
gl.readPixels(512, 512, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
|
||||
testPassed("read-pixels-test second loop, after readpixels: " + (new Date().getTime()));
|
||||
results.push(buf);
|
||||
for (var kk = 0; kk < 99; ++kk) {
|
||||
gl.uniform1i(loc, (jj + kk) % 3);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
}
|
||||
testPassed("read-pixels-test second loop end: " + (new Date().getTime()));
|
||||
}
|
||||
for (var ii = 0; ii < colors.length; ++ii) {
|
||||
testPassed("read-pixels-test third loop, ii = " + ii + ": " + (new Date().getTime()));
|
||||
var buf = results[ii];
|
||||
var color = colors[ii];
|
||||
actual = [buf[0], buf[1], buf[2], buf[3]];
|
||||
expected = [color[0], color[1], color[2], color[3]];
|
||||
shouldBe("actual", "expected");
|
||||
testPassed("read-pixels-test third loop end: " + (new Date().getTime()));
|
||||
}
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors");
|
||||
|
||||
|
|
|
@ -910,11 +910,6 @@ nsDOMDataTransfer::FillInExternalDragData(TransferItem& aItem, PRUint32 aIndex)
|
|||
NS_PRECONDITION(mIsExternal, "Not an external drag");
|
||||
|
||||
if (!aItem.mData) {
|
||||
nsCOMPtr<nsITransferable> trans =
|
||||
do_CreateInstance("@mozilla.org/widget/transferable;1");
|
||||
if (!trans)
|
||||
return;
|
||||
|
||||
NS_ConvertUTF16toUTF8 utf8format(aItem.mFormat);
|
||||
const char* format = utf8format.get();
|
||||
if (strcmp(format, "text/plain") == 0)
|
||||
|
@ -926,6 +921,16 @@ nsDOMDataTransfer::FillInExternalDragData(TransferItem& aItem, PRUint32 aIndex)
|
|||
if (!dragSession)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsITransferable> trans =
|
||||
do_CreateInstance("@mozilla.org/widget/transferable;1");
|
||||
if (!trans)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
dragSession->GetSourceDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
trans->Init(doc ? doc->GetLoadContext() : nsnull);
|
||||
|
||||
trans->AddDataFlavor(format);
|
||||
dragSession->GetData(trans, aIndex);
|
||||
|
||||
|
|
|
@ -39,12 +39,10 @@ nsRegion
|
|||
nsDOMNotifyPaintEvent::GetRegion()
|
||||
{
|
||||
nsRegion r;
|
||||
bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
|
||||
if (!nsContentUtils::IsCallerTrustedForRead()) {
|
||||
return r;
|
||||
}
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
if (!isTrusted &&
|
||||
(mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
|
||||
continue;
|
||||
|
||||
r.Or(r, mInvalidateRequests[i].mRect);
|
||||
r.SimplifyOutward(10);
|
||||
}
|
||||
|
@ -98,17 +96,15 @@ nsDOMNotifyPaintEvent::GetPaintRequests(nsIDOMPaintRequestList** aResult)
|
|||
if (!requests)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
if (!isTrusted &&
|
||||
(mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
|
||||
continue;
|
||||
|
||||
nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
|
||||
if (!r)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
r->SetRequest(mInvalidateRequests[i]);
|
||||
requests->Append(r);
|
||||
if (nsContentUtils::IsCallerTrustedForRead()) {
|
||||
for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
|
||||
nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
|
||||
if (!r)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
r->SetRequest(mInvalidateRequests[i]);
|
||||
requests->Append(r);
|
||||
}
|
||||
}
|
||||
|
||||
requests.forget(aResult);
|
||||
|
|
|
@ -35,17 +35,7 @@ nsPaintRequest::GetClientRect(nsIDOMClientRect** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsPaintRequest::GetReason(nsAString& aResult)
|
||||
{
|
||||
switch (mRequest.mFlags & nsIFrame::INVALIDATE_REASON_MASK) {
|
||||
case nsIFrame::INVALIDATE_REASON_SCROLL_BLIT:
|
||||
aResult.AssignLiteral("scroll copy");
|
||||
break;
|
||||
case nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT:
|
||||
aResult.AssignLiteral("scroll repaint");
|
||||
break;
|
||||
default:
|
||||
aResult.Truncate();
|
||||
break;
|
||||
}
|
||||
aResult.AssignLiteral("repaint");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ _TEST_FILES = \
|
|||
test_bug409604.html \
|
||||
test_bug412567.html \
|
||||
test_bug426082.html \
|
||||
bug426082.html \
|
||||
test_bug427537.html \
|
||||
test_bug432698.html \
|
||||
test_bug443985.html \
|
||||
|
@ -70,6 +71,7 @@ _TEST_FILES = \
|
|||
test_bug648573.html \
|
||||
test_bug615597.html \
|
||||
test_bug656379-1.html \
|
||||
bug656379-1.html \
|
||||
test_bug656379-2.html \
|
||||
test_bug656954.html \
|
||||
test_bug659350.html \
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=426082
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 426082</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 426082 **/
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = document.getElementById("normalButtonCanvas");
|
||||
pressedButtonCanvas = document.getElementById("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = document.getElementById("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = document.getElementById("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = document.getElementById("currentSnapshot");
|
||||
button = document.getElementById("button");
|
||||
label = document.getElementById("label");
|
||||
outside = document.getElementById("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
console.log("Button rect: " + rect.left + " " + rect.top + " " + rect.right + " " + rect.bottom);
|
||||
return Array.some(region, function (r) {
|
||||
console.log("Region rect: " + r.left + " " + r.top + " " + r.right + " " + r.bottom);
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
console.log("paint");
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
console.log("painted");
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
console.log("check painted");
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
window.opener.finishTests();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
window.opener.ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,208 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=656379
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 656379</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
input[type=button] {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
input[type=button]::-moz-focus-inner { border: none; }
|
||||
|
||||
/* Make sure that normal, focused, hover+active, focused+hover+active
|
||||
buttons all have different styles so that the test keeps moving along. */
|
||||
input[type=button]:hover:active {
|
||||
background: red;
|
||||
}
|
||||
input[type=button]:focus {
|
||||
background: green;
|
||||
}
|
||||
input[type=button]:focus:hover:active {
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=656379">Mozilla Bug 656379</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
window.opener.ok(true, "Paint");
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
window.opener.ok(true, "Painted button");
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
window.opener.ok(true, "1");
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
window.opener.ok(true, "2");
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
window.opener.ok(true, "3");
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
window.opener.ok(true, "4");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
window.opener.ok(true, "5");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
window.opener.ok(true, "6");
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
window.opener.ok(true, "7");
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
window.opener.ok(true, "8");
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
window.opener.ok(true, "9");
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
window.opener.finishTests();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
window.opener.ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -9,170 +9,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=426082
|
|||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 426082 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var subwindow = window.open("./bug426082.html", "bug426082", "width=800,height=1000");
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,190 +9,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=656379
|
|||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
input[type=button] {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
input[type=button]::-moz-focus-inner { border: none; }
|
||||
|
||||
/* Make sure that normal, focused, hover+active, focused+hover+active
|
||||
buttons all have different styles so that the test keeps moving along. */
|
||||
input[type=button]:hover:active {
|
||||
background: red;
|
||||
}
|
||||
input[type=button]:focus {
|
||||
background: green;
|
||||
}
|
||||
input[type=button]:focus:hover:active {
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 426082 **/
|
||||
/** Test for Bug 656379 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var subwindow = window.open("./bug656379-1.html", "bug656379", "width=800,height=1000");
|
||||
|
||||
var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
|
||||
pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
|
||||
|
||||
function runTests() {
|
||||
normalButtonCanvas = $("normalButtonCanvas");
|
||||
pressedButtonCanvas = $("pressedButtonCanvas");
|
||||
normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
|
||||
pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
|
||||
currentSnapshot = $("currentSnapshot");
|
||||
button = $("button");
|
||||
label = $("label");
|
||||
outside = $("outside");
|
||||
SimpleTest.executeSoon(executeTests);
|
||||
}
|
||||
|
||||
function isRectContainedInRectFromRegion(rect, region) {
|
||||
return Array.some(region, function (r) {
|
||||
return rect.left >= r.left &&
|
||||
rect.top >= r.top &&
|
||||
rect.right <= r.right &&
|
||||
rect.bottom <= r.bottom;
|
||||
});
|
||||
}
|
||||
|
||||
function paintListener(e) {
|
||||
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
|
||||
gNeedsPaint = false;
|
||||
takeSnapshot(currentSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
var gNeedsPaint = false;
|
||||
function executeTests() {
|
||||
var testYielder = tests();
|
||||
function execNext() {
|
||||
try {
|
||||
if (!gNeedsPaint) {
|
||||
testYielder.next();
|
||||
button.getBoundingClientRect(); // Flush.
|
||||
gNeedsPaint = true;
|
||||
}
|
||||
SimpleTest.executeSoon(execNext);
|
||||
} catch (e) {}
|
||||
}
|
||||
execNext();
|
||||
}
|
||||
|
||||
function tests() {
|
||||
window.addEventListener("MozAfterPaint", paintListener, false);
|
||||
takeSnapshot(normalButtonCanvas);
|
||||
// Press the button.
|
||||
sendMouseEvent("mousemove", button);
|
||||
sendMouseEvent("mousedown", button);
|
||||
yield;
|
||||
takeSnapshot(pressedFocusedButtonCanvas);
|
||||
compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", button);
|
||||
yield;
|
||||
// make sure the button is focused as this doesn't happen on click on Mac
|
||||
button.focus();
|
||||
takeSnapshot(normalFocusedButtonCanvas);
|
||||
compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
|
||||
// Unfocus the button.
|
||||
sendMouseEvent("mousedown", outside);
|
||||
sendMouseEvent("mouseup", outside);
|
||||
yield;
|
||||
|
||||
// Press the label.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
|
||||
takeSnapshot(pressedButtonCanvas);
|
||||
// Move the mouse down from the label.
|
||||
sendMouseEvent("mousemove", outside);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
|
||||
// ... and up again.
|
||||
sendMouseEvent("mousemove", label);
|
||||
yield;
|
||||
compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
|
||||
// Release.
|
||||
sendMouseEvent("mouseup", label);
|
||||
yield;
|
||||
compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
|
||||
// Press the label and remove it.
|
||||
sendMouseEvent("mousemove", label);
|
||||
sendMouseEvent("mousedown", label);
|
||||
yield;
|
||||
label.parentNode.removeChild(label);
|
||||
yield;
|
||||
compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
|
||||
sendMouseEvent("mouseup", label);
|
||||
window.removeEventListener("MozAfterPaint", paintListener, false);
|
||||
function finishTests() {
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function sendMouseEvent(t, elem) {
|
||||
var r = elem.getBoundingClientRect();
|
||||
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
|
||||
}
|
||||
|
||||
function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
|
||||
var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
|
||||
if (correct) {
|
||||
if (shouldBeIdentical) {
|
||||
ok(true, msg + " - expected " + c1url);
|
||||
} else {
|
||||
ok(true, msg + " - got " + c1url + " and " + c2url);
|
||||
}
|
||||
} else {
|
||||
if (shouldBeIdentical) {
|
||||
ok(false, msg + " - expected " + c1url + " but got " + c2url);
|
||||
} else {
|
||||
ok(false, msg + " - expected something other than " + c1url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function takeSnapshot(canvas) {
|
||||
var r = buttonRect();
|
||||
var ctx = canvas.getContext("2d");
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
canvas.width = r.width + 4;
|
||||
canvas.height = r.height + 4;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
|
||||
}
|
||||
|
||||
function buttonRect() {
|
||||
return button.getBoundingClientRect();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<p><input type="button" value="Button" id="button"></p>
|
||||
<p><label for="button" id="label">Label</label></p>
|
||||
<p id="outside">Something under the label</p>
|
||||
|
||||
<canvas id="normalButtonCanvas"></canvas>
|
||||
<canvas id="pressedButtonCanvas"></canvas>
|
||||
<canvas id="normalFocusedButtonCanvas"></canvas>
|
||||
<canvas id="pressedFocusedButtonCanvas"></canvas>
|
||||
<canvas id="currentSnapshot"></canvas>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -650,35 +650,38 @@ nsHTMLCanvasElement::InvalidateCanvasContent(const gfxRect* damageRect)
|
|||
|
||||
frame->MarkLayersActive(nsChangeHint(0));
|
||||
|
||||
nsRect invalRect;
|
||||
nsRect contentArea = frame->GetContentRect();
|
||||
Layer* layer;
|
||||
if (damageRect) {
|
||||
nsIntSize size = GetWidthHeight();
|
||||
if (size.width != 0 && size.height != 0) {
|
||||
|
||||
// damageRect and size are in CSS pixels; contentArea is in appunits
|
||||
// We want a rect in appunits; so avoid doing pixels-to-appunits and
|
||||
// vice versa conversion here.
|
||||
gfxRect realRect(*damageRect);
|
||||
realRect.Scale(contentArea.width / gfxFloat(size.width),
|
||||
contentArea.height / gfxFloat(size.height));
|
||||
realRect.RoundOut();
|
||||
|
||||
// then make it a nsRect
|
||||
invalRect = nsRect(realRect.X(), realRect.Y(),
|
||||
realRect.Width(), realRect.Height());
|
||||
|
||||
invalRect = invalRect.Intersect(nsRect(nsPoint(0,0), contentArea.Size()));
|
||||
nsIntRect invalRect(realRect.X(), realRect.Y(),
|
||||
realRect.Width(), realRect.Height());
|
||||
layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
|
||||
}
|
||||
} else {
|
||||
invalRect = nsRect(nsPoint(0, 0), contentArea.Size());
|
||||
layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
|
||||
}
|
||||
invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
|
||||
|
||||
Layer* layer = frame->InvalidateLayer(invalRect, nsDisplayItem::TYPE_CANVAS);
|
||||
|
||||
if (layer) {
|
||||
static_cast<CanvasLayer*>(layer)->Updated();
|
||||
}
|
||||
|
||||
/*
|
||||
* Treat canvas invalidations as animation activity for JS. Frequently
|
||||
* invalidating a canvas will feed into heuristics and cause JIT code to be
|
||||
* kept around longer, for smoother animations.
|
||||
*/
|
||||
nsIScriptGlobalObject *scope = OwnerDoc()->GetScriptGlobalObject();
|
||||
if (scope) {
|
||||
JSObject *obj = scope->GetGlobalJSObject();
|
||||
if (obj) {
|
||||
js::NotifyAnimationActivity(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -690,7 +693,7 @@ nsHTMLCanvasElement::InvalidateCanvas()
|
|||
if (!frame)
|
||||
return;
|
||||
|
||||
frame->Invalidate(frame->GetContentRect() - frame->GetPosition());
|
||||
frame->InvalidateFrame();
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
@ -765,12 +768,8 @@ nsresult
|
|||
NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
|
||||
if (Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
|
||||
nsresult rv = NS_NewCanvasRenderingContext2DAzure(aResult);
|
||||
// If Azure fails, fall back to a classic canvas.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (AzureCanvasEnabled()) {
|
||||
return NS_NewCanvasRenderingContext2DAzure(aResult);
|
||||
}
|
||||
|
||||
return NS_NewCanvasRenderingContext2DThebes(aResult);
|
||||
|
|
|
@ -79,11 +79,10 @@ void VideoFrameContainer::Invalidate()
|
|||
}
|
||||
|
||||
if (frame) {
|
||||
nsRect contentRect = frame->GetContentRect() - frame->GetPosition();
|
||||
if (invalidateFrame) {
|
||||
frame->Invalidate(contentRect);
|
||||
frame->InvalidateFrame();
|
||||
} else {
|
||||
frame->InvalidateLayer(contentRect, nsDisplayItem::TYPE_VIDEO);
|
||||
frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,8 @@ _TEST_FILES = \
|
|||
test_bug311007.xul \
|
||||
bug311007_window.xul \
|
||||
test_principalInherit.xul \
|
||||
test_mozFrameType.xul \
|
||||
mozFrameType_window.xul \
|
||||
$(NULL)
|
||||
|
||||
_DOCSHELL_SUBHARNESS = \
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<window title="Test mozFrameType attribute"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="runTests();">
|
||||
|
||||
<html:iframe id="normalFrame"/>
|
||||
<html:iframe id="typeContentFrame" mozframetype="content"/>
|
||||
|
||||
<script type="application/javascript" src="docshell_helpers.js" />
|
||||
<script type="application/javascript"><![CDATA[
|
||||
function runTests() {
|
||||
let opener = window.opener;
|
||||
let SimpleTest = opener.wrappedJSObject.SimpleTest;
|
||||
|
||||
let Ci = Components.interfaces;
|
||||
|
||||
function getDocShellType(frame) {
|
||||
return frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.itemType;
|
||||
}
|
||||
|
||||
var normalFrame = document.getElementById("normalFrame");
|
||||
var typeContentFrame = document.getElementById("typeContentFrame");
|
||||
|
||||
SimpleTest.is(getDocShellType(normalFrame), Ci.nsIDocShellTreeItem.typeChrome,
|
||||
"normal iframe in chrome document is typeChrome");
|
||||
SimpleTest.is(getDocShellType(typeContentFrame), Ci.nsIDocShellTreeItem.typeContent,
|
||||
"iframe with mozFrameType='content' in chrome document is typeContent");
|
||||
|
||||
// Wait for the window to be closed before finishing the test
|
||||
let ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
ww.registerNotification(function(subject, topic, data) {
|
||||
if (topic == "domwindowclosed") {
|
||||
ww.unregisterNotification(arguments.callee);
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SimpleTest.finish();
|
||||
}, opener);
|
||||
}
|
||||
});
|
||||
|
||||
window.close();
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=769771
|
||||
-->
|
||||
<window title="Test mozFrameType attribute"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<title>Test mozFrameType attribute</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Test for Bug 769771 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.open("mozFrameType_window.xul", "mozFrameType",
|
||||
"chrome,width=600,height=600");
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</window>
|
|
@ -53,6 +53,7 @@ WebappsRegistry.prototype = {
|
|||
install: 'r',
|
||||
getSelf: 'r',
|
||||
getInstalled: 'r',
|
||||
getNotInstalled: 'r',
|
||||
mgmt: 'r'
|
||||
},
|
||||
|
||||
|
@ -100,8 +101,10 @@ WebappsRegistry.prototype = {
|
|||
case "Webapps:GetInstalled:Return:OK":
|
||||
Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
|
||||
break;
|
||||
case "Webapps:GetNotInstalled:Return:OK":
|
||||
Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
|
||||
break;
|
||||
case "Webapps:GetSelf:Return:KO":
|
||||
case "Webapps:GetInstalled:Return:KO":
|
||||
Services.DOMRequest.fireError(req, "ERROR");
|
||||
break;
|
||||
}
|
||||
|
@ -172,6 +175,14 @@ WebappsRegistry.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getNotInstalled: function() {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:GetNotInstalled", { origin: this._getOrigin(this._window.location.href),
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) });
|
||||
return request;
|
||||
},
|
||||
|
||||
get mgmt() {
|
||||
if (!this._mgmt)
|
||||
this._mgmt = new WebappsApplicationMgmt(this._window);
|
||||
|
@ -185,7 +196,7 @@ WebappsRegistry.prototype = {
|
|||
// nsIDOMGlobalPropertyInitializer implementation
|
||||
init: function(aWindow) {
|
||||
this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
|
||||
"Webapps:GetInstalled:Return:OK", "Webapps:GetInstalled:Return:KO",
|
||||
"Webapps:GetInstalled:Return:OK", "Webapps:GetNotInstalled:Return:OK",
|
||||
"Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
|
||||
|
||||
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
|
|
@ -35,10 +35,12 @@ XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
|||
let DOMApplicationRegistry = {
|
||||
appsFile: null,
|
||||
webapps: { },
|
||||
allAppsLaunchable: false,
|
||||
|
||||
init: function() {
|
||||
this.messages = ["Webapps:Install", "Webapps:Uninstall",
|
||||
"Webapps:GetSelf", "Webapps:GetInstalled",
|
||||
"Webapps:GetSelf",
|
||||
"Webapps:GetInstalled", "Webapps:GetNotInstalled",
|
||||
"Webapps:Launch", "Webapps:GetAll"];
|
||||
|
||||
this.messages.forEach((function(msgName) {
|
||||
|
@ -124,6 +126,9 @@ let DOMApplicationRegistry = {
|
|||
case "Webapps:GetInstalled":
|
||||
this.getInstalled(msg);
|
||||
break;
|
||||
case "Webapps:GetNotInstalled":
|
||||
this.getNotInstalled(msg);
|
||||
break;
|
||||
case "Webapps:GetAll":
|
||||
if (msg.hasPrivileges)
|
||||
this.getAll(msg);
|
||||
|
@ -296,7 +301,7 @@ let DOMApplicationRegistry = {
|
|||
let tmp = [];
|
||||
let id = this._appId(aData.origin);
|
||||
|
||||
if (id) {
|
||||
if (id && this._isLaunchable(aData.origin)) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
aData.apps.push(app);
|
||||
tmp.push({ id: id });
|
||||
|
@ -312,10 +317,10 @@ let DOMApplicationRegistry = {
|
|||
getInstalled: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
let id = this._appId(aData.origin);
|
||||
|
||||
for (id in this.webapps) {
|
||||
if (this.webapps[id].installOrigin == aData.origin) {
|
||||
for (let id in this.webapps) {
|
||||
if (this.webapps[id].installOrigin == aData.origin &&
|
||||
this._isLaunchable(aData.origin)) {
|
||||
aData.apps.push(this._cloneAppObject(this.webapps[id]));
|
||||
tmp.push({ id: id });
|
||||
}
|
||||
|
@ -328,12 +333,34 @@ let DOMApplicationRegistry = {
|
|||
}).bind(this));
|
||||
},
|
||||
|
||||
getNotInstalled: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
|
||||
for (let id in this.webapps) {
|
||||
if (this.webapps[id].installOrigin == aData.origin &&
|
||||
!this._isLaunchable(aData.origin)) {
|
||||
aData.apps.push(this._cloneAppObject(this.webapps[id]));
|
||||
tmp.push({ id: id });
|
||||
}
|
||||
}
|
||||
|
||||
this._readManifests(tmp, (function(aResult) {
|
||||
for (let i = 0; i < aResult.length; i++)
|
||||
aData.apps[i].manifest = aResult[i].manifest;
|
||||
ppmm.sendAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
getAll: function(aData) {
|
||||
aData.apps = [];
|
||||
let tmp = [];
|
||||
|
||||
for (let id in this.webapps) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
if (!this._isLaunchable(app.installOrigin))
|
||||
continue;
|
||||
|
||||
aData.apps.push(app);
|
||||
tmp.push({ id: id });
|
||||
}
|
||||
|
@ -445,6 +472,61 @@ let DOMApplicationRegistry = {
|
|||
}
|
||||
}
|
||||
this._saveApps(aCallback);
|
||||
},
|
||||
|
||||
_isLaunchable: function(aOrigin) {
|
||||
if (this.allAppsLaunchable)
|
||||
return true;
|
||||
|
||||
#ifdef XP_WIN
|
||||
let uninstallKey = Cc["@mozilla.org/windows-registry-key;1"]
|
||||
.createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
uninstallKey.open(uninstallKey.ROOT_KEY_CURRENT_USER,
|
||||
"SOFTWARE\\Microsoft\\Windows\\" +
|
||||
"CurrentVersion\\Uninstall\\" +
|
||||
aOrigin,
|
||||
uninstallKey.ACCESS_READ);
|
||||
uninstallKey.close();
|
||||
return true;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
#elifdef XP_MACOSX
|
||||
let mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"]
|
||||
.createInstance(Ci.nsIMacWebAppUtils);
|
||||
|
||||
return !!mwaUtils.pathForAppWithIdentifier(aOrigin);
|
||||
#elifdef XP_UNIX
|
||||
let env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let xdg_data_home_env = env.get("XDG_DATA_HOME");
|
||||
|
||||
let desktopINI;
|
||||
if (xdg_data_home_env != "") {
|
||||
desktopINI = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsIFile);
|
||||
desktopINI.initWithPath(xdg_data_home_env);
|
||||
}
|
||||
else {
|
||||
desktopINI = Services.dirsvc.get("Home", Ci.nsIFile);
|
||||
desktopINI.append(".local");
|
||||
desktopINI.append("share");
|
||||
}
|
||||
desktopINI.append("applications");
|
||||
|
||||
let origin = Services.io.newURI(aOrigin, null, null);
|
||||
let uniqueName = origin.scheme + ";" +
|
||||
origin.host +
|
||||
(origin.port != -1 ? ";" + origin.port : "");
|
||||
|
||||
desktopINI.append("owa-" + uniqueName + ".desktop");
|
||||
|
||||
return desktopINI.exists();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "Connection.h"
|
||||
#include "MobileConnection.h"
|
||||
#include "nsIIdleObserver.h"
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
#include "MediaManager.h"
|
||||
|
@ -650,6 +651,43 @@ GetVibrationDurationFromJsval(const jsval& aJSVal, JSContext* cx,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
Navigator::AddIdleObserver(nsIIdleObserver* aIdleObserver)
|
||||
{
|
||||
if (!nsContentUtils::IsIdleObserverAPIEnabled()) {
|
||||
NS_WARNING("The IdleObserver API has been disabled.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aIdleObserver);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED);
|
||||
if (NS_FAILED(win->RegisterIdleObserver(aIdleObserver))) {
|
||||
NS_WARNING("Failed to add idle observer.");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Navigator::RemoveIdleObserver(nsIIdleObserver* aIdleObserver)
|
||||
{
|
||||
if (!nsContentUtils::IsIdleObserverAPIEnabled()) {
|
||||
NS_WARNING("The IdleObserver API has been disabled");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aIdleObserver);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED);
|
||||
if (NS_FAILED(win->UnregisterIdleObserver(aIdleObserver))) {
|
||||
NS_WARNING("Failed to remove idle observer.");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Navigator::MozVibrate(const jsval& aPattern, JSContext* cx)
|
||||
{
|
||||
|
|
|
@ -534,6 +534,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
|
|||
|
||||
#undef None // something included above defines this preprocessor symbol, maybe Xlib headers
|
||||
#include "WebGLContext.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -4590,6 +4591,10 @@ nsDOMClassInfo::Init()
|
|||
// Non-proxy bindings
|
||||
mozilla::dom::Register(nameSpaceManager);
|
||||
|
||||
if (!AzureCanvasEnabled()) {
|
||||
nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"), NULL);
|
||||
}
|
||||
|
||||
sIsInitialized = true;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -4914,11 +4919,7 @@ nsDOMClassInfo::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
{
|
||||
PRUint32 mode_type = mode & JSACC_TYPEMASK;
|
||||
|
||||
if ((mode_type == JSACC_WATCH ||
|
||||
mode_type == JSACC_PROTO ||
|
||||
mode_type == JSACC_PARENT) &&
|
||||
sSecMan) {
|
||||
|
||||
if ((mode_type == JSACC_WATCH || mode_type == JSACC_PROTO) && sSecMan) {
|
||||
nsresult rv;
|
||||
JSObject *real_obj;
|
||||
if (wrapper) {
|
||||
|
@ -5373,11 +5374,10 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
|
|||
JSHandleId id, unsigned flags,
|
||||
JSObject **objp)
|
||||
{
|
||||
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING |
|
||||
JSRESOLVE_QUALIFIED) ||
|
||||
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_QUALIFIED) ||
|
||||
!JSID_IS_STRING(id)) {
|
||||
// Nothing to do here if we're either assigning or declaring,
|
||||
// doing a qualified resolve, or resolving a number.
|
||||
// Nothing to do here if we're assigning, doing a qualified resolve, or
|
||||
// resolving a non-string property.
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
|
|
@ -206,12 +206,10 @@ nsDOMWindowUtils::Redraw(PRUint32 aCount, PRUint32 *aDurationOut)
|
|||
nsIFrame *rootFrame = presShell->GetRootFrame();
|
||||
|
||||
if (rootFrame) {
|
||||
nsRect r(nsPoint(0, 0), rootFrame->GetSize());
|
||||
|
||||
PRIntervalTime iStart = PR_IntervalNow();
|
||||
|
||||
for (PRUint32 i = 0; i < aCount; i++)
|
||||
rootFrame->InvalidateWithFlags(r, nsIFrame::INVALIDATE_IMMEDIATE);
|
||||
rootFrame->InvalidateFrame();
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
|
||||
XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), False);
|
||||
|
@ -356,14 +354,7 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
|||
|
||||
nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
nsIContent* rootContent =
|
||||
rootScrollFrame ? rootScrollFrame->GetContent() : nsnull;
|
||||
nsRect rootDisplayport;
|
||||
bool usingDisplayport = rootContent &&
|
||||
nsLayoutUtils::GetDisplayPort(rootContent, &rootDisplayport);
|
||||
rootFrame->InvalidateWithFlags(
|
||||
usingDisplayport ? rootDisplayport : rootFrame->GetVisualOverflowRect(),
|
||||
nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
|
||||
rootFrame->InvalidateFrame();
|
||||
|
||||
// If we are hiding something that is a display root then send empty paint
|
||||
// transaction in order to release retained layers because it won't get
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsDOMStorage.h"
|
||||
#include "nsDOMOfflineResourceList.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIIdleService.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef GetClassName
|
||||
|
@ -220,6 +221,7 @@
|
|||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "prrng.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
|
@ -238,6 +240,7 @@ using mozilla::TimeDuration;
|
|||
|
||||
nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nsnull;
|
||||
bool nsGlobalWindow::sWarnedAboutWindowInternal = false;
|
||||
bool nsGlobalWindow::sIdleObserversAPIFuzzTimeDisabled = false;
|
||||
|
||||
static nsIEntropyCollector *gEntropyCollector = nsnull;
|
||||
static PRInt32 gRefCnt = 0;
|
||||
|
@ -495,7 +498,9 @@ nsDOMMozURLProperty::RevokeObjectURL(const nsAString& aURL)
|
|||
* An indirect observer object that means we don't have to implement nsIObserver
|
||||
* on nsGlobalWindow, where any script could see it.
|
||||
*/
|
||||
class nsGlobalWindowObserver MOZ_FINAL : public nsIObserver {
|
||||
class nsGlobalWindowObserver MOZ_FINAL : public nsIObserver,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
nsGlobalWindowObserver(nsGlobalWindow* aWindow) : mWindow(aWindow) {}
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -506,11 +511,19 @@ public:
|
|||
return mWindow->Observe(aSubject, aTopic, aData);
|
||||
}
|
||||
void Forget() { mWindow = nsnull; }
|
||||
NS_IMETHODIMP GetInterface(const nsIID& aIID, void** aResult)
|
||||
{
|
||||
if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)) && mWindow) {
|
||||
return mWindow->QueryInterface(aIID, aResult);
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
private:
|
||||
nsGlobalWindow* mWindow;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver, nsIObserver)
|
||||
NS_IMPL_ISUPPORTS2(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
|
||||
|
||||
nsTimeout::nsTimeout()
|
||||
{
|
||||
|
@ -628,15 +641,21 @@ NewOuterWindowProxy(JSContext *cx, JSObject *parent)
|
|||
|
||||
nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
||||
: nsPIDOMWindow(aOuterWindow),
|
||||
mIdleFuzzFactor(0),
|
||||
mIdleCallbackIndex(-1),
|
||||
mCurrentlyIdle(false),
|
||||
mAddActiveEventFuzzTime(true),
|
||||
mIsFrozen(false),
|
||||
mFullScreen(false),
|
||||
mIsClosed(false),
|
||||
mInClose(false),
|
||||
mIsClosed(false),
|
||||
mInClose(false),
|
||||
mHavePendingClose(false),
|
||||
mHadOriginalOpener(false),
|
||||
mIsPopupSpam(false),
|
||||
mBlockScriptedClosingFlag(false),
|
||||
mFireOfflineStatusChangeEventOnThaw(false),
|
||||
mNotifyIdleObserversIdleOnThaw(false),
|
||||
mNotifyIdleObserversActiveOnThaw(false),
|
||||
mCreatingInnerWindow(false),
|
||||
mIsChrome(false),
|
||||
mCleanMessageManager(false),
|
||||
|
@ -723,6 +742,9 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
Preferences::AddIntVarCache(&gMinBackgroundTimeoutValue,
|
||||
"dom.min_background_timeout_value",
|
||||
DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE);
|
||||
Preferences::AddBoolVarCache(&sIdleObserversAPIFuzzTimeDisabled,
|
||||
"dom.idle-observers-api.fuzz_time.disabled",
|
||||
false);
|
||||
}
|
||||
|
||||
if (gDumpFile == nsnull) {
|
||||
|
@ -956,7 +978,7 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
|
|||
if (mCleanedUp)
|
||||
return;
|
||||
mCleanedUp = true;
|
||||
|
||||
|
||||
mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nsnull);
|
||||
mEventTargetObjects.Clear();
|
||||
|
||||
|
@ -967,6 +989,10 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
|
|||
os->RemoveObserver(mObserver, "dom-storage2-changed");
|
||||
}
|
||||
|
||||
if (mIdleService) {
|
||||
mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
|
||||
}
|
||||
|
||||
// Drop its reference to this dying window, in case for some bogus reason
|
||||
// the object stays around.
|
||||
mObserver->Forget();
|
||||
|
@ -1024,6 +1050,11 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
|
|||
|
||||
CleanupCachedXBLHandlers(this);
|
||||
|
||||
if (mIdleTimer) {
|
||||
mIdleTimer->Cancel();
|
||||
mIdleTimer = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
|
||||
#endif
|
||||
|
@ -1073,6 +1104,13 @@ nsGlobalWindow::FreeInnerObjects()
|
|||
|
||||
ClearAllTimeouts();
|
||||
|
||||
if (mIdleTimer) {
|
||||
mIdleTimer->Cancel();
|
||||
mIdleTimer = nsnull;
|
||||
}
|
||||
|
||||
mIdleObservers.Clear();
|
||||
|
||||
mChromeEventHandler = nsnull;
|
||||
|
||||
if (mListenerManager) {
|
||||
|
@ -1236,6 +1274,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIdleService)
|
||||
|
||||
// Traverse stuff from nsPIDOMWindow
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler)
|
||||
|
@ -1247,6 +1286,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPendingStorageEvents)
|
||||
|
||||
for (PRUint32 i = 0; i < tmp->mIdleObservers.Length(); i++) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mIdleObservers[i].nsIIdleObserverPtr");
|
||||
cb.NoteXPCOMChild(tmp->mIdleObservers.ElementAt(i).mIdleObserver.get());
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
|
@ -1282,9 +1325,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mIdleService)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPendingStorageEvents)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mIdleObservers)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
struct TraceData
|
||||
|
@ -2472,6 +2518,15 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||
}
|
||||
|
||||
aVisitor.mParentTarget = GetParentTarget();
|
||||
|
||||
// Handle 'active' event.
|
||||
if (!mIdleObservers.IsEmpty() &&
|
||||
NS_IS_TRUSTED_EVENT(aVisitor.mEvent) &&
|
||||
(NS_IS_MOUSE_EVENT(aVisitor.mEvent) ||
|
||||
NS_IS_DRAG_EVENT(aVisitor.mEvent))) {
|
||||
mAddActiveEventFuzzTime = false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -8380,6 +8435,408 @@ nsGlobalWindow::FireOfflineStatusEvent()
|
|||
nsContentUtils::DispatchTrustedEvent(mDoc, eventTarget, name, true, false);
|
||||
}
|
||||
|
||||
class NotifyIdleObserverRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NotifyIdleObserverRunnable(nsIIdleObserver* aIdleObserver,
|
||||
PRUint32 aTimeInS,
|
||||
bool aCallOnidle,
|
||||
nsGlobalWindow* aIdleWindow)
|
||||
: mIdleObserver(aIdleObserver), mTimeInS(aTimeInS), mIdleWindow(aIdleWindow),
|
||||
mCallOnidle(aCallOnidle)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (mIdleWindow->ContainsIdleObserver(mIdleObserver, mTimeInS)) {
|
||||
return mCallOnidle ? mIdleObserver->Onidle() : mIdleObserver->Onactive();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIIdleObserver> mIdleObserver;
|
||||
PRUint32 mTimeInS;
|
||||
nsRefPtr<nsGlobalWindow> mIdleWindow;
|
||||
|
||||
// If false then call on active
|
||||
bool mCallOnidle;
|
||||
};
|
||||
|
||||
void
|
||||
nsGlobalWindow::NotifyIdleObserver(nsIIdleObserver* aIdleObserver,
|
||||
PRUint32 aIdleObserverTimeInS,
|
||||
bool aCallOnidle)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> caller =
|
||||
new NotifyIdleObserverRunnable(aIdleObserver, aIdleObserverTimeInS,
|
||||
aCallOnidle, this);
|
||||
if (NS_FAILED(NS_DispatchToCurrentThread(caller))) {
|
||||
NS_WARNING("Failed to dispatch thread for idle observer notification.");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsGlobalWindow::ContainsIdleObserver(nsIIdleObserver* aIdleObserver, PRUint32 aTimeInS)
|
||||
{
|
||||
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
||||
bool found = false;
|
||||
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
||||
while (iter.HasMore()) {
|
||||
IdleObserverHolder& idleObserver = iter.GetNext();
|
||||
if (idleObserver.mIdleObserver == aIdleObserver &&
|
||||
idleObserver.mTimeInS == aTimeInS) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
IdleActiveTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
nsRefPtr<nsGlobalWindow> idleWindow = static_cast<nsGlobalWindow*>(aClosure);
|
||||
MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
|
||||
idleWindow->NotifyIdleObserversOfIdleActiveEvent();
|
||||
}
|
||||
|
||||
void
|
||||
IdleObserverTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
nsRefPtr<nsGlobalWindow> idleWindow = static_cast<nsGlobalWindow*>(aClosure);
|
||||
MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
|
||||
idleWindow->HandleIdleObserverCallback();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::HandleIdleObserverCallback()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
MOZ_ASSERT(static_cast<PRUint32>(mIdleCallbackIndex) < mIdleObservers.Length(),
|
||||
"Idle callback index exceeds array bounds!");
|
||||
IdleObserverHolder idleObserver =
|
||||
mIdleObservers.ElementAt(mIdleCallbackIndex);
|
||||
NotifyIdleObserver(idleObserver.mIdleObserver,
|
||||
idleObserver.mTimeInS,
|
||||
true);
|
||||
mIdleCallbackIndex++;
|
||||
if (NS_FAILED(ScheduleNextIdleObserverCallback())) {
|
||||
NS_WARNING("Failed to set next idle observer callback.");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::ScheduleNextIdleObserverCallback()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
MOZ_ASSERT(mIdleService, "No idle service!");
|
||||
|
||||
if (mIdleCallbackIndex < 0 ||
|
||||
static_cast<PRUint32>(mIdleCallbackIndex) >= mIdleObservers.Length()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
IdleObserverHolder& idleObserver =
|
||||
mIdleObservers.ElementAt(mIdleCallbackIndex);
|
||||
|
||||
PRUint32 userIdleTimeMS = 0;
|
||||
nsresult rv = mIdleService->GetIdleTime(&userIdleTimeMS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 callbackTimeMS = 0;
|
||||
if (idleObserver.mTimeInS * 1000 > userIdleTimeMS) {
|
||||
callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS;
|
||||
}
|
||||
|
||||
mIdleTimer->Cancel();
|
||||
rv = mIdleTimer->InitWithFuncCallback(IdleObserverTimerCallback,
|
||||
this,
|
||||
callbackTimeMS,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsGlobalWindow::GetFuzzTimeMS()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
|
||||
if (sIdleObserversAPIFuzzTimeDisabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUint32 randNum = 0;
|
||||
PRSize nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
|
||||
if (nbytes != sizeof(randNum)) {
|
||||
NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
|
||||
return MAX_IDLE_FUZZ_TIME_MS;
|
||||
}
|
||||
|
||||
if (randNum > MAX_IDLE_FUZZ_TIME_MS) {
|
||||
(randNum) %= MAX_IDLE_FUZZ_TIME_MS;
|
||||
}
|
||||
|
||||
return randNum;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::ScheduleActiveTimerCallback()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
|
||||
if (!mAddActiveEventFuzzTime) {
|
||||
return NotifyIdleObserversOfIdleActiveEvent();
|
||||
}
|
||||
|
||||
nsRefPtr<nsGlobalWindow> kungFuDeathGrip(this);
|
||||
|
||||
MOZ_ASSERT(mIdleTimer);
|
||||
mIdleTimer->Cancel();
|
||||
|
||||
PRUint32 fuzzFactorInMS = GetFuzzTimeMS();
|
||||
nsresult rv = mIdleTimer->InitWithFuncCallback(IdleActiveTimerCallback,
|
||||
this,
|
||||
fuzzFactorInMS,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::ScheduleIdleTimerCallback()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
MOZ_ASSERT(mIdleTimer);
|
||||
|
||||
nsRefPtr<nsGlobalWindow> kungFuDeathGrip(this);
|
||||
mIdleTimer->Cancel();
|
||||
mIdleFuzzFactor = GetFuzzTimeMS();
|
||||
nsresult rv = mIdleTimer->InitWithFuncCallback(IdleActiveTimerCallback,
|
||||
this,
|
||||
mIdleFuzzFactor,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::NotifyIdleObserversOfIdleActiveEvent()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
|
||||
if (mCurrentlyIdle) {
|
||||
mIdleCallbackIndex = 0;
|
||||
nsresult rv = ScheduleNextIdleObserverCallback();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mIdleCallbackIndex = -1;
|
||||
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
||||
while (iter.HasMore()) {
|
||||
IdleObserverHolder& idleObserver = iter.GetNext();
|
||||
NotifyIdleObserver(idleObserver.mIdleObserver, idleObserver.mTimeInS, false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsGlobalWindow::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
|
||||
{
|
||||
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
||||
|
||||
PRUint32 i = 0;
|
||||
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
||||
while (iter.HasMore()) {
|
||||
IdleObserverHolder& idleObserver = iter.GetNext();
|
||||
if (idleObserver.mTimeInS > aIdleObserver->mTimeInS) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
MOZ_ASSERT(i <= mIdleObservers.Length(), "Array index out of bounds error.");
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
|
||||
nsresult rv;
|
||||
if (mIdleObservers.IsEmpty()) {
|
||||
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mIdleTimer) {
|
||||
mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
mIdleTimer->Cancel();
|
||||
}
|
||||
|
||||
mIdleFuzzFactor = GetFuzzTimeMS();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mIdleService);
|
||||
MOZ_ASSERT(mIdleTimer);
|
||||
|
||||
IdleObserverHolder tmpIdleObserver;
|
||||
tmpIdleObserver.mIdleObserver = aIdleObserver;
|
||||
rv = aIdleObserver->GetTime(&tmpIdleObserver.mTimeInS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_ARG_MAX(tmpIdleObserver.mTimeInS, PR_UINT32_MAX / 1000);
|
||||
NS_ENSURE_ARG_MIN(tmpIdleObserver.mTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
|
||||
|
||||
PRUint32 insertAtIndex = FindInsertionIndex(&tmpIdleObserver);
|
||||
if (insertAtIndex == mIdleObservers.Length()) {
|
||||
mIdleObservers.AppendElement(tmpIdleObserver);
|
||||
}
|
||||
else {
|
||||
mIdleObservers.InsertElementAt(insertAtIndex, tmpIdleObserver);
|
||||
}
|
||||
|
||||
bool userIsIdle = false;
|
||||
rv = nsContentUtils::IsUserIdle(MIN_IDLE_NOTIFICATION_TIME_S, &userIsIdle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Special case. First idle observer added to empty list while the user is idle.
|
||||
// Haven't received 'idle' topic notification from slow idle service yet.
|
||||
// Need to wait for the idle notification and then notify idle observers in the list.
|
||||
if (userIsIdle && mIdleCallbackIndex == -1) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mIdleCallbackIndex >= 0);
|
||||
|
||||
if (!mCurrentlyIdle) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (static_cast<PRInt32>(insertAtIndex) < mIdleCallbackIndex) {
|
||||
NotifyIdleObserver(tmpIdleObserver.mIdleObserver,
|
||||
tmpIdleObserver.mTimeInS,
|
||||
true);
|
||||
mIdleCallbackIndex++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (static_cast<PRInt32>(insertAtIndex) == mIdleCallbackIndex) {
|
||||
PRUint32 userIdleTimeMS;
|
||||
rv = mIdleService->GetIdleTime(&userIdleTimeMS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (tmpIdleObserver.mTimeInS*1000 <= userIdleTimeMS) {
|
||||
NotifyIdleObserver(tmpIdleObserver.mIdleObserver,
|
||||
tmpIdleObserver.mTimeInS,
|
||||
true);
|
||||
mIdleCallbackIndex++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mIdleTimer->Cancel();
|
||||
|
||||
rv = ScheduleNextIdleObserverCallback();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
|
||||
PRInt32* aRemoveElementIndex)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
|
||||
|
||||
*aRemoveElementIndex = 0;
|
||||
if (mIdleObservers.IsEmpty()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRUint32 aIdleObserverTimeInS;
|
||||
nsresult rv = aIdleObserver->GetTime(&aIdleObserverTimeInS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_ARG_MIN(aIdleObserverTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
|
||||
|
||||
nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
|
||||
while (iter.HasMore()) {
|
||||
IdleObserverHolder& idleObserver = iter.GetNext();
|
||||
if (idleObserver.mTimeInS == aIdleObserverTimeInS &&
|
||||
idleObserver.mIdleObserver == aIdleObserver ) {
|
||||
break;
|
||||
}
|
||||
(*aRemoveElementIndex)++;
|
||||
}
|
||||
return static_cast<PRUint32>(*aRemoveElementIndex) >= mIdleObservers.Length() ?
|
||||
NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::UnregisterIdleObserver(nsIIdleObserver* aIdleObserver)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
|
||||
MOZ_ASSERT(mIdleTimer);
|
||||
|
||||
PRInt32 removeElementIndex;
|
||||
nsresult rv = FindIndexOfElementToRemove(aIdleObserver, &removeElementIndex);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Idle observer not found in list of idle observers. No idle observer removed.");
|
||||
return NS_OK;
|
||||
}
|
||||
mIdleObservers.RemoveElementAt(removeElementIndex);
|
||||
|
||||
if (mIdleObservers.IsEmpty() && mIdleService) {
|
||||
rv = mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mIdleService = nsnull;
|
||||
|
||||
mIdleCallbackIndex = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mCurrentlyIdle) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (removeElementIndex < mIdleCallbackIndex) {
|
||||
mIdleCallbackIndex--;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (removeElementIndex != mIdleCallbackIndex) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsGlobalWindow> kungFuDeathGrip(this);
|
||||
|
||||
mIdleTimer->Cancel();
|
||||
|
||||
// If the last element in the array had been notified then decrement
|
||||
// mIdleCallbackIndex because an idle was removed from the list of
|
||||
// idle observers.
|
||||
// Example: add idle observer with time 1, 2, 3,
|
||||
// Idle notifications for idle observers with time 1, 2, 3 are complete
|
||||
// Remove idle observer with time 3 while the user is still idle.
|
||||
// The user never transitioned to active state.
|
||||
// Add an idle observer with idle time 4
|
||||
if (static_cast<PRUint32>(mIdleCallbackIndex) == mIdleObservers.Length()) {
|
||||
mIdleCallbackIndex--;
|
||||
}
|
||||
rv = ScheduleNextIdleObserverCallback();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
|
@ -8395,6 +8852,29 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
|
||||
mCurrentlyIdle = true;
|
||||
if (IsFrozen()) {
|
||||
// need to fire only one idle event while the window is frozen.
|
||||
mNotifyIdleObserversIdleOnThaw = true;
|
||||
mNotifyIdleObserversActiveOnThaw = false;
|
||||
} else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
|
||||
ScheduleIdleTimerCallback();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
|
||||
mCurrentlyIdle = false;
|
||||
if (IsFrozen()) {
|
||||
mNotifyIdleObserversActiveOnThaw = true;
|
||||
mNotifyIdleObserversIdleOnThaw = false;
|
||||
} else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
|
||||
ScheduleActiveTimerCallback();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
|
||||
nsIPrincipal *principal;
|
||||
nsresult rv;
|
||||
|
@ -8563,6 +9043,16 @@ nsGlobalWindow::FireDelayedDOMEvents()
|
|||
FireOfflineStatusEvent();
|
||||
}
|
||||
|
||||
if (mNotifyIdleObserversIdleOnThaw) {
|
||||
mNotifyIdleObserversIdleOnThaw = false;
|
||||
ScheduleIdleTimerCallback();
|
||||
}
|
||||
|
||||
if (mNotifyIdleObserversActiveOnThaw) {
|
||||
mNotifyIdleObserversActiveOnThaw = false;
|
||||
ScheduleActiveTimerCallback();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeNode> node =
|
||||
do_QueryInterface(GetDocShell());
|
||||
if (node) {
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "nsIInlineEventHandlers.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIIdleObserver.h"
|
||||
|
||||
// JS includes
|
||||
#include "jsapi.h"
|
||||
|
@ -79,6 +80,12 @@
|
|||
// dialogs up to this limit, even if they were disabled.
|
||||
#define MAX_DIALOG_COUNT 10
|
||||
|
||||
// Idle fuzz time upper limit
|
||||
#define MAX_IDLE_FUZZ_TIME_MS 90000
|
||||
|
||||
// Min idle notification time in seconds.
|
||||
#define MIN_IDLE_NOTIFICATION_TIME_S 1
|
||||
|
||||
class nsIDOMBarProp;
|
||||
class nsIDocument;
|
||||
class nsPresContext;
|
||||
|
@ -101,6 +108,7 @@ class nsDOMEventTargetHelper;
|
|||
class nsDOMOfflineResourceList;
|
||||
class nsDOMMozURLProperty;
|
||||
class nsDOMWindowUtils;
|
||||
class nsIIdleService;
|
||||
|
||||
#ifdef MOZ_DISABLE_DOMCRYPTO
|
||||
class nsIDOMCrypto;
|
||||
|
@ -195,6 +203,35 @@ private:
|
|||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
struct IdleObserverHolder
|
||||
{
|
||||
nsCOMPtr<nsIIdleObserver> mIdleObserver;
|
||||
PRUint32 mTimeInS;
|
||||
|
||||
IdleObserverHolder()
|
||||
: mTimeInS(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IdleObserverHolder);
|
||||
}
|
||||
|
||||
IdleObserverHolder(const IdleObserverHolder& aOtherIdleObserver)
|
||||
: mIdleObserver(aOtherIdleObserver.mIdleObserver), mTimeInS(aOtherIdleObserver.mTimeInS)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IdleObserverHolder);
|
||||
}
|
||||
|
||||
bool operator==(const IdleObserverHolder& aOtherIdleObserver) const {
|
||||
return
|
||||
mIdleObserver == aOtherIdleObserver.mIdleObserver &&
|
||||
mTimeInS == aOtherIdleObserver.mTimeInS;
|
||||
}
|
||||
|
||||
~IdleObserverHolder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(IdleObserverHolder);
|
||||
}
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// nsGlobalWindow: Global Object for Scripting
|
||||
//*****************************************************************************
|
||||
|
@ -546,7 +583,39 @@ public:
|
|||
void AddEventTargetObject(nsDOMEventTargetHelper* aObject);
|
||||
void RemoveEventTargetObject(nsDOMEventTargetHelper* aObject);
|
||||
|
||||
void NotifyIdleObserver(nsIIdleObserver* aIdleObserver,
|
||||
PRUint32 aIdleObserverTimeInS,
|
||||
bool aCallOnidle);
|
||||
nsresult NotifyIdleObserversOfIdleActiveEvent();
|
||||
bool ContainsIdleObserver(nsIIdleObserver* aIdleObserver, PRUint32 timeInS);
|
||||
void HandleIdleObserverCallback();
|
||||
|
||||
protected:
|
||||
// Array of idle observers that are notified of idle events.
|
||||
nsTObserverArray<IdleObserverHolder> mIdleObservers;
|
||||
|
||||
// Idle timer used for function callbacks to notify idle observers.
|
||||
nsCOMPtr<nsITimer> mIdleTimer;
|
||||
|
||||
// Idle fuzz time added to idle timer callbacks.
|
||||
PRUint32 mIdleFuzzFactor;
|
||||
|
||||
// Index in mArrayIdleObservers
|
||||
// Next idle observer to notify user idle status
|
||||
PRInt32 mIdleCallbackIndex;
|
||||
|
||||
// If false then the topic is "active"
|
||||
// If true then the topic is "idle"
|
||||
bool mCurrentlyIdle;
|
||||
|
||||
// Set to true when a fuzz time needs to be applied
|
||||
// to active notifications to the idle observer.
|
||||
bool mAddActiveEventFuzzTime;
|
||||
|
||||
nsCOMPtr <nsIIdleService> mIdleService;
|
||||
|
||||
static bool sIdleObserversAPIFuzzTimeDisabled;
|
||||
|
||||
friend class HashchangeCallback;
|
||||
friend class nsBarProp;
|
||||
|
||||
|
@ -696,6 +765,17 @@ protected:
|
|||
const nsAString &aPopupWindowName,
|
||||
const nsAString &aPopupWindowFeatures);
|
||||
void FireOfflineStatusEvent();
|
||||
|
||||
nsresult ScheduleNextIdleObserverCallback();
|
||||
PRUint32 GetFuzzTimeMS();
|
||||
nsresult ScheduleActiveTimerCallback();
|
||||
nsresult ScheduleIdleTimerCallback();
|
||||
PRUint32 FindInsertionIndex(IdleObserverHolder* aIdleObserver);
|
||||
virtual nsresult RegisterIdleObserver(nsIIdleObserver* aIdleObserverPtr);
|
||||
nsresult FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
|
||||
PRInt32* aRemoveElementIndex);
|
||||
virtual nsresult UnregisterIdleObserver(nsIIdleObserver* aIdleObserverPtr);
|
||||
|
||||
nsresult FireHashchange(const nsAString &aOldURL, const nsAString &aNewURL);
|
||||
|
||||
void FlushPendingNotifications(mozFlushType aType);
|
||||
|
@ -721,7 +801,7 @@ protected:
|
|||
nsresult GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY,
|
||||
bool aDoFlush);
|
||||
nsresult GetScrollMaxXY(PRInt32* aScrollMaxX, PRInt32* aScrollMaxY);
|
||||
|
||||
|
||||
nsresult GetOuterSize(nsIntSize* aSizeCSSPixels);
|
||||
nsresult SetOuterSize(PRInt32 aLengthCSSPixels, bool aIsWidth);
|
||||
nsRect GetInnerScreenRect();
|
||||
|
@ -798,7 +878,7 @@ protected:
|
|||
|
||||
static void NotifyDOMWindowFrozen(nsGlobalWindow* aWindow);
|
||||
static void NotifyDOMWindowThawed(nsGlobalWindow* aWindow);
|
||||
|
||||
|
||||
void ClearStatus();
|
||||
|
||||
virtual void UpdateParentTarget();
|
||||
|
@ -832,7 +912,7 @@ protected:
|
|||
// where we don't want to force creation of a new inner window since
|
||||
// we're in the middle of doing just that.
|
||||
bool mIsFrozen : 1;
|
||||
|
||||
|
||||
// These members are only used on outer window objects. Make sure
|
||||
// you never set any of these on an inner object!
|
||||
bool mFullScreen : 1;
|
||||
|
@ -850,6 +930,8 @@ protected:
|
|||
|
||||
// Track what sorts of events we need to fire when thawed
|
||||
bool mFireOfflineStatusChangeEventOnThaw : 1;
|
||||
bool mNotifyIdleObserversIdleOnThaw : 1;
|
||||
bool mNotifyIdleObserversActiveOnThaw : 1;
|
||||
|
||||
// Indicates whether we're in the middle of creating an initializing
|
||||
// a new inner window object.
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
|
||||
|
||||
#include "sampler.h"
|
||||
|
||||
|
@ -2960,8 +2961,8 @@ DoMergingCC(bool aForced)
|
|||
static PRInt32 sUnmergedNeeded = 0;
|
||||
static PRInt32 sMergedInARow = 0;
|
||||
|
||||
MOZ_ASSERT(0 <= sUnmergedNeeded <= kMinConsecutiveUnmerged);
|
||||
MOZ_ASSERT(0 <= sMergedInARow <= kMaxConsecutiveMerged);
|
||||
MOZ_ASSERT(0 <= sUnmergedNeeded && sUnmergedNeeded <= kMinConsecutiveUnmerged);
|
||||
MOZ_ASSERT(0 <= sMergedInARow && sMergedInARow <= kMaxConsecutiveMerged);
|
||||
|
||||
if (sMergedInARow == kMaxConsecutiveMerged) {
|
||||
MOZ_ASSERT(sUnmergedNeeded == 0);
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
|
||||
#define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
|
||||
#define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
|
||||
|
||||
class nsIIdleObserver;
|
||||
class nsIPrincipal;
|
||||
|
||||
// Popup control state enum. The values in this enum must go from most
|
||||
|
@ -48,8 +48,8 @@ class nsIArray;
|
|||
class nsPIWindowRoot;
|
||||
|
||||
#define NS_PIDOMWINDOW_IID \
|
||||
{ 0x41dd6a62, 0xda59, 0x46e5, \
|
||||
{ 0x9d, 0x74, 0x45, 0xf4, 0x49, 0x4e, 0x1a, 0x70 } }
|
||||
{ 0x0c4d0b84, 0xb524, 0x4572, \
|
||||
{ 0x8e, 0xd1, 0x7f, 0x78, 0x14, 0x7c, 0x4d, 0xf1 } }
|
||||
|
||||
class nsPIDOMWindow : public nsIDOMWindowInternal
|
||||
{
|
||||
|
@ -70,6 +70,9 @@ public:
|
|||
mIsActive = aActive;
|
||||
}
|
||||
|
||||
virtual nsresult RegisterIdleObserver(nsIIdleObserver* aIdleObserver) = 0;
|
||||
virtual nsresult UnregisterIdleObserver(nsIIdleObserver* aIdleObserver) = 0;
|
||||
|
||||
bool IsActive()
|
||||
{
|
||||
NS_PRECONDITION(IsOuterWindow(),
|
||||
|
|
|
@ -19,6 +19,14 @@ TEST_FILES = \
|
|||
test_screen_orientation.html \
|
||||
$(NULL)
|
||||
|
||||
CHROME_TEST_FILES = \
|
||||
test_bug715041.xul \
|
||||
test_bug715041_removal.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
||||
libs:: $(CHROME_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
||||
|
||||
|
|
|
@ -0,0 +1,760 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=715041
|
||||
-->
|
||||
<window title="Mozilla Bug 715041"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=715041"
|
||||
target="_blank">Mozilla Bug 715041</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Mock Idle Service Test for Bug 715041 **/
|
||||
SpecialPowers.setBoolPref("dom.idle-observers-api.fuzz_time.disabled", true);
|
||||
|
||||
//class mock javascript idle service
|
||||
var idleServiceObj = {
|
||||
observers: [],
|
||||
windowObservers: [],
|
||||
idleTimeInMS: 5000, //in milli seconds
|
||||
|
||||
// takes note of the idle observers added as the minimum idle observer
|
||||
// with the idle service
|
||||
timesAdded: [],
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsISupports) ||
|
||||
iid.equals(Components.interfaces.nsIFactory) ||
|
||||
iid.equals(Components.interfaces.nsIIdleService)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
createInstance: function(outer, iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
get idleTime() {
|
||||
return this.idleTimeInMS; //in milli seconds
|
||||
},
|
||||
|
||||
set idleTime(timeInMS) {
|
||||
this.idleTimeInMS = timeInMS;
|
||||
},
|
||||
|
||||
getWindowFromObserver: function(observer) {
|
||||
try {
|
||||
var interfaceRequestor = observer.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
|
||||
var window = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
return window;
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
testIdleBackService: function(observer, topic) {
|
||||
dump("\nJS FAKE IDLE SERVICE\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
|
||||
if (this.observers.length > 1) {
|
||||
this.observers[1].observer.observe(observer, topic, '\0');
|
||||
dump("JS CALLED OBSERVE FUNCTION!!!\n\n");
|
||||
}
|
||||
},
|
||||
|
||||
addIdleObserver: function(observer, time) {
|
||||
dump("\nJS FAKE IDLE SERVICE add idle observer before\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
|
||||
var window = this.getWindowFromObserver(observer);
|
||||
dump("window is: " + window + "\n");
|
||||
|
||||
if (window) {
|
||||
this.observers.push({ observer: observer, time: time, });
|
||||
addedIdleObserver = true;
|
||||
numIdleObserversAdded++;
|
||||
this.timesAdded.push(time);
|
||||
|
||||
dump ("\nMOCK IDLE SERVICE ADDING idle observer with time: " + time + "\n");
|
||||
dump("MOCK IDLE SERVICE: num idle observers added: " + numIdleObserversAdded + "\n\n");
|
||||
}
|
||||
else {
|
||||
dump("SHOULD NEVER GET HERE!");
|
||||
oldIdleService.addIdleObserver(observer, time);
|
||||
addedIdleObserver = false;
|
||||
}
|
||||
|
||||
dump("\nJS FAKE IDLE SERVICE end of add idle observer\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
},
|
||||
|
||||
removeIdleObserver: function(observer, time) {
|
||||
dump("\nJS REMOVE IDLE OBSERVER () time to be removed: " + time + "\n");
|
||||
var window = this.getWindowFromObserver(observer);
|
||||
if (!window) {
|
||||
oldIdleService.removeIdleObserver(observer, time);
|
||||
}
|
||||
else {
|
||||
var observerIndex = -1;
|
||||
for (var i=0; i<this.observers.length; i++) {
|
||||
dump("JS removeIdleObserver() observer time: " + this.observers[i].time + "\n");
|
||||
if (this.observers[i].time === time) {
|
||||
observerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (observerIndex != -1 && this.observers.length > 0) {
|
||||
numIdleObserversRemoved++;
|
||||
this.observers.splice(observerIndex, 1);
|
||||
removedIdleObserver = true;
|
||||
dump("MOCK IDLE SERVICE REMOVING idle observer with time " + time + "\n");
|
||||
dump("MOCK IDLE SERVICE numIdleObserversRemoved: " + numIdleObserversRemoved + " numIdleObserversAdded: " + numIdleObserversAdded + "\n\n");
|
||||
}
|
||||
else {
|
||||
removedIdleObserver = false;
|
||||
}
|
||||
}
|
||||
dump("\nJS FAKE IDLE SERVICE end of remove idle observer\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
},
|
||||
};
|
||||
|
||||
/** Test for Bug 715041 **/
|
||||
dump("\n\n\nJS STARTING TESTING FOR BUG 715041\n");
|
||||
|
||||
//bool variables
|
||||
var addedIdleObserver = removedIdleObserver = passed = cleanUp = false;
|
||||
|
||||
//test case enabled
|
||||
var AddOutOfOrderActiveEnabled = AddOutOfOrderIdleEnabled =
|
||||
AddShiftLocalEnabled = AddNewLocalWhileAllIdleEnabled =
|
||||
ShiftLocalTimerBackEnabled =
|
||||
AddRemoveIdleObserverWithInvalidTimeEnabled = true;
|
||||
|
||||
//msgXCount
|
||||
var msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = tcZero = currTestCaseNum = prevMsgNum =
|
||||
numIdleObserversRemoved = numIdleObserversAdded = 0;
|
||||
|
||||
//test case number
|
||||
var tcZero = 0;
|
||||
var tcAddOutOfOrderActive = 1;
|
||||
var tcAddOutOfOrderIdle = 2;
|
||||
var tcAddShiftLocal = 3;
|
||||
var tcAddNewLocalWhileAllIdle = 4;
|
||||
var tcShiftLocalTimerBack = 5;
|
||||
var tcAddRemoveIdleObserverWithInvalidTime = 6;
|
||||
|
||||
function ResetMsgCounts() {
|
||||
msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = prevMsgNum = 0;
|
||||
}
|
||||
|
||||
function ResetVars() {
|
||||
msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = prevMsgNum = 0;
|
||||
|
||||
numIdleObserversAdded = numIdleObserversRemoved = 0;
|
||||
currTestCaseNum = -1;
|
||||
addedIdleObserver = removedIdleObserver = passed = cleanUp = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* - function printMsgCounts()
|
||||
*/
|
||||
function printMsgCounts() {
|
||||
dump("\nmsg0Count: " + msg0Count +
|
||||
"\nmsg1Count: " + msg1Count +
|
||||
"\nmsg2Count: " + msg2Count +
|
||||
"\nmsg3Count: " + msg3Count +
|
||||
"\nmsg5Count: " + msg5Count +
|
||||
"\nmsg6Count: " + msg6Count +
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
function performNextTest() {
|
||||
dump("\nfunction performNextTest()\ncurrTestCaseNum: " + currTestCaseNum +
|
||||
"\ncleanUp: " + cleanUp +
|
||||
"\npassed: " + passed +
|
||||
"\nnumIdleObserversRemoved: " + numIdleObserversRemoved +
|
||||
"\nnumIdleObservesAdded: " + numIdleObserversAdded + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcZero:
|
||||
ok(passed, "Test case 0 failed clean up!");
|
||||
caseZeroCleanUp();
|
||||
break;
|
||||
case tcAddShiftLocal:
|
||||
if (cleanUp && numIdleObserversRemoved === 1) {
|
||||
passed = true;
|
||||
ok(passed, "Failed test case AddShiftLocalCleanUp()");
|
||||
if (AddNewLocalWhileAllIdleEnabled) {
|
||||
AddNewLocalWhileAllIdle();
|
||||
}
|
||||
else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tcAddNewLocalWhileAllIdle:
|
||||
ok(passed, "Failed test case: AddNewLocalWhileAllIdle()");
|
||||
AddNewLocalWhileAllIdleCleanUp();
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Place Holder.
|
||||
var idleHandler0 = function() { dump("rmsg 0, should never be used!\n"); };
|
||||
|
||||
//idleHandler1
|
||||
function idleHandler1() {
|
||||
msg1Count++;
|
||||
dump("msg 1 Count: " + msg1Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcAddOutOfOrderIdle:
|
||||
if (msg1Count === 1 && msg2Count === 1 && msg3Count === 1) {
|
||||
idleServiceObj.idleTime = 0;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "active");
|
||||
}
|
||||
else if (msg1Count === 4 && msg2Count === 4 && msg3Count === 4) {
|
||||
passed = true;
|
||||
AddOutOfOrderIdleCleanUp();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler2
|
||||
function idleHandler2() {
|
||||
msg2Count++;
|
||||
dump("msg 2 Count: " + msg2Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcZero:
|
||||
switch (msg2Count) {
|
||||
case 2:
|
||||
passed = true;
|
||||
performNextTest();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case tcAddOutOfOrderIdle:
|
||||
if (msg3Count === 1 && msg2Count === 1 && !msg1Count) {
|
||||
idleServiceObj.idleTime = 4000;
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
}
|
||||
break;
|
||||
case tcAddShiftLocal:
|
||||
if (!msg1Count && msg2Count === 1 && !msg3Count && !msg4Count) {
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
}
|
||||
AddShiftLocalCleanUp();
|
||||
break;
|
||||
case tcAddNewLocalWhileAllIdle:
|
||||
if (msg1Count === 1 && msg2Count === 2) {
|
||||
idleServiceObj.idleTime = 3500;
|
||||
window.navigator.addIdleObserver(idleObserversArray[5]);
|
||||
}
|
||||
break;
|
||||
case (tcShiftLocalTimerBack):
|
||||
if (!msg1Count && msg2Count === 1 && !msg3Count && !msg4Count && !msg5Count) {
|
||||
window.navigator.addIdleObserver(idleObserversArray[5]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler3
|
||||
function idleHandler3() {
|
||||
msg3Count++;
|
||||
dump("msg 3 Count: " + msg3Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case (tcAddOutOfOrderIdle):
|
||||
if (msg3Count === 1) {
|
||||
idleServiceObj.idleTime = 3500;
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
}
|
||||
if (msg1Count === 2 && msg2Count === 2 && msg3Count === 2) {
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
else if (msg1Count === 3 && msg2Count === 3 && msg3Count === 3) {
|
||||
AddOutOfOrderIdle();
|
||||
}
|
||||
else if (msg1Count === 3 && msg2Count === 3 && msg3Count === 4) {
|
||||
passed = true;
|
||||
AddOutOfOrderIdleCleanUp();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler4
|
||||
function idleHandler4() {
|
||||
msg4Count++;
|
||||
dump("msg 4 Count: " + msg4Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcAddOutOfOrderActive:
|
||||
if (msg1Count && msg2Count && msg3Count && msg4Count) {
|
||||
passed = true;
|
||||
ok(passed, "idleHandler4: failed AddOutOfOrderActive()");
|
||||
AddOutOfOrderActiveCleanUp();
|
||||
cleanUp = true;
|
||||
}
|
||||
break;
|
||||
case tcAddShiftLocal:
|
||||
if (msg1Count === 1 && msg3Count === 1 && msg4Count === 1) {
|
||||
idleServiceObj.idleTime = 3200;
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler5
|
||||
function idleHandler5() {
|
||||
msg5Count++;
|
||||
dump("msg 5 Count: " + msg5Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcAddNewLocalWhileAllIdle:
|
||||
if (msg1Count === 1 && msg2Count === 2 && msg5Count === 1) {
|
||||
passed = true;
|
||||
performNextTest();
|
||||
}
|
||||
break;
|
||||
case tcShiftLocalTimerBack:
|
||||
if (!msg1Count && msg2Count === 1 && !msg3Count && msg4Count === 1 && msg5Count === 1) {
|
||||
passed = true;
|
||||
ShiftLocalTimerBackCleanUp();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler6
|
||||
function idleHandler6() {
|
||||
dump("msg 6 Count: " + msg6Count + "\n");
|
||||
}
|
||||
|
||||
var idleObserversArray = [];
|
||||
idleObserversArray[0] = {time: 0, onidle: idleHandler0, onactive: idleHandler0};
|
||||
idleObserversArray[1] = {time: 1, onidle: idleHandler1, onactive: idleHandler1};
|
||||
idleObserversArray[2] = {time: 2, onidle: idleHandler2, onactive: idleHandler2};
|
||||
idleObserversArray[3] = {time: 3, onidle: idleHandler3, onactive: idleHandler3};
|
||||
idleObserversArray[4] = {time: 4, onidle: idleHandler4, onactive: idleHandler4};
|
||||
idleObserversArray[5] = {time: 5, onidle: idleHandler5, onactive: idleHandler5};
|
||||
idleObserversArray[6] = {time: 0, onidle: idleHandler6, onactive: idleHandler6};
|
||||
idleObserversArray[7] = {time: 2, onidle: null, onactive: null};
|
||||
|
||||
idleServiceObj.observers.push( {observer: idleObserversArray[0], time: 0, } );
|
||||
|
||||
/*
|
||||
* - case 0
|
||||
* - AddSingleIdleObserver
|
||||
* - takes care of adding duplicate local too
|
||||
* - user is currently idle since the
|
||||
* requested idle time of 2s < current idle time of 5000ms set below.
|
||||
*/
|
||||
function caseZero() {
|
||||
dump("\n\nTESTING CASE 0\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcZero;
|
||||
idleServiceObj.idleTime = 5000;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[2], "idle");
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
}
|
||||
|
||||
function caseZeroCleanUp() {
|
||||
dump("\ncaseZeroCleanUp()\n");
|
||||
dump("==============\n");
|
||||
ResetVars();
|
||||
currTestCaseNum = tcZero;
|
||||
cleanUp = false;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
|
||||
if (AddOutOfOrderActiveEnabled) {
|
||||
AddOutOfOrderActive();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
AddOutOfOrderActive()
|
||||
- Tests if the idle observer with the min time is always registered correctly
|
||||
with the idle service.
|
||||
*/
|
||||
function AddOutOfOrderActive() {
|
||||
dump("\n\nTESTING CASE AddOutOfOrderActive\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddOutOfOrderActive;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]); //msg3
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]); //msg4
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]); //msg1
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]); //msg2
|
||||
passed = false;
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
/*
|
||||
- AddOutOfOrderActiveCleanUp()
|
||||
*/
|
||||
function AddOutOfOrderActiveCleanUp() {
|
||||
dump("\nAddOutOfOrderActiveCleanUp()\n");
|
||||
dump("==============================\n");
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddOutOfOrderActive;
|
||||
cleanUp = false;
|
||||
idleServiceObj.idleTime = 4500;
|
||||
|
||||
for (var i=1; i<5; i++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
dump("JS AddOutOfOrderActiveCleanUp() DONE\n");
|
||||
if (AddOutOfOrderIdleEnabled) {
|
||||
AddOutOfOrderIdle();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- AddOutOfOrderIdle()
|
||||
*/
|
||||
function AddOutOfOrderIdle() {
|
||||
dump("\nAddOutOfOrderIdle()\n");
|
||||
dump("======================================================================\n");
|
||||
|
||||
dump("\nJS AddOutOfOrderIdle\n");
|
||||
dump("JS NUM OBSERVERS: " + idleServiceObj.observers.length + "\n");
|
||||
|
||||
if (!msg1Count && !msg2Count && !msg3Count) {
|
||||
ResetVars();
|
||||
}
|
||||
currTestCaseNum = tcAddOutOfOrderIdle;
|
||||
cleanUp = false;
|
||||
|
||||
if (!msg1Count && !msg2Count && !msg3Count) {
|
||||
idleServiceObj.idleTime = 3100;
|
||||
}
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
if (!msg1Count && !msg2Count && !msg3Count) {
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[3], "idle");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- AddOutOfOrderIdleCleanUp()
|
||||
*/
|
||||
function AddOutOfOrderIdleCleanUp() {
|
||||
ok(passed, "Failed test case: AddOutOfOrderIdle()");
|
||||
dump("\nAddOutOfOrderIdleCleanUp()\n");
|
||||
dump("==========================\n");
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddOutOfOrderIdle;
|
||||
cleanUp = true;
|
||||
idleServiceObj.idleTime = 4100;
|
||||
|
||||
for (var j=1; j<4; j++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[j]);
|
||||
}
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
|
||||
if (idleServiceObj.observers.length === 1) {
|
||||
passed = true;
|
||||
}
|
||||
else {
|
||||
passed = false;
|
||||
}
|
||||
ok(passed, "Failed test case: AddOutOfOrderIdleCleanUp()");
|
||||
if (AddShiftLocalEnabled) {
|
||||
AddShiftLocal();
|
||||
}
|
||||
else {
|
||||
dump("Finished AddOutOfOrderIdleCleanUp() test.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* function AddShiftLocal()
|
||||
* - user is idle
|
||||
* - check that local idle timer is shifted correctly
|
||||
* - msg 1 fired when user is idle
|
||||
* - msg 3 fired when 3000
|
||||
* - msg 2 fired immediately when added at 3200 ms
|
||||
* - msg 4 fired by local timer.
|
||||
*/
|
||||
function AddShiftLocal()
|
||||
{
|
||||
dump("\n\nTESTING CASE AddShiftLocal\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddShiftLocal;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
/*
|
||||
* function AddShiftLocalCleanUp()
|
||||
*/
|
||||
function AddShiftLocalCleanUp()
|
||||
{
|
||||
dump("\n\nTESTING CASE AddShiftLocalCleanUp\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddShiftLocal;
|
||||
|
||||
for (var i=1; i<5; i++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
dump("AddShiftLocalCleanUp() done clean up\n");
|
||||
if (AddNewLocalWhileAllIdleEnabled) {
|
||||
AddNewLocalWhileAllIdle();
|
||||
}
|
||||
else {
|
||||
dump("Finished testing AddShiftLocal()\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AddNewLocalWhileAllIdle()
|
||||
* - no local idle timer exists because all of the idle observers that were added had a requested
|
||||
* idle time of < curr user idle time and so were fired immediately. No local timer was required.
|
||||
* - now add an idle observer whose requested idle time is > current use idle time and > min idle
|
||||
* requested time in the list of idle observers.
|
||||
*/
|
||||
function AddNewLocalWhileAllIdle()
|
||||
{
|
||||
dump("\n\nTESTING CASE AddNewLocalWhileAllIdle\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddNewLocalWhileAllIdle;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function AddNewLocalWhileAllIdleCleanUp()
|
||||
{
|
||||
dump("\n\nTESTING CASE AddNewLocalWhileAllIdleCleanUp\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddNewLocalWhileAllIdle;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[5]);
|
||||
|
||||
if (ShiftLocalTimerBackEnabled) {
|
||||
ShiftLocalTimerBack();
|
||||
}
|
||||
else {
|
||||
dump("Finished testing AddNewLocalWhileAllIdle()\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ShiftLocalTimerBack()
|
||||
* - add a new idle observer whose requested time is > current user idle time
|
||||
* but < the current local timer that has been set.
|
||||
* - the local timer will need to be reset to fire the new msg added.
|
||||
* RESULT
|
||||
* - should print all of them in order
|
||||
*/
|
||||
function ShiftLocalTimerBack()
|
||||
{
|
||||
dump("\n\nTESTING CASE ShiftLocalTimerBack()\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcShiftLocalTimerBack;
|
||||
idleServiceObj.idleTime = 2100;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[2], "idle");
|
||||
}
|
||||
|
||||
function ShiftLocalTimerBackCleanUp()
|
||||
{
|
||||
dump("\n\nTESTING CASE ShiftLocalTimerBackCleanUp\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcShiftLocalTimerBack;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[5]);
|
||||
dump("ShiftLocalTimerBackCleanUp() done clean up\n");
|
||||
|
||||
try {
|
||||
componentMgr.unregisterFactory(idleServiceCID, idleServiceObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: ShiftLocalTimerBackCleanUp() Failed to unregister factory, mock idle service!\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.registerFactory(oldIdleServiceCID, "Re registering old idle service", idleServiceContractID, oldIdleServiceFactoryObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: ShiftLocalTimerBackCleanUp() Failed to register factory, original idle service!\n");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
/*
|
||||
* function AddRemoveIdleObserverWithInvalidTime()
|
||||
*/
|
||||
function AddRemoveIdleObserverWithInvalidTime()
|
||||
{
|
||||
dump("\n\nTESTING CASE AddRemoveIdleObserverWithInvalidTime()\n");
|
||||
dump("==============\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcAddRemoveIdleObserverWithInvalidTime;
|
||||
|
||||
//while idle
|
||||
idleServiceObj.idleTime = 2100;
|
||||
var rv = window.navigator.addIdleObserver(idleObserversArray[6]);
|
||||
dump("rv: " + rv + "\n");
|
||||
rv = window.navigator.removeIdleObserver(idleObserversArray[6]);
|
||||
|
||||
idleServiceObj.idleTime = 0;
|
||||
window.navigator.addIdleObserver(idleObserversArray[6]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[6]);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
try {
|
||||
var idleServiceCID = Components.ID("287075a6-f968-4516-8043-406c46f503b4");
|
||||
var idleServiceContractID = "@mozilla.org/widget/idleservice;1";
|
||||
var oldIdleService = Components.classes[idleServiceContractID].getService(Components.interfaces.nsIIdleService);
|
||||
}
|
||||
catch(ex) {
|
||||
dump("test_bug715041.xul: 1) Failed to get old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
// Registering new moch JS idle service
|
||||
var componentMgr = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: Failed to query component registrar interface.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
var oldIdleServiceFactoryObj = componentMgr.getClassObjectByContractID(idleServiceContractID, Components.interfaces.nsIFactory);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: Failed to get old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
var oldIdleServiceCID = componentMgr.contractIDToCID(idleServiceContractID);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: Failed to convert ID to CID for old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.unregisterFactory(oldIdleServiceCID, oldIdleServiceFactoryObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: Failed to unregister old idle service factory object!\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.registerFactory(idleServiceCID, "Test Simple Idle/Back Notifications", idleServiceContractID, idleServiceObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041.xul: Failed to register mock idle service.\n");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(10);
|
||||
|
||||
AddOutOfOrderActiveEnabled = true;
|
||||
AddOutOfOrderIdleEnabled = true;
|
||||
AddNewLocalWhileAllIdleEnabled = true;
|
||||
AddShiftLocalEnabled = true;
|
||||
AddIdleObserverWithInvalidTimeEnabled = false;
|
||||
|
||||
caseZero();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
|
|
@ -0,0 +1,845 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=715041
|
||||
-->
|
||||
<window title="Mozilla Bug 715041"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=715041"
|
||||
target="_blank">Mozilla Bug 715041</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Mock Idle Service Test for Bug 715041 **/
|
||||
SpecialPowers.setBoolPref("dom.idle-observers-api.fuzz_time.disabled", true);
|
||||
|
||||
try {
|
||||
var idleServiceCID = Components.ID("6f95d965-4322-4829-8a3c-5dc8a4587f4d");
|
||||
var idleServiceContractID = "@mozilla.org/widget/idleservice;1";
|
||||
var oldIdleService = Components.classes[idleServiceContractID].getService(Components.interfaces.nsIIdleService);
|
||||
}
|
||||
catch (ex) {
|
||||
dump("test_bug715041_removal.xul: failed to get old idle service 1.");
|
||||
}
|
||||
|
||||
//class mock javascript idle service
|
||||
var idleServiceObj = {
|
||||
observers: [],
|
||||
windowObservers: [],
|
||||
idleTimeInMS: 5000, //in milli seconds
|
||||
|
||||
// takes note of the idle observers added as the minimum idle observer
|
||||
//with the idle service
|
||||
timesAdded: [],
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsISupports) ||
|
||||
iid.equals(Components.interfaces.nsIFactory) ||
|
||||
iid.equals(Components.interfaces.nsIIdleService)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
createInstance: function(outer, iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
get idleTime() {
|
||||
return this.idleTimeInMS; //in milli seconds
|
||||
},
|
||||
|
||||
set idleTime(timeInMS) {
|
||||
this.idleTimeInMS = timeInMS;
|
||||
},
|
||||
|
||||
getWindowFromObserver: function(observer) {
|
||||
try {
|
||||
var interfaceRequestor = observer.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
|
||||
var window = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
return window;
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
testIdleBackService: function(observer, topic) {
|
||||
dump("\nJS FAKE IDLE SERVICE\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
|
||||
if (this.observers.length > 1) {
|
||||
this.observers[1].observer.observe(observer, topic, '\0');
|
||||
dump("JS CALLED OBSERVE FUNCTION!!!\n\n");
|
||||
}
|
||||
},
|
||||
|
||||
addIdleObserver: function(observer, time) {
|
||||
dump("\nJS FAKE IDLE SERVICE add idle observer before\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
var window = this.getWindowFromObserver(observer);
|
||||
|
||||
if (window) {
|
||||
this.observers.push({ observer: observer, time: time, });
|
||||
addedIdleObserver = true;
|
||||
numIdleObserversAdded++;
|
||||
this.timesAdded.push(time);
|
||||
dump ("\nMOCK IDLE SERVICE ADDING idle observer with time: " + time + "\n");
|
||||
dump("MOCK IDLE SERVICE: num idle observers added: " + numIdleObserversAdded + "\n\n");
|
||||
}
|
||||
else {
|
||||
dump("SHOULD NEVER GET HERE!");
|
||||
oldIdleService.addIdleObserver(observer, time);
|
||||
addedIdleObserver = false;
|
||||
}
|
||||
|
||||
dump("\nJS FAKE IDLE SERVICE end of add idle observer\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
},
|
||||
|
||||
removeIdleObserver: function(observer, time) {
|
||||
dump("\nJS REMOVE IDLE OBSERVER () time to be removed: " + time + "\n");
|
||||
var window = this.getWindowFromObserver(observer);
|
||||
if (!window) {
|
||||
oldIdleService.removeIdleObserver(observer, time);
|
||||
}
|
||||
else {
|
||||
var observerIndex = -1;
|
||||
for (var i=0; i<this.observers.length; i++) {
|
||||
dump("JS removeIdleObserver() observer time: " + this.observers[i].time + "\n");
|
||||
if (this.observers[i].time === time) {
|
||||
observerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (observerIndex != -1 && this.observers.length > 0) {
|
||||
numIdleObserversRemoved++;
|
||||
this.observers.splice(observerIndex, 1);
|
||||
removedIdleObserver = true;
|
||||
dump("MOCK IDLE SERVICE REMOVING idle observer with time " + time + "\n");
|
||||
dump("MOCK IDLE SERVICE numIdleObserversRemoved: " + numIdleObserversRemoved + " numIdleObserversAdded: " + numIdleObserversAdded + "\n\n");
|
||||
}
|
||||
else {
|
||||
removedIdleObserver = false;
|
||||
}
|
||||
}
|
||||
dump("\nJS FAKE IDLE SERVICE end of remove idle observer\n");
|
||||
dump("JS NUM OBSERVERS: " + this.observers.length + "\n");
|
||||
},
|
||||
};
|
||||
|
||||
/** Test for Bug 715041 **/
|
||||
dump("\n\n\nJS STARTING TESTING FOR BUG 715041 REMOVAL\n");
|
||||
|
||||
//bool variables
|
||||
var addedIdleObserver = removedIdleObserver = passed = cleanUp = false;
|
||||
|
||||
//msgXCount
|
||||
var msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = tcZero = currTestCaseNum = prevMsgNum = 0;
|
||||
|
||||
//test case number
|
||||
var tcRemoveHeadIdleObserverWhileActive = 0;
|
||||
var tcRemoveLocalIdleObserverWhileIdle = 1;
|
||||
var tcRemoveHeadIdleObserver = 2;
|
||||
var tcRemoveLocalIdleTimerWhileIdle = 3;
|
||||
var tcRemoveLocalIdleTimerLastElement = 4;
|
||||
var tcRemoveHeadAfterLastLocalFired = 5;
|
||||
var tcRemoveHeadIdleObserverWhileIdleCase1 = 6;
|
||||
var tcRemoveLastAddLast = 7;
|
||||
|
||||
function ResetMsgCounts() {
|
||||
msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = prevMsgNum = 0;
|
||||
}
|
||||
|
||||
function ResetVars() {
|
||||
msg0Count = msg1Count = msg2Count = msg3Count = msg4Count = msg5Count =
|
||||
msg6Count = prevMsgNum = 0;
|
||||
|
||||
numIdleObserversAdded = numIdleObserversRemoved = 0;
|
||||
currTestCaseNum = -1;
|
||||
addedIdleObserver = removedIdleObserver = passed = cleanUp = false;
|
||||
}
|
||||
|
||||
function printVariableValues()
|
||||
{
|
||||
dump("\nfunction printVariableValues()\ncurrTestCaseNum: " + currTestCaseNum +
|
||||
"\ncleanUp: " + cleanUp +
|
||||
"\npassed: " + passed +
|
||||
"\nnumIdleObserversRemoved: " + numIdleObserversRemoved +
|
||||
"\nnumIdleObservesAdded: " + numIdleObserversAdded +
|
||||
"\nmsg1Count " + msg1Count +
|
||||
"\nmsg2Count " + msg2Count +
|
||||
"\nmsg3Count " + msg3Count +
|
||||
"\nmsg4Count " + msg4Count +
|
||||
"\nmsg5Count " + msg5Count +
|
||||
"\n");
|
||||
}
|
||||
|
||||
//Place Holder.
|
||||
var idleHandler0 = function() { dump("msg 0, should never be used!\n"); };
|
||||
|
||||
//idleHandler1
|
||||
function idleHandler1() {
|
||||
msg1Count++;
|
||||
dump("msg 1 Count: " + msg1Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcRemoveHeadIdleObserver:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count && !msg5Count) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
}
|
||||
break;
|
||||
case tcRemoveLocalIdleObserverWhileIdle:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
}
|
||||
break;
|
||||
case tcRemoveLocalIdleTimerWhileIdle:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count) {
|
||||
idleServiceObj.idleTime = 2000;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
}
|
||||
break;
|
||||
case tcRemoveHeadIdleObserverWhileIdleCase1:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count) {
|
||||
for (var i=1; i<4; i++) {
|
||||
window.navigator.addIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
|
||||
idleServiceObj.idleTime = 1200;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
}
|
||||
break;
|
||||
case tcRemoveLocalIdleTimerLastElement:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count && !msg5Count) {
|
||||
idleServiceObj.idleTime = 1500;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
idleServiceObj.idleTime = 1700;
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
idleServiceObj.idleTime = 2000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[2], "idle");
|
||||
}
|
||||
break;
|
||||
case tcRemoveHeadAfterLastLocalFired:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && !msg4Count && !msg5Count) {
|
||||
dump("idle handler 1: case tcRemoveHeadAfterLastLocalFired:\n");
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
}
|
||||
break;
|
||||
case tcRemoveLastAddLast:
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler2
|
||||
function idleHandler2() {
|
||||
msg2Count++;
|
||||
dump("msg 2 Count: " + msg2Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcRemoveLocalIdleTimerLastElement:
|
||||
if (msg1Count === 1 && msg2Count === 1 && !msg3Count && !msg4Count) {
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler3
|
||||
function idleHandler3() {
|
||||
msg3Count++;
|
||||
dump("msg 3 Count: " + msg3Count + "\n");
|
||||
passed = false;
|
||||
switch (currTestCaseNum) {
|
||||
case tcRemoveHeadIdleObserverWhileActive:
|
||||
if (!msg1Count && msg2Count === 1 && msg3Count === 1) {
|
||||
passed = true;
|
||||
}
|
||||
dump("idleHandler3: passed: " + passed + "\n");
|
||||
RemoveHeadIdleObserverWhileActiveCleanUp();
|
||||
break;
|
||||
case tcRemoveHeadIdleObserverWhileIdleCase1:
|
||||
if (msg3Count != 2 && msg3Count != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg1Count === 2 && msg2Count === 2 && msg3Count === 2 && !msg4Count) {
|
||||
passed = true;
|
||||
ok(passed, "Failed test case remove head idle observer while idle case 1, part 1.\n");
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "active");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg1Count === 3 && msg2Count === 4 && msg3Count === 4 &&
|
||||
!msg4Count && !msg5Count) {
|
||||
passed = true;
|
||||
}
|
||||
RemoveHeadIdleObserverWhileIdleCase1CleanUp();
|
||||
break;
|
||||
case tcRemoveLastAddLast:
|
||||
if (msg1Count === 1 && msg2Count === 1 && msg3Count === 1
|
||||
&& !msg4Count && !msg5Count) {
|
||||
idleServiceObj.idleTime = 3200;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
idleServiceObj.idleTime = 3500;
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case tcRemoveHeadAfterLastLocalFired:
|
||||
if (msg3Count === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg1Count === 2 && msg2Count === 2 && msg3Count === 2 && msg4Count === 1) {
|
||||
passed = true;
|
||||
}
|
||||
RemoveHeadAfterLastLocalFiredCleanUp();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler4
|
||||
function idleHandler4() {
|
||||
msg4Count++;
|
||||
dump("msg 4 Count: " + msg4Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
case tcRemoveLocalIdleObserverWhileIdle:
|
||||
if (msg1Count === 1 && !msg2Count && msg3Count === 1 && msg4Count === 1) {
|
||||
passed = true;
|
||||
RemoveLocalIdleObserverWhileIdleCleanUp();
|
||||
}
|
||||
break;
|
||||
case tcRemoveHeadIdleObserver:
|
||||
printVariableValues();
|
||||
if (msg1Count === 1 && msg2Count === 1 && msg3Count === 1 && msg4Count === 1) {
|
||||
passed = true;
|
||||
RemoveHeadIdleObserverCleanUp();
|
||||
}
|
||||
break;
|
||||
case tcRemoveLocalIdleTimerWhileIdle:
|
||||
if (msg1Count === 1 && !msg2Count && !msg3Count && msg4Count === 1) {
|
||||
passed = true;
|
||||
RemoveLocalIdleTimerWhileIdleCleanUp();
|
||||
}
|
||||
break
|
||||
case tcRemoveLocalIdleTimerLastElement:
|
||||
if (msg1Count === 1 && msg2Count === 1 && !msg3Count && msg4Count === 1) {
|
||||
passed = true;
|
||||
ok(passed, "Failed test case remove local idle timer last element.\n");
|
||||
RemoveLocalIdleTimerLastElementCleanUp();
|
||||
}
|
||||
break;
|
||||
case tcRemoveHeadAfterLastLocalFired:
|
||||
if (msg1Count === 1 && msg2Count === 1 && msg3Count === 1 && msg4Count === 1) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
passed = true;
|
||||
ok(passed, "Failed remove head after last local fired.\n");
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "active");
|
||||
}
|
||||
break;
|
||||
case tcRemoveLastAddLast:
|
||||
if (msg1Count === 1 && msg2Count === 1 && msg3Count === 1 && msg4Count == 1) {
|
||||
idleServiceObj.idleTime = 4100;
|
||||
passed = true;
|
||||
RemoveLastAddLastCleanUp();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler5
|
||||
function idleHandler5() {
|
||||
msg5Count++;
|
||||
dump("msg 5 Count: " + msg5Count + "\n");
|
||||
|
||||
switch (currTestCaseNum) {
|
||||
|
||||
default:
|
||||
//do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//idleHandler6
|
||||
function idleHandler6() {
|
||||
dump("msg 6 Count: " + msg6Count + "\n");
|
||||
}
|
||||
|
||||
var idleObserversArray = [];
|
||||
idleObserversArray[0] = {time: 0, onidle: idleHandler0, onactive: idleHandler0};
|
||||
idleObserversArray[1] = {time: 1, onidle: idleHandler1, onactive: idleHandler1};
|
||||
idleObserversArray[2] = {time: 2, onidle: idleHandler2, onactive: idleHandler2};
|
||||
idleObserversArray[3] = {time: 3, onidle: idleHandler3, onactive: idleHandler3};
|
||||
idleObserversArray[4] = {time: 4, onidle: idleHandler4, onactive: idleHandler4};
|
||||
idleObserversArray[5] = {time: 5, onidle: idleHandler5, onactive: idleHandler5};
|
||||
idleObserversArray[6] = {time: 0, onidle: idleHandler6, onactive: idleHandler6};
|
||||
|
||||
//observers array space holder at index zero
|
||||
idleServiceObj.observers.push( {observer: idleObserversArray[0], time: 0, } );
|
||||
|
||||
/*
|
||||
* - function RemoveHeadIdleObserverWhileActive1()
|
||||
* - Remove head idle observer before the head idle notification is fired by the
|
||||
* idle service. I.e. remove the head idle observer while the user is active.
|
||||
* - RESULT: prints 2 in 2ms, 3
|
||||
*/
|
||||
function RemoveHeadIdleObserverWhileActive() {
|
||||
dump("\n\nTESTING CASE RemoveHeadIdleObserverWhileActive\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserverWhileActive;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
dump("test_bug715041_removal.xul: RemoveHeadIdleObserverWhileActive() idle time " + idleServiceObj.idleTime + "\n");
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
|
||||
idleServiceObj.idleTime = 800;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[2], "idle");
|
||||
}
|
||||
|
||||
function RemoveHeadIdleObserverWhileActiveCleanUp() {
|
||||
dump("\nRemoveHeadIdleObserverWhileActiveCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
dump("Passed: " + passed + "\n");
|
||||
ok(passed, "Failed test case: RemoveHeadIdleObserverWhileActive");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserverWhileActive;
|
||||
idleServiceObj.idleTime = 3500;
|
||||
|
||||
for (var i=2; i<4; i++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
|
||||
dump("JS RemoveHeadIdleObserverWhileActiveCleanUp() DONE\n");
|
||||
if (RemoveLocalIdleObserverWhileIdleEnabled) {
|
||||
RemoveLocalIdleObserverWhileIdle();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* function RemoveLocalIdleObserverWhileIdle()
|
||||
* Remove local observer before the local oberver at index 1 is triggered while
|
||||
* the user is idle.
|
||||
* RESULT: should print 1, 3, 4
|
||||
*/
|
||||
function RemoveLocalIdleObserverWhileIdle() {
|
||||
dump("\n\nTESTING CASE RemoveLocalIdleObserverWhileIdle\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLocalIdleObserverWhileIdle;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveLocalIdleObserverWhileIdleCleanUp() {
|
||||
dump("\nRemoveLocalIdleObserverWhileIdleCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveLocalIdleObserverWhileIdleCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserverWhileActive;
|
||||
idleServiceObj.idleTime = 3500;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
|
||||
dump("JS RemoveLocalIdleObserverWhileIdleCleanUp() DONE\n");
|
||||
if (RemoveHeadIdleObserverEnabled) {
|
||||
RemoveHeadIdleObserver();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* function RemoveHeadIdleObserver()
|
||||
* Remove head idle observer while the user has been idle for 2400 ms.
|
||||
* - RESULT: prints 1, 2, remove 2, 3, 4
|
||||
*/
|
||||
function RemoveHeadIdleObserver() {
|
||||
dump("\n\nTESTING CASE RemoveHeadIdleObserver\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserver;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveHeadIdleObserverCleanUp() {
|
||||
dump("\nRemoveHeadIdleObserverCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveHeadIdleObserverCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserver;
|
||||
idleServiceObj.idleTime = 3500;
|
||||
|
||||
for (var i=2; i<5; i++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
|
||||
dump("JS RemoveHeadIdleObserverCleanUp() DONE\n");
|
||||
if (RemoveLocalIdleTimerWhileIdleEnabled) {
|
||||
RemoveLocalIdleTimerWhileIdle();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RemoveLocalIdleTimerWhileIdle()
|
||||
* - Removes the idle observer that is also set as the current local idle timer callback
|
||||
* local idle observer being removed is NOT at index 1!
|
||||
* - RESULT: should trigger 1 in 1ms and 4 in 4ms
|
||||
*/
|
||||
function RemoveLocalIdleTimerWhileIdle()
|
||||
{
|
||||
dump("\n\nTESTING CASE RemoveLocalIdleTimerWhileIdle\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLocalIdleTimerWhileIdle;
|
||||
idleServiceObj.idleTime = 500;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[3]);
|
||||
window.navigator.addIdleObserver(idleObserversArray[4]);
|
||||
|
||||
idleServiceObj.idleTime = 1000;
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveLocalIdleTimerWhileIdleCleanUp()
|
||||
{
|
||||
dump("\nRemoveLocalIdleTimerWhileIdleCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveLocalIdleTimerWhileIdleCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLocalIdleTimerWhileIdle;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
|
||||
dump("JS RemoveLocalIdleTimerWhileIdleCleanUp() DONE\n");
|
||||
if (RemoveLocalIdleTimerLastElementEnabled) {
|
||||
RemoveLocalIdleTimerLastElement();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* function RemoveLocalIdleTimerLastElement()
|
||||
*/
|
||||
function RemoveLocalIdleTimerLastElement()
|
||||
{
|
||||
dump("\n\nTESTING CASE RemoveLocalIdleTimerLastElement\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLocalIdleTimerLastElement;
|
||||
idleServiceObj.idleTime = 1200;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveLocalIdleTimerLastElementCleanUp() {
|
||||
dump("\nRemoveLocalIdleTimerLastElementCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveLocalIdleTimerLastElementCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLocalIdleTimerLastElement;
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
|
||||
dump("JS RemoveLocalIdleTimerLastElementCleanUp() DONE\n");
|
||||
if (RemoveHeadAfterLastLocalFiredEnabled) {
|
||||
RemoveHeadAfterLastLocalFired();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- Remove the head after the last local idle timer has been fired
|
||||
- add 1 2 3 4
|
||||
- after 4 has been notified, removed idle observer with time 4
|
||||
- send a back topic
|
||||
- message notification should be 1, 2, 3.
|
||||
*/
|
||||
function RemoveHeadAfterLastLocalFired()
|
||||
{
|
||||
dump("\n\nTESTING CASE RemoveHeadAfterLastLocalFired\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadAfterLastLocalFired;
|
||||
idleServiceObj.idleTime = 1200;
|
||||
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveHeadAfterLastLocalFiredCleanUp() {
|
||||
dump("\RemoveHeadAfterLastLocalFiredCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveHeadAfterLastLocalFiredCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadAfterLastLocalFired;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
|
||||
dump("JS RemoveHeadAfterLastLocalFiredCleanUp() DONE\n");
|
||||
if (RemoveHeadIdleObserverWhileIdleCase1Enabled) {
|
||||
RemoveHeadIdleObserverWhileIdleCase1();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveHeadIdleObserverWhileIdleCase1() {
|
||||
dump("\n\nTESTING CASE RemoveHeadIdleObserverWhileIdleCase1\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserverWhileIdleCase1;
|
||||
idleServiceObj.idleTime = 1000;
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveHeadIdleObserverWhileIdleCase1CleanUp() {
|
||||
dump("\nRemoveHeadIdleObserverWhileIdleCase1CleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveHeadIdleObserverWhileIdleCase1CleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveHeadIdleObserverWhileIdleCase1;
|
||||
|
||||
for (var i=1; i<4; i++) {
|
||||
window.navigator.removeIdleObserver(idleObserversArray[i]);
|
||||
}
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[3]);
|
||||
|
||||
dump("JS RemoveHeadIdleObserverWhileIdleCase1CleanUp() DONE\n");
|
||||
if (RemoveLastAddLastEnabled) {
|
||||
RemoveLastAddLast();
|
||||
}
|
||||
else {
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* - RemoveLastAddLast()
|
||||
*
|
||||
* - User is currently idle.
|
||||
* - Add callback 1, 2, 3,
|
||||
* - Remove callback 3 after 3200 MS. I.e. after callback 3 has been notified.
|
||||
* - Add callback 4 after 3500 MS
|
||||
* - Output: 1, 2, 3, 4
|
||||
*/
|
||||
function RemoveLastAddLast()
|
||||
{
|
||||
dump("\n\nTESTING CASE RemoveLastAddLast()\n");
|
||||
dump("=================================\n");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLastAddLast;
|
||||
idleServiceObj.idleTime = 1000;
|
||||
window.navigator.addIdleObserver(idleObserversArray[1]);
|
||||
idleServiceObj.testIdleBackService(idleObserversArray[1], "idle");
|
||||
}
|
||||
|
||||
function RemoveLastAddLastCleanUp()
|
||||
{
|
||||
dump("\RemoveLastAddLastCleanUp()\n");
|
||||
dump("=====================================\n");
|
||||
|
||||
ok(passed, "Failed test case: RemoveLastAddLastCleanUp()");
|
||||
|
||||
ResetVars();
|
||||
currTestCaseNum = tcRemoveLastAddLast;
|
||||
|
||||
window.navigator.removeIdleObserver(idleObserversArray[1]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[2]);
|
||||
window.navigator.removeIdleObserver(idleObserversArray[4]);
|
||||
|
||||
if (numIdleObserversRemoved === 1 && !numIdleObserversAdded) {
|
||||
ok(true, "Failed test case: RemoveLastAddLastCleanUp()");
|
||||
}
|
||||
else {
|
||||
ok(false, "Failed test case: RemoveLastAddLastCleanUp()");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
componentMgr.unregisterFactory(idleServiceCID, idleServiceObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: RemoveLastAddLastCleanUp() Failed to unregister factory, mock idle service!\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.registerFactory(oldIdleServiceCID, "Re registering old idle service", idleServiceContractID, oldIdleServiceFactoryObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: RemoveLastAddLastCleanUp() Failed to register factory, original idle service!\n");
|
||||
}
|
||||
|
||||
dump("JS RemoveLastAddLastCleanUp() DONE\n");
|
||||
dump("Finishing testing idle API.\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
// Registering new moch JS idle service
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(10);
|
||||
|
||||
try {
|
||||
var idleServiceCID = Components.ID("0fdc1bbf-3868-4660-9855-0c2e376922bc");
|
||||
var idleServiceContractID = "@mozilla.org/widget/idleservice;1";
|
||||
var oldIdleService = Components.classes[idleServiceContractID].getService(Components.interfaces.nsIIdleService);
|
||||
}
|
||||
catch(ex) {
|
||||
dump("test_bug715041_removal.xul: 1) Failed to get old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
// Registering new moch JS idle service
|
||||
var componentMgr = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: Failed to query component registrar interface.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
var oldIdleServiceFactoryObj = componentMgr.getClassObjectByContractID(idleServiceContractID, Components.interfaces.nsIFactory);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: Failed to get old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
var oldIdleServiceCID = componentMgr.contractIDToCID(idleServiceContractID);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041._removalxul: Failed to convert ID to CID for old idle service.\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.unregisterFactory(oldIdleServiceCID, oldIdleServiceFactoryObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: Failed to unregister old idle service factory object!\n");
|
||||
}
|
||||
|
||||
try {
|
||||
componentMgr.registerFactory(idleServiceCID, "Test Simple Idle/Back Notifications", idleServiceContractID, idleServiceObj);
|
||||
}
|
||||
catch(err) {
|
||||
dump("test_bug715041_removal.xul: Failed to register mock idle service.\n");
|
||||
}
|
||||
|
||||
//test case enabled
|
||||
var RemoveLocalIdleObserverWhileIdleEnabled = true;
|
||||
var RemoveHeadIdleObserverEnabled = true;
|
||||
var RemoveLocalIdleTimerWhileIdleEnabled = true;
|
||||
var RemoveLocalIdleTimerLastElementEnabled = true;
|
||||
var RemoveHeadAfterLastLocalFiredEnabled = true;
|
||||
var RemoveHeadIdleObserverWhileIdleCase1Enabled = true;
|
||||
var RemoveLastAddLastEnabled = true;
|
||||
|
||||
RemoveHeadIdleObserverWhileActive();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "xpcpublic.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
// nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
|
||||
// try to use it without fixing that first.
|
||||
|
@ -187,7 +188,7 @@ inline nsresult
|
|||
UnwrapObject(JSContext* cx, JSObject* obj, U& value)
|
||||
{
|
||||
return UnwrapObject<static_cast<prototypes::ID>(
|
||||
PrototypeIDMap<T>::PrototypeID)>(cx, obj, value);
|
||||
PrototypeIDMap<T>::PrototypeID), T>(cx, obj, value);
|
||||
}
|
||||
|
||||
const size_t kProtoOrIfaceCacheCount =
|
||||
|
|
|
@ -68,6 +68,40 @@ DOMInterfaces = {
|
|||
'castable': False
|
||||
}],
|
||||
|
||||
'CanvasRenderingContext2D': [
|
||||
{
|
||||
'nativeType': 'nsCanvasRenderingContext2DAzure',
|
||||
# Making this non-prefable requires that we ensure that nothing takes this
|
||||
# type as an argument or that the non-Azure variant is removed.
|
||||
'prefable': True,
|
||||
'infallible': {
|
||||
'all': [
|
||||
'canvas', 'save', 'restore', 'globalAlpha', 'shadowOffsetX',
|
||||
'shadowOffsetY', 'shadowBlur', 'shadowColor', 'clearRect',
|
||||
'fillRect', 'strokeRect', 'beginPath', 'fill', 'stroke', 'clip',
|
||||
'isPointInPath', 'lineWidth', 'lineCap', 'miterLimit', 'textAlign',
|
||||
'textBaseline', 'closePath', 'moveTo', 'lineTo', 'quadraticCurveTo',
|
||||
'bezierCurveTo', 'rect', 'mozFillRule', 'mozDashOffset',
|
||||
'mozImageSmoothingEnabled'
|
||||
],
|
||||
'setterOnly': [
|
||||
'strokeStyle', 'fillStyle', 'lineJoin'
|
||||
],
|
||||
'getterOnly': [
|
||||
'font', 'mozTextStyle'
|
||||
]
|
||||
},
|
||||
'implicitJSContext': [
|
||||
'createImageData', 'getImageData', 'putImageData', 'strokeStyle',
|
||||
'fillStyle', 'mozDash'
|
||||
],
|
||||
'resultNotAddRefed': [ 'canvas' ],
|
||||
'binaryNames': {
|
||||
'mozImageSmoothingEnabled': 'imageSmoothingEnabled',
|
||||
'mozFillRule': 'fillRule'
|
||||
}
|
||||
}],
|
||||
|
||||
'Document': [
|
||||
{
|
||||
'nativeType': 'nsIDocument',
|
||||
|
@ -357,7 +391,11 @@ def addExternalHTMLElement(element):
|
|||
addExternalHTMLElement('HTMLCanvasElement')
|
||||
addExternalHTMLElement('HTMLImageElement')
|
||||
addExternalHTMLElement('HTMLVideoElement')
|
||||
addExternalIface('CanvasGradient', headerFile='nsIDOMCanvasRenderingContext2D.h')
|
||||
addExternalIface('CanvasPattern', headerFile='nsIDOMCanvasRenderingContext2D.h')
|
||||
addExternalIface('HitRegionOptions', nativeType='nsISupports')
|
||||
addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
|
||||
addExternalIface('TextMetrics', headerFile='nsIDOMCanvasRenderingContext2D.h')
|
||||
addExternalIface('WebGLActiveInfo', nativeType='mozilla::WebGLActiveInfo',
|
||||
headerFile='WebGLContext.h')
|
||||
addExternalIface('WebGLBuffer', nativeType='mozilla::WebGLBuffer',
|
||||
|
@ -379,3 +417,5 @@ addExternalIface('WebGLShaderPrecisionFormat',
|
|||
headerFile='WebGLContext.h')
|
||||
addExternalIface('WebGLTexture', nativeType='mozilla::WebGLTexture',
|
||||
headerFile='WebGLContext.h')
|
||||
addExternalIface('Window')
|
||||
addExternalIface('XULElement')
|
||||
|
|
|
@ -75,6 +75,7 @@ EXPORTS_$(binding_include_path) = \
|
|||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
|
||||
-I$(topsrcdir)/js/xpconnect/wrappers \
|
||||
-I$(topsrcdir)/content/canvas/src \
|
||||
-I$(topsrcdir)/content/html/content/src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -51,21 +51,16 @@ def enum(*names):
|
|||
return Foo()
|
||||
|
||||
class WebIDLError(Exception):
|
||||
def __init__(self, message, location, warning=False, extraLocations=[]):
|
||||
def __init__(self, message, locations, warning=False):
|
||||
self.message = message
|
||||
self.location = location
|
||||
self.locations = [str(loc) for loc in locations]
|
||||
self.warning = warning
|
||||
self.extraLocations = [str(loc) for loc in extraLocations]
|
||||
|
||||
def __str__(self):
|
||||
extraLocationsStr = (
|
||||
"" if len(self.extraLocations) == 0 else
|
||||
"\n" + "\n".join(self.extraLocations))
|
||||
return "%s: %s%s%s%s" % (self.warning and 'warning' or 'error',
|
||||
return "%s: %s%s%s" % (self.warning and 'warning' or 'error',
|
||||
self.message,
|
||||
", " if self.location else "",
|
||||
self.location,
|
||||
extraLocationsStr)
|
||||
", " if len(self.locations) != 0 else "",
|
||||
"\n".join(self.locations))
|
||||
|
||||
class Location(object):
|
||||
def __init__(self, lexer, lineno, lexpos, filename):
|
||||
|
@ -111,7 +106,7 @@ class Location(object):
|
|||
|
||||
class BuiltinLocation(object):
|
||||
def __init__(self, text):
|
||||
self.msg = text
|
||||
self.msg = text + "\n"
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, BuiltinLocation) and \
|
||||
|
@ -230,7 +225,7 @@ class IDLScope(IDLObject):
|
|||
|
||||
raise WebIDLError(
|
||||
"Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
|
||||
% (identifier.name, str(self), conflictdesc), "")
|
||||
% (identifier.name, str(self), conflictdesc), [])
|
||||
|
||||
def _lookupIdentifier(self, identifier):
|
||||
return self._dict[identifier.name]
|
||||
|
@ -272,12 +267,12 @@ class IDLUnresolvedIdentifier(IDLObject):
|
|||
|
||||
if name[:2] == "__" and not allowDoubleUnderscore:
|
||||
raise WebIDLError("Identifiers beginning with __ are reserved",
|
||||
location)
|
||||
[location])
|
||||
if name[0] == '_' and not allowDoubleUnderscore:
|
||||
name = name[1:]
|
||||
if name in ["prototype", "constructor", "toString"] and not allowForbidden:
|
||||
raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
|
||||
location)
|
||||
[location])
|
||||
|
||||
self.name = name
|
||||
|
||||
|
@ -334,7 +329,8 @@ class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
|
|||
try:
|
||||
scope._lookupIdentifier(self.identifier)
|
||||
except:
|
||||
raise WebIDLError("Unresolved type '%s'." % self.identifier, self.location)
|
||||
raise WebIDLError("Unresolved type '%s'." % self.identifier,
|
||||
[self.location])
|
||||
|
||||
obj = self.identifier.resolve(scope, None)
|
||||
return scope.lookupIdentifier(obj)
|
||||
|
@ -443,15 +439,13 @@ class IDLInterface(IDLObjectWithScope):
|
|||
"non-callback interface %s" %
|
||||
(self.identifier.name,
|
||||
self.parent.identifier.name),
|
||||
self.location,
|
||||
extraLocations=[self.parent.location])
|
||||
[self.location, self.parent.location])
|
||||
elif self.parent.isCallback():
|
||||
raise WebIDLError("Non-callback interface %s inheriting from "
|
||||
"callback interface %s" %
|
||||
(self.identifier.name,
|
||||
self.parent.identifier.name),
|
||||
self.location,
|
||||
extraLocations=[self.parent.location])
|
||||
[self.location, self.parent.location])
|
||||
|
||||
for iface in self.implementedInterfaces:
|
||||
iface.finish(scope)
|
||||
|
@ -460,8 +454,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
if cycleInGraph:
|
||||
raise WebIDLError("Interface %s has itself as ancestor or "
|
||||
"implemented interface" % self.identifier.name,
|
||||
self.location,
|
||||
extraLocations=[cycleInGraph.location])
|
||||
[self.location, cycleInGraph.location])
|
||||
|
||||
if self.isCallback():
|
||||
# "implements" should have made sure we have no
|
||||
|
@ -505,8 +498,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
raise WebIDLError(
|
||||
"Multiple definitions of %s on %s coming from 'implements' statements" %
|
||||
(member.identifier.name, self),
|
||||
additionalMember.location,
|
||||
extraLocations=[member.location])
|
||||
[additionalMember.location, member.location])
|
||||
self.members.extend(additionalMembers)
|
||||
|
||||
for ancestor in self.getInheritedInterfaces():
|
||||
|
@ -541,7 +533,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
|
||||
if memberType in specialMembersSeen:
|
||||
raise WebIDLError("Multiple " + memberType + " on %s" % (self),
|
||||
self.location)
|
||||
[self.location])
|
||||
|
||||
specialMembersSeen.add(memberType)
|
||||
|
||||
|
@ -596,17 +588,17 @@ class IDLInterface(IDLObjectWithScope):
|
|||
# Special cased attrs
|
||||
if identifier == "TreatNonCallableAsNull":
|
||||
raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces",
|
||||
self.location)
|
||||
[self.location])
|
||||
elif identifier == "NoInterfaceObject":
|
||||
if self.ctor():
|
||||
raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
|
||||
self.location)
|
||||
[self.location])
|
||||
|
||||
self._noInterfaceObject = True
|
||||
elif identifier == "Constructor":
|
||||
if not self.hasInterfaceObject():
|
||||
raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
|
||||
self.location)
|
||||
[self.location])
|
||||
|
||||
args = attrlist[0] if len(attrlist) else []
|
||||
|
||||
|
@ -707,8 +699,7 @@ class IDLDictionary(IDLObjectWithScope):
|
|||
if not isinstance(self.parent, IDLDictionary):
|
||||
raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
|
||||
self.identifier.name,
|
||||
oldParent.location,
|
||||
extraLocations=[self.parent.location])
|
||||
[oldParent.location, self.parent.location])
|
||||
|
||||
# Make sure the parent resolves all its members before we start
|
||||
# looking at them.
|
||||
|
@ -731,7 +722,7 @@ class IDLDictionary(IDLObjectWithScope):
|
|||
if ancestor == self:
|
||||
raise WebIDLError("Dictionary %s has itself as an ancestor" %
|
||||
self.identifier.name,
|
||||
self.identifier.location)
|
||||
[self.identifier.location])
|
||||
inheritedMembers.extend(ancestor.members)
|
||||
ancestor = ancestor.parent
|
||||
|
||||
|
@ -741,8 +732,7 @@ class IDLDictionary(IDLObjectWithScope):
|
|||
if member.identifier.name == inheritedMember.identifier.name:
|
||||
raise WebIDLError("Dictionary %s has two members with name %s" %
|
||||
(self.identifier.name, member.identifier.name),
|
||||
member.location,
|
||||
extraLocations=[inheritedMember.location])
|
||||
[member.location, inheritedMember.location])
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
@ -757,7 +747,8 @@ class IDLEnum(IDLObjectWithIdentifier):
|
|||
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||
|
||||
if len(values) != len(set(values)):
|
||||
raise WebIDLError("Enum %s has multiple identical strings" % name.name, location)
|
||||
raise WebIDLError("Enum %s has multiple identical strings" % name.name,
|
||||
[location])
|
||||
|
||||
IDLObjectWithIdentifier.__init__(self, location, parentScope, name)
|
||||
self._values = values
|
||||
|
@ -895,7 +886,7 @@ class IDLType(IDLObject):
|
|||
def treatNonCallableAsNull(self):
|
||||
if not (self.nullable() and self.tag() == IDLType.Tags.callback):
|
||||
raise WebIDLError("Type %s cannot be TreatNonCallableAsNull" % self,
|
||||
self.location)
|
||||
[self.location])
|
||||
|
||||
return hasattr(self, "_treatNonCallableAsNull")
|
||||
|
||||
|
@ -932,7 +923,8 @@ class IDLUnresolvedType(IDLType):
|
|||
try:
|
||||
obj = scope._lookupIdentifier(self.name)
|
||||
except:
|
||||
raise WebIDLError("Unresolved type '%s'." % self.name, self.location)
|
||||
raise WebIDLError("Unresolved type '%s'." % self.name,
|
||||
[self.location])
|
||||
|
||||
assert obj
|
||||
if obj.isType():
|
||||
|
@ -1030,7 +1022,7 @@ class IDLNullableType(IDLType):
|
|||
if self.inner.isUnion() and self.inner.hasNullableType:
|
||||
raise WebIDLError("The inner type of a nullable type must not be a "
|
||||
"union type that itself has a nullable type as a "
|
||||
"member type", self.location)
|
||||
"member type", [self.location])
|
||||
self.name = self.inner.name
|
||||
return self
|
||||
|
||||
|
@ -1159,8 +1151,7 @@ class IDLUnionType(IDLType):
|
|||
if self.flatMemberTypes[i].nullable():
|
||||
if self.hasNullableType:
|
||||
raise WebIDLError("Can't have more than one nullable types in a union",
|
||||
nullableType.location,
|
||||
extraLocation=self.flatMemberTypes[i].location)
|
||||
[nullableType.location, self.flatMemberTypes[i].location])
|
||||
self.hasNullableType = True
|
||||
nullableType = self.flatMemberTypes[i]
|
||||
self.flatMemberTypes[i] = self.flatMemberTypes[i].inner
|
||||
|
@ -1176,7 +1167,7 @@ class IDLUnionType(IDLType):
|
|||
raise WebIDLError("Flat member types of a union should be "
|
||||
"distinguishable, " + str(t) + " is not "
|
||||
"distinguishable from " + str(u),
|
||||
t.location, extraLocation=u.location)
|
||||
[self.location, t.location, u.location])
|
||||
|
||||
return self
|
||||
|
||||
|
@ -1200,10 +1191,10 @@ class IDLArrayType(IDLType):
|
|||
assert not parameterType.isVoid()
|
||||
if parameterType.isSequence():
|
||||
raise WebIDLError("Array type cannot parameterize over a sequence type",
|
||||
location)
|
||||
[location])
|
||||
if parameterType.isDictionary():
|
||||
raise WebIDLError("Array type cannot parameterize over a dictionary type",
|
||||
location)
|
||||
[location])
|
||||
|
||||
IDLType.__init__(self, location, parameterType.name)
|
||||
self.inner = parameterType
|
||||
|
@ -1713,9 +1704,9 @@ class IDLValue(IDLObject):
|
|||
|
||||
# Else, see if we can coerce to 'type'.
|
||||
if self.type.isInteger():
|
||||
if not self.type.isInteger():
|
||||
if not type.isInteger():
|
||||
raise WebIDLError("Cannot coerce type %s to type %s." %
|
||||
(self.type, type), location)
|
||||
(self.type, type), [location])
|
||||
|
||||
# We're both integer types. See if we fit.
|
||||
|
||||
|
@ -1725,7 +1716,7 @@ class IDLValue(IDLObject):
|
|||
return IDLValue(self.location, type, self.value)
|
||||
else:
|
||||
raise WebIDLError("Value %s is out of range for type %s." %
|
||||
(self.value, type), location)
|
||||
(self.value, type), [location])
|
||||
else:
|
||||
pass
|
||||
|
||||
|
@ -1740,7 +1731,7 @@ class IDLNullValue(IDLObject):
|
|||
def coerceToType(self, type, location):
|
||||
if not isinstance(type, IDLNullableType) and not (type.isUnion() and type.hasNullableType):
|
||||
raise WebIDLError("Cannot coerce null value to type %s." % type,
|
||||
location)
|
||||
[location])
|
||||
|
||||
nullValue = IDLNullValue(self.location)
|
||||
nullValue.type = type
|
||||
|
@ -1790,7 +1781,7 @@ class IDLConst(IDLInterfaceMember):
|
|||
assert isinstance(type, IDLType)
|
||||
if type.isDictionary():
|
||||
raise WebIDLError("A constant cannot be of a dictionary type",
|
||||
self.location)
|
||||
[self.location])
|
||||
self.type = type
|
||||
|
||||
# The value might not match the type
|
||||
|
@ -1820,7 +1811,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
if readonly and inherit:
|
||||
raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
|
||||
self.location)
|
||||
[self.location])
|
||||
|
||||
def __str__(self):
|
||||
return "'%s' attribute '%s'" % (self.type, self.identifier)
|
||||
|
@ -1835,10 +1826,10 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
if self.type.isDictionary():
|
||||
raise WebIDLError("An attribute cannot be of a dictionary type",
|
||||
self.location)
|
||||
[self.location])
|
||||
if self.type.isSequence():
|
||||
raise WebIDLError("An attribute cannot be of a sequence type",
|
||||
self.location)
|
||||
[self.location])
|
||||
if self.type.isUnion():
|
||||
for f in self.type.flatMemberTypes:
|
||||
if f.isDictionary():
|
||||
|
@ -1846,13 +1837,13 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
"type if one of its member types (or "
|
||||
"one of its member types's member "
|
||||
"types, and so on) is a dictionary "
|
||||
"type", self.location)
|
||||
"type", [self.location, f.location])
|
||||
if f.isSequence():
|
||||
raise WebIDLError("An attribute cannot be of a union "
|
||||
"type if one of its member types (or "
|
||||
"one of its member types's member "
|
||||
"types, and so on) is a sequence "
|
||||
"type", self.location)
|
||||
"type", [self.location, f.location])
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
@ -1868,7 +1859,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
IDLObjectWithIdentifier.resolve(self, parentScope)
|
||||
|
||||
class IDLArgument(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False):
|
||||
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
|
||||
assert isinstance(type, IDLType)
|
||||
|
@ -1881,10 +1872,21 @@ class IDLArgument(IDLObjectWithIdentifier):
|
|||
self.optional = optional
|
||||
self.defaultValue = defaultValue
|
||||
self.variadic = variadic
|
||||
self.dictionaryMember = dictionaryMember
|
||||
|
||||
assert not variadic or optional
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
if self.dictionaryMember:
|
||||
for (attr, value) in attrs:
|
||||
if attr == "TreatUndefinedAs":
|
||||
raise WebIDLError("[TreatUndefinedAs] is not allowed for "
|
||||
"dictionary members", [self.location])
|
||||
elif attr == "TreatNullAs":
|
||||
raise WebIDLError("[TreatNullAs] is not allowed for "
|
||||
"dictionary members", [self.location])
|
||||
|
||||
# But actually, we can't handle this at all, so far.
|
||||
assert len(attrs) == 0
|
||||
|
||||
class IDLCallbackType(IDLType, IDLObjectWithScope):
|
||||
|
@ -2032,18 +2034,18 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
# Only the last argument can be variadic
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Variadic argument is not last argument",
|
||||
variadicArgument.location)
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Non-optional argument after optional arguments",
|
||||
argument.location)
|
||||
[argument.location])
|
||||
# Once we see an argument with no default value, there can
|
||||
# be no more default values.
|
||||
if sawOptionalWithNoDefault and argument.defaultValue:
|
||||
raise WebIDLError("Argument with default value after optional "
|
||||
"arguments with no default values",
|
||||
argument.location)
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
if argument.variadic:
|
||||
variadicArgument = argument
|
||||
|
@ -2106,11 +2108,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
|
||||
if self.isStatic() != method.isStatic():
|
||||
raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method1.identifier,
|
||||
method.location)
|
||||
[method.location])
|
||||
|
||||
if self.isLegacycaller() != method.isLegacycaller():
|
||||
raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method1.identifier,
|
||||
method.location)
|
||||
[method.location])
|
||||
|
||||
# Can't overload special things!
|
||||
assert not self.isGetter()
|
||||
|
@ -2178,8 +2180,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
"is before distinguishing index %d" %
|
||||
(self.identifier.name, argCount, idx,
|
||||
distinguishingIndex),
|
||||
self.location,
|
||||
extraLocations=[location])
|
||||
[self.location, location])
|
||||
|
||||
def signaturesForArgCount(self, argc):
|
||||
return [(retval, args) for (retval, args) in self.signatures() if
|
||||
|
@ -2207,8 +2208,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
locations = self.locationsForArgCount(argc)
|
||||
raise WebIDLError("Signatures with %d arguments for method '%s' are not "
|
||||
"distinguishable" % (argc, self.identifier.name),
|
||||
locations[0],
|
||||
extraLocations=locations[1:])
|
||||
locations)
|
||||
|
||||
class IDLImplementsStatement(IDLObject):
|
||||
def __init__(self, location, implementor, implementee):
|
||||
|
@ -2227,19 +2227,19 @@ class IDLImplementsStatement(IDLObject):
|
|||
if not isinstance(implementor, IDLInterface):
|
||||
raise WebIDLError("Left-hand side of 'implements' is not an "
|
||||
"interface",
|
||||
self.implementor.location)
|
||||
[self.implementor.location])
|
||||
if implementor.isCallback():
|
||||
raise WebIDLError("Left-hand side of 'implements' is a callback "
|
||||
"interface",
|
||||
self.implementor.location)
|
||||
[self.implementor.location])
|
||||
if not isinstance(implementee, IDLInterface):
|
||||
raise WebIDLError("Right-hand side of 'implements' is not an "
|
||||
"interface",
|
||||
self.implementee.location)
|
||||
[self.implementee.location])
|
||||
if implementee.isCallback():
|
||||
raise WebIDLError("Right-hand side of 'implements' is a callback "
|
||||
"interface",
|
||||
self.implementee.location)
|
||||
[self.implementee.location])
|
||||
implementor.addImplementedInterface(implementee)
|
||||
|
||||
def validate(self):
|
||||
|
@ -2267,10 +2267,10 @@ class Tokenizer(object):
|
|||
t.value = parseInt(t.value)
|
||||
except:
|
||||
raise WebIDLError("Invalid integer literal",
|
||||
Location(lexer=self.lexer,
|
||||
lineno=self.lexer.lineno,
|
||||
lexpos=self.lexer.lexpos,
|
||||
filename=self._filename))
|
||||
[Location(lexer=self.lexer,
|
||||
lineno=self.lexer.lineno,
|
||||
lexpos=self.lexer.lexpos,
|
||||
filename=self._filename)])
|
||||
return t
|
||||
|
||||
def t_FLOATLITERAL(self, t):
|
||||
|
@ -2365,10 +2365,10 @@ class Tokenizer(object):
|
|||
|
||||
def t_error(self, t):
|
||||
raise WebIDLError("Unrecognized Input",
|
||||
Location(lexer=self.lexer,
|
||||
lineno=self.lexer.lineno,
|
||||
lexpos=self.lexer.lexpos,
|
||||
filename = self.filename))
|
||||
[Location(lexer=self.lexer,
|
||||
lineno=self.lexer.lineno,
|
||||
lexpos=self.lexer.lexpos,
|
||||
filename = self.filename)])
|
||||
|
||||
def __init__(self, outputdir, lexer=None):
|
||||
if lexer:
|
||||
|
@ -2546,7 +2546,8 @@ class Parser(Tokenizer):
|
|||
defaultValue = p[3]
|
||||
|
||||
p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
|
||||
defaultValue=defaultValue, variadic=False)
|
||||
defaultValue=defaultValue, variadic=False,
|
||||
dictionaryMember=True)
|
||||
|
||||
def p_DefaultValue(self, p):
|
||||
"""
|
||||
|
@ -2656,7 +2657,7 @@ class Parser(Tokenizer):
|
|||
# Determine the smallest type it could possibly fit in and use that.
|
||||
integerType = matchIntegerValueToType(p[1])
|
||||
if integerType == None:
|
||||
raise WebIDLError("Integer literal out of range", location)
|
||||
raise WebIDLError("Integer literal out of range", [location])
|
||||
|
||||
p[0] = IDLValue(location, integerType, p[1])
|
||||
|
||||
|
@ -2743,7 +2744,7 @@ class Parser(Tokenizer):
|
|||
# Disallow duplicates in the qualifier set
|
||||
if not len(set(qualifiers)) == len(qualifiers):
|
||||
raise WebIDLError("Duplicate qualifiers are not allowed",
|
||||
self.getLocation(p, 1))
|
||||
[self.getLocation(p, 1)])
|
||||
|
||||
static = True if IDLMethod.Special.Static in p[1] else False
|
||||
# If static is there that's all that's allowed. This is disallowed
|
||||
|
@ -2760,7 +2761,7 @@ class Parser(Tokenizer):
|
|||
if getter or deleter:
|
||||
if setter or creator:
|
||||
raise WebIDLError("getter and deleter are incompatible with setter and creator",
|
||||
self.getLocation(p, 1))
|
||||
[self.getLocation(p, 1)])
|
||||
|
||||
(returnType, identifier, arguments) = p[2]
|
||||
|
||||
|
@ -2772,7 +2773,7 @@ class Parser(Tokenizer):
|
|||
if len(arguments) != 1:
|
||||
raise WebIDLError("%s has wrong number of arguments" %
|
||||
("getter" if getter else "deleter"),
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
argType = arguments[0].type
|
||||
if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
|
||||
specialType = IDLMethod.NamedOrIndexed.Named
|
||||
|
@ -2781,21 +2782,21 @@ class Parser(Tokenizer):
|
|||
else:
|
||||
raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
|
||||
("getter" if getter else "deleter"),
|
||||
arguments[0].location)
|
||||
[arguments[0].location])
|
||||
if arguments[0].optional or arguments[0].variadic:
|
||||
raise WebIDLError("%s cannot have %s argument" %
|
||||
("getter" if getter else "deleter",
|
||||
"optional" if arguments[0].optional else "variadic"),
|
||||
arguments[0].location)
|
||||
[arguments[0].location])
|
||||
if getter:
|
||||
if returnType.isVoid():
|
||||
raise WebIDLError("getter cannot have void return type",
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
if setter or creator:
|
||||
if len(arguments) != 2:
|
||||
raise WebIDLError("%s has wrong number of arguments" %
|
||||
("setter" if setter else "creator"),
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
argType = arguments[0].type
|
||||
if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
|
||||
specialType = IDLMethod.NamedOrIndexed.Named
|
||||
|
@ -2804,25 +2805,25 @@ class Parser(Tokenizer):
|
|||
else:
|
||||
raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
|
||||
("setter" if setter else "creator"),
|
||||
arguments[0].location)
|
||||
[arguments[0].location])
|
||||
if arguments[0].optional or arguments[0].variadic:
|
||||
raise WebIDLError("%s cannot have %s argument" %
|
||||
("setter" if setter else "creator",
|
||||
"optional" if arguments[0].optional else "variadic"),
|
||||
arguments[0].location)
|
||||
[arguments[0].location])
|
||||
if arguments[1].optional or arguments[1].variadic:
|
||||
raise WebIDLError("%s cannot have %s argument" %
|
||||
("setter" if setter else "creator",
|
||||
"optional" if arguments[1].optional else "variadic"),
|
||||
arguments[1].location)
|
||||
[arguments[1].location])
|
||||
|
||||
if stringifier:
|
||||
if len(arguments) != 0:
|
||||
raise WebIDLError("stringifier has wrong number of arguments",
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
if not returnType.isString():
|
||||
raise WebIDLError("stringifier must have string return type",
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
|
||||
inOptionalArguments = False
|
||||
variadicArgument = False
|
||||
|
@ -2830,12 +2831,12 @@ class Parser(Tokenizer):
|
|||
# Only the last argument can be variadic
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Only the last argument can be variadic",
|
||||
variadicArgument.location)
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Cannot have a non-optional argument following an optional argument",
|
||||
argument.location)
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
variadicArgument = argument if argument.variadic else None
|
||||
|
||||
|
@ -2844,7 +2845,7 @@ class Parser(Tokenizer):
|
|||
if not getter and not setter and not creator and \
|
||||
not deleter and not legacycaller and not stringifier:
|
||||
raise WebIDLError("Identifier required for non-special methods",
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
|
||||
location = BuiltinLocation("<auto-generated-identifier>")
|
||||
identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" %
|
||||
|
@ -2982,12 +2983,12 @@ class Parser(Tokenizer):
|
|||
|
||||
if not optional and defaultValue:
|
||||
raise WebIDLError("Mandatory arguments can't have a default value.",
|
||||
self.getLocation(p, 6))
|
||||
[self.getLocation(p, 6)])
|
||||
|
||||
if variadic:
|
||||
if optional:
|
||||
raise WebIDLError("Variadic arguments should not be marked optional.",
|
||||
self.getLocation(p, 2))
|
||||
[self.getLocation(p, 2)])
|
||||
optional = variadic
|
||||
|
||||
p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
|
||||
|
@ -3458,9 +3459,9 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_error(self, p):
|
||||
if not p:
|
||||
raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both", None)
|
||||
raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both", [])
|
||||
else:
|
||||
raise WebIDLError("invalid syntax", Location(self.lexer, p.lineno, p.lexpos, self._filename))
|
||||
raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)])
|
||||
|
||||
def __init__(self, outputdir='', lexer=None):
|
||||
Tokenizer.__init__(self, outputdir, lexer)
|
||||
|
|
|
@ -93,3 +93,31 @@ def WebIDLTest(parser, harness):
|
|||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow cycles in dictionary inheritance chains")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary A {
|
||||
[TreatNullAs=EmptyString] DOMString foo;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [TreatNullAs] on dictionary members");
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary A {
|
||||
[TreatUndefinedAs=EmptyString] DOMString foo;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [TreatUndefinedAs] on dictionary members");
|
||||
|
|
|
@ -109,7 +109,7 @@ def WebIDLTest(parser, harness):
|
|||
harness.check(len(results[1].members), 1,
|
||||
"Should look like we have one method")
|
||||
harness.check(len(results[1].members[0].signatures()), 4,
|
||||
"Should have foid signatures")
|
||||
"Should have four signatures")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
|
|
|
@ -1,413 +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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
|
||||
// Event whitelisted for bubbling.
|
||||
let whitelistedEvents = [
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_SLEEP, // Power button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
|
||||
];
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementChild - " + msg + "\n");
|
||||
}
|
||||
|
||||
function sendAsyncMsg(msg, data) {
|
||||
sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
function sendSyncMsg(msg, data) {
|
||||
return sendSyncMessage('browser-element-api:' + msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementChild implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementParent.)
|
||||
*
|
||||
* This script is injected into an <iframe mozbrowser> via
|
||||
* nsIMessageManager::LoadFrameScript().
|
||||
*
|
||||
* Our job here is to listen for events within this frame and bubble them up to
|
||||
* the parent process.
|
||||
*/
|
||||
|
||||
var global = this;
|
||||
|
||||
function BrowserElementChild() {
|
||||
// Maps outer window id --> weak ref to window. Used by modal dialog code.
|
||||
this._windowIDDict = {};
|
||||
|
||||
this._init();
|
||||
};
|
||||
|
||||
BrowserElementChild.prototype = {
|
||||
_init: function() {
|
||||
debug("Starting up.");
|
||||
sendAsyncMsg("hello");
|
||||
|
||||
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
|
||||
|
||||
docShell.isBrowserFrame = true;
|
||||
docShell.QueryInterface(Ci.nsIWebProgress)
|
||||
.addProgressListener(this._progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION |
|
||||
Ci.nsIWebProgress.NOTIFY_SECURITY |
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
|
||||
|
||||
// This is necessary to get security web progress notifications.
|
||||
var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
|
||||
.createInstance(Ci.nsISecureBrowserUI);
|
||||
securityUI.init(content);
|
||||
|
||||
// A mozbrowser iframe contained inside a mozapp iframe should return false
|
||||
// for nsWindowUtils::IsPartOfApp (unless the mozbrowser iframe is itself
|
||||
// also mozapp). That is, mozapp is transitive down to its children, but
|
||||
// mozbrowser serves as a barrier.
|
||||
//
|
||||
// This is because mozapp iframes have some privileges which we don't want
|
||||
// to extend to untrusted mozbrowser content.
|
||||
//
|
||||
// Get the app manifest from the parent, if our frame has one.
|
||||
let appManifestURL = sendSyncMsg('get-mozapp-manifest-url')[0];
|
||||
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
if (!!appManifestURL) {
|
||||
windowUtils.setIsApp(true);
|
||||
windowUtils.setApp(appManifestURL);
|
||||
} else {
|
||||
windowUtils.setIsApp(false);
|
||||
}
|
||||
|
||||
addEventListener('DOMTitleChanged',
|
||||
this._titleChangedHandler.bind(this),
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
addEventListener('DOMLinkAdded',
|
||||
this._iconChangedHandler.bind(this),
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
var self = this;
|
||||
function addMsgListener(msg, handler) {
|
||||
addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMsgListener("get-screenshot", this._recvGetScreenshot);
|
||||
addMsgListener("set-visible", this._recvSetVisible);
|
||||
addMsgListener("unblock-modal-prompt", this._recvStopWaiting);
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
// We are using the system group for those events so if something in the
|
||||
// content called .stopPropagation() this will still be called.
|
||||
els.addSystemEventListener(global, 'keydown',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keypress',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keyup',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'DOMWindowClose',
|
||||
this._closeHandler.bind(this),
|
||||
/* useCapture = */ false);
|
||||
},
|
||||
|
||||
_tryGetInnerWindowID: function(win) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
return utils.currentInnerWindowID;
|
||||
}
|
||||
catch(e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a modal prompt. Called by BrowserElementPromptService.
|
||||
*/
|
||||
showModalPrompt: function(win, args) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
args.windowID = { outer: utils.outerWindowID,
|
||||
inner: this._tryGetInnerWindowID(win) };
|
||||
sendAsyncMsg('showmodalprompt', args);
|
||||
|
||||
let returnValue = this._waitForResult(win);
|
||||
|
||||
if (args.promptType == 'prompt' ||
|
||||
args.promptType == 'confirm') {
|
||||
return returnValue;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
|
||||
* this window.
|
||||
*/
|
||||
_waitForResult: function(win) {
|
||||
debug("_waitForResult(" + win + ")");
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let outerWindowID = utils.outerWindowID;
|
||||
let innerWindowID = this._tryGetInnerWindowID(win);
|
||||
if (innerWindowID === null) {
|
||||
// I have no idea what waiting for a result means when there's no inner
|
||||
// window, so let's just bail.
|
||||
debug("_waitForResult: No inner window. Bailing.");
|
||||
return;
|
||||
}
|
||||
|
||||
this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
|
||||
|
||||
debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
|
||||
"innerWindowID=" + innerWindowID + ")");
|
||||
|
||||
// In theory, we're supposed to pass |modalStateWin| back to
|
||||
// leaveModalStateWithWindow. But in practice, the window is always null,
|
||||
// because it's the window associated with this script context, which
|
||||
// doesn't have a window. But we'll play along anyway in case this
|
||||
// changes.
|
||||
var modalStateWin = utils.enterModalStateWithWindow();
|
||||
|
||||
// We'll decrement win.modalDepth when we receive a unblock-modal-prompt message
|
||||
// for the window.
|
||||
if (!win.modalDepth) {
|
||||
win.modalDepth = 0;
|
||||
}
|
||||
win.modalDepth++;
|
||||
let origModalDepth = win.modalDepth;
|
||||
|
||||
let thread = Services.tm.currentThread;
|
||||
debug("Nested event loop - begin");
|
||||
while (win.modalDepth == origModalDepth) {
|
||||
// Bail out of the loop if the inner window changed; that means the
|
||||
// window navigated.
|
||||
if (this._tryGetInnerWindowID(win) !== innerWindowID) {
|
||||
debug("_waitForResult: Inner window ID changed " +
|
||||
"while in nested event loop.");
|
||||
break;
|
||||
}
|
||||
|
||||
thread.processNextEvent(/* mayWait = */ true);
|
||||
}
|
||||
debug("Nested event loop - finish");
|
||||
|
||||
// If we exited the loop because the inner window changed, then bail on the
|
||||
// modal prompt.
|
||||
if (innerWindowID !== this._tryGetInnerWindowID(win)) {
|
||||
throw Components.Exception("Modal state aborted by navigation",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
let returnValue = win.modalReturnValue;
|
||||
delete win.modalReturnValue;
|
||||
|
||||
utils.leaveModalStateWithWindow(modalStateWin);
|
||||
|
||||
debug("Leaving modal state (outerID=" + outerWindowID + ", " +
|
||||
"innerID=" + innerWindowID + ")");
|
||||
return returnValue;
|
||||
},
|
||||
|
||||
_recvStopWaiting: function(msg) {
|
||||
let outerID = msg.json.windowID.outer;
|
||||
let innerID = msg.json.windowID.inner;
|
||||
let returnValue = msg.json.returnValue;
|
||||
debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
|
||||
", returnValue=" + returnValue + ")");
|
||||
|
||||
if (!this._windowIDDict[outerID]) {
|
||||
debug("recvStopWaiting: No record of outer window ID " + outerID);
|
||||
return;
|
||||
}
|
||||
|
||||
let win = this._windowIDDict[outerID].get();
|
||||
delete this._windowIDDict[outerID];
|
||||
|
||||
if (!win) {
|
||||
debug("recvStopWaiting, but window is gone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (innerID !== this._tryGetInnerWindowID(win)) {
|
||||
debug("recvStopWaiting, but inner ID has changed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("recvStopWaiting " + win);
|
||||
win.modalReturnValue = returnValue;
|
||||
win.modalDepth--;
|
||||
},
|
||||
|
||||
_titleChangedHandler: function(e) {
|
||||
debug("Got titlechanged: (" + e.target.title + ")");
|
||||
var win = e.target.defaultView;
|
||||
|
||||
// Ignore titlechanges which don't come from the top-level
|
||||
// <iframe mozbrowser> window.
|
||||
if (win == content) {
|
||||
sendAsyncMsg('titlechange', e.target.title);
|
||||
}
|
||||
else {
|
||||
debug("Not top level!");
|
||||
}
|
||||
},
|
||||
|
||||
_iconChangedHandler: function(e) {
|
||||
debug("Got iconchanged: (" + e.target.href + ")");
|
||||
var hasIcon = e.target.rel.split(' ').some(function(x) {
|
||||
return x.toLowerCase() === 'icon';
|
||||
});
|
||||
|
||||
if (hasIcon) {
|
||||
var win = e.target.ownerDocument.defaultView;
|
||||
// Ignore iconchanges which don't come from the top-level
|
||||
// <iframe mozbrowser> window.
|
||||
if (win == content) {
|
||||
sendAsyncMsg('iconchange', e.target.href);
|
||||
}
|
||||
else {
|
||||
debug("Not top level!");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_closeHandler: function(e) {
|
||||
let win = e.target;
|
||||
if (win != content || e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Closing window " + win);
|
||||
sendAsyncMsg('close');
|
||||
|
||||
// Inform the window implementation that we handled this close ourselves.
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
_recvGetScreenshot: function(data) {
|
||||
debug("Received getScreenshot message: (" + data.json.id + ")");
|
||||
var canvas = content.document
|
||||
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
canvas.mozOpaque = true;
|
||||
canvas.height = content.innerHeight;
|
||||
canvas.width = content.innerWidth;
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth,
|
||||
content.innerHeight, "rgb(255,255,255)");
|
||||
sendAsyncMsg('got-screenshot', {
|
||||
id: data.json.id,
|
||||
screenshot: canvas.toDataURL("image/png")
|
||||
});
|
||||
},
|
||||
|
||||
_recvSetVisible: function(data) {
|
||||
debug("Received setVisible message: (" + data.json.visible + ")");
|
||||
if (docShell.isActive !== data.json.visible) {
|
||||
docShell.isActive = data.json.visible;
|
||||
}
|
||||
},
|
||||
|
||||
_keyEventHandler: function(e) {
|
||||
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
|
||||
sendAsyncMsg('keyevent', {
|
||||
type: e.type,
|
||||
keyCode: e.keyCode,
|
||||
charCode: e.charCode,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// The docShell keeps a weak reference to the progress listener, so we need
|
||||
// to keep a strong ref to it ourselves.
|
||||
_progressListener: {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
_seenLoadStart: false,
|
||||
|
||||
onLocationChange: function(webProgress, request, location, flags) {
|
||||
// We get progress events from subshells here, which is kind of weird.
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore locationchange events which occur before the first loadstart.
|
||||
// These are usually about:blank loads we don't care about.
|
||||
if (!this._seenLoadStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMsg('locationchange', location.spec);
|
||||
},
|
||||
|
||||
onStateChange: function(webProgress, request, stateFlags, status) {
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
|
||||
this._seenLoadStart = true;
|
||||
sendAsyncMsg('loadstart');
|
||||
}
|
||||
|
||||
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
|
||||
sendAsyncMsg('loadend');
|
||||
}
|
||||
},
|
||||
|
||||
onSecurityChange: function(webProgress, request, state) {
|
||||
if (webProgress != docShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
var stateDesc;
|
||||
if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
|
||||
stateDesc = 'secure';
|
||||
}
|
||||
else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
|
||||
stateDesc = 'broken';
|
||||
}
|
||||
else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
|
||||
stateDesc = 'insecure';
|
||||
}
|
||||
else {
|
||||
debug("Unexpected securitychange state!");
|
||||
stateDesc = '???';
|
||||
}
|
||||
|
||||
// XXX Until bug 764496 is fixed, this will always return false.
|
||||
var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
|
||||
|
||||
sendAsyncMsg('securitychange', {state: stateDesc, extendedValidation: isEV});
|
||||
},
|
||||
|
||||
onStatusChange: function(webProgress, request, status, message) {},
|
||||
onProgressChange: function(webProgress, request, curSelfProgress,
|
||||
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
|
||||
},
|
||||
};
|
||||
|
||||
var api = new BrowserElementChild();
|
|
@ -1,298 +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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* BrowserElementParent implements one half of <iframe mozbrowser>. (The other
|
||||
* half is, unsurprisingly, BrowserElementChild.)
|
||||
*
|
||||
* BrowserElementParentFactory detects when we create a windows or docshell
|
||||
* contained inside a <iframe mozbrowser> and creates a BrowserElementParent
|
||||
* object for that window.
|
||||
*
|
||||
* BrowserElementParent injects script to listen for certain events in the
|
||||
* child. We then listen to messages from the child script and take
|
||||
* appropriate action here in the parent.
|
||||
*/
|
||||
|
||||
function BrowserElementParentFactory() {
|
||||
this._initialized = false;
|
||||
}
|
||||
|
||||
BrowserElementParentFactory.prototype = {
|
||||
classID: Components.ID("{ddeafdac-cb39-47c4-9cb8-c9027ee36d26}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
/**
|
||||
* Called on app startup, and also when the browser frames enabled pref is
|
||||
* changed.
|
||||
*/
|
||||
_init: function() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the pref is disabled, do nothing except wait for the pref to change.
|
||||
// (This is important for tests, if nothing else.)
|
||||
if (!this._browserFramesPrefEnabled()) {
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("_init");
|
||||
this._initialized = true;
|
||||
|
||||
// Maps frame elements to BrowserElementParent objects. We never look up
|
||||
// anything in this map; the purpose is to keep the BrowserElementParent
|
||||
// alive for as long as its frame element lives.
|
||||
this._bepMap = new WeakMap();
|
||||
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true);
|
||||
os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true);
|
||||
},
|
||||
|
||||
_browserFramesPrefEnabled: function() {
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
try {
|
||||
return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader) {
|
||||
debug("In-process browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_observeRemoteBrowserFrameShown: function(frameLoader) {
|
||||
debug("Remote browser frame shown " + frameLoader);
|
||||
this._createBrowserElementParent(frameLoader);
|
||||
},
|
||||
|
||||
_createBrowserElementParent: function(frameLoader) {
|
||||
let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
this._bepMap.set(frameElement, new BrowserElementParent(frameLoader));
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch(topic) {
|
||||
case 'app-startup':
|
||||
this._init();
|
||||
break;
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
|
||||
if (data == BROWSER_FRAMES_ENABLED_PREF) {
|
||||
this._init();
|
||||
}
|
||||
break;
|
||||
case 'remote-browser-frame-shown':
|
||||
this._observeRemoteBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'in-process-browser-frame-shown':
|
||||
this._observeInProcessBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'content-document-global-created':
|
||||
this._observeContentGlobalCreated(subject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function BrowserElementParent(frameLoader) {
|
||||
debug("Creating new BrowserElementParent object for " + frameLoader);
|
||||
this._screenshotListeners = {};
|
||||
this._screenshotReqCounter = 0;
|
||||
|
||||
this._frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
if (!this._frameElement) {
|
||||
debug("No frame element?");
|
||||
return;
|
||||
}
|
||||
|
||||
this._mm = frameLoader.messageManager;
|
||||
|
||||
// Messages we receive are handed to functions which take a (data) argument,
|
||||
// where |data| is the message manager's data object.
|
||||
|
||||
let self = this;
|
||||
function addMessageListener(msg, handler) {
|
||||
self._mm.addMessageListener('browser-element-api:' + msg, handler.bind(self));
|
||||
}
|
||||
|
||||
addMessageListener("hello", this._recvHello);
|
||||
addMessageListener("locationchange", this._fireEventFromMsg);
|
||||
addMessageListener("loadstart", this._fireEventFromMsg);
|
||||
addMessageListener("loadend", this._fireEventFromMsg);
|
||||
addMessageListener("titlechange", this._fireEventFromMsg);
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("close", this._fireEventFromMsg);
|
||||
addMessageListener("securitychange", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
|
||||
addMessageListener('got-screenshot', this._recvGotScreenshot);
|
||||
|
||||
function defineMethod(name, fn) {
|
||||
XPCNativeWrapper.unwrap(self._frameElement)[name] = fn.bind(self);
|
||||
}
|
||||
|
||||
// Define methods on the frame element.
|
||||
defineMethod('getScreenshot', this._getScreenshot);
|
||||
defineMethod('setVisible', this._setVisible);
|
||||
|
||||
this._mm.loadFrameScript("chrome://global/content/BrowserElementChild.js",
|
||||
/* allowDelayedLoad = */ true);
|
||||
}
|
||||
|
||||
BrowserElementParent.prototype = {
|
||||
get _window() {
|
||||
return this._frameElement.ownerDocument.defaultView;
|
||||
},
|
||||
|
||||
_sendAsyncMsg: function(msg, data) {
|
||||
this._frameElement.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.messageManager
|
||||
.sendAsyncMessage('browser-element-api:' + msg, data);
|
||||
},
|
||||
|
||||
_recvHello: function(data) {
|
||||
debug("recvHello");
|
||||
},
|
||||
|
||||
/**
|
||||
* Fire either a vanilla or a custom event, depending on the contents of
|
||||
* |data|.
|
||||
*/
|
||||
_fireEventFromMsg: function(data) {
|
||||
let name = data.name.substring('browser-element-api:'.length);
|
||||
let detail = data.json;
|
||||
|
||||
debug('fireEventFromMsg: ' + name + ', ' + detail);
|
||||
let evt = this._createEvent(name, detail,
|
||||
/* cancelable = */ false);
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_handleShowModalPrompt: function(data) {
|
||||
// Fire a showmodalprmopt event on the iframe. When this method is called,
|
||||
// the child is spinning in a nested event loop waiting for an
|
||||
// unblock-modal-prompt message.
|
||||
//
|
||||
// If the embedder calls preventDefault() on the showmodalprompt event,
|
||||
// we'll block the child until event.detail.unblock() is called.
|
||||
//
|
||||
// Otherwise, if preventDefault() is not called, we'll send the
|
||||
// unblock-modal-prompt message to the child as soon as the event is done
|
||||
// dispatching.
|
||||
|
||||
let detail = data.json;
|
||||
debug('handleShowPrompt ' + JSON.stringify(detail));
|
||||
|
||||
// Strip off the windowID property from the object we send along in the
|
||||
// event.
|
||||
let windowID = detail.windowID;
|
||||
delete detail.windowID;
|
||||
debug("Event will have detail: " + JSON.stringify(detail));
|
||||
let evt = this._createEvent('showmodalprompt', detail,
|
||||
/* cancelable = */ true);
|
||||
|
||||
let self = this;
|
||||
let unblockMsgSent = false;
|
||||
function sendUnblockMsg() {
|
||||
if (unblockMsgSent) {
|
||||
return;
|
||||
}
|
||||
unblockMsgSent = true;
|
||||
|
||||
// We don't need to sanitize evt.detail.returnValue (e.g. converting the
|
||||
// return value of confirm() to a boolean); Gecko does that for us.
|
||||
|
||||
let data = { windowID: windowID,
|
||||
returnValue: evt.detail.returnValue };
|
||||
self._sendAsyncMsg('unblock-modal-prompt', data);
|
||||
}
|
||||
|
||||
XPCNativeWrapper.unwrap(evt.detail).unblock = function() {
|
||||
sendUnblockMsg();
|
||||
};
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
|
||||
if (!evt.defaultPrevented) {
|
||||
// Unblock the inner frame immediately. Otherwise we'll unblock upon
|
||||
// evt.detail.unblock().
|
||||
sendUnblockMsg();
|
||||
}
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
return new this._window.CustomEvent('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable,
|
||||
detail: detail });
|
||||
}
|
||||
|
||||
return new this._window.Event('mozbrowser' + evtName,
|
||||
{ bubbles: true,
|
||||
cancelable: cancelable });
|
||||
},
|
||||
|
||||
_sendMozAppManifestURL: function(data) {
|
||||
return this._frameElement.getAttribute('mozapp');
|
||||
},
|
||||
|
||||
|
||||
_getScreenshot: function() {
|
||||
let id = 'req_' + this._screenshotReqCounter++;
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
this._screenshotListeners[id] = req;
|
||||
this._sendAsyncMsg('get-screenshot', {id: id});
|
||||
return req;
|
||||
},
|
||||
|
||||
_recvGotScreenshot: function(data) {
|
||||
var req = this._screenshotListeners[data.json.id];
|
||||
delete this._screenshotListeners[data.json.id];
|
||||
Services.DOMRequest.fireSuccess(req, data.json.screenshot);
|
||||
},
|
||||
|
||||
_setVisible: function(visible) {
|
||||
this._sendAsyncMsg('set-visible', {visible: visible});
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(data) {
|
||||
let evt = this._window.document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent(data.json.type, true, true, this._window,
|
||||
false, false, false, false, // modifiers
|
||||
data.json.keyCode,
|
||||
data.json.charCode);
|
||||
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParentFactory]);
|
|
@ -83,7 +83,7 @@ interface mozIDOMApplicationMgmt : nsISupports
|
|||
attribute nsIDOMEventListener onuninstall;
|
||||
};
|
||||
|
||||
[scriptable, uuid(f6929871-288b-4613-9a37-9a150760ac50)]
|
||||
[scriptable, uuid(d7b0ff50-e667-4ed2-b996-0eb937763952)]
|
||||
interface mozIDOMApplicationRegistry : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -106,5 +106,11 @@ interface mozIDOMApplicationRegistry : nsISupports
|
|||
*/
|
||||
nsIDOMDOMRequest getInstalled();
|
||||
|
||||
/**
|
||||
* the request will return the applications acquired from this origin but which
|
||||
* are not launchable (e.g. by not being natively installed), or null.
|
||||
*/
|
||||
nsIDOMDOMRequest getNotInstalled();
|
||||
|
||||
readonly attribute mozIDOMApplicationMgmt mgmt;
|
||||
};
|
||||
|
|
|
@ -57,6 +57,7 @@ XPIDLSRCS = \
|
|||
nsIDOMPerformance.idl \
|
||||
nsIDOMPerformanceTiming.idl \
|
||||
nsIDOMPerformanceNavigation.idl \
|
||||
nsIIdleObserver.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(e0737ed5-89c5-4fe3-891e-a75bf3a1bb55)]
|
||||
interface nsIIdleObserver;
|
||||
|
||||
[scriptable, uuid(c148ed5a-31c1-4a21-a13b-341f592579ff)]
|
||||
interface nsIDOMNavigator : nsISupports
|
||||
{
|
||||
readonly attribute DOMString appCodeName;
|
||||
|
@ -78,6 +80,16 @@ interface nsIDOMNavigator : nsISupports
|
|||
[implicit_jscontext]
|
||||
void mozVibrate(in jsval aPattern);
|
||||
|
||||
/**
|
||||
* Navigator requests to add an idle observer to the existing window.
|
||||
*/
|
||||
void addIdleObserver(in nsIIdleObserver aIdleObserver);
|
||||
|
||||
/**
|
||||
* Navigator requests to remove an idle observer from the existing window.
|
||||
*/
|
||||
void removeIdleObserver(in nsIIdleObserver aIdleObserver);
|
||||
|
||||
/**
|
||||
* Request a wake lock for a resource.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(37916e05-e062-4f72-96d5-660cfb55e9b6)]
|
||||
interface nsIIdleObserver : nsISupports
|
||||
{
|
||||
// Time is in seconds and is read only when idle observers are added
|
||||
// and removed.
|
||||
readonly attribute unsigned long time;
|
||||
void onidle();
|
||||
void onactive();
|
||||
};
|
|
@ -46,7 +46,9 @@ interface nsIDOMCanvasRenderingContext2D : nsISupports
|
|||
readonly attribute nsIDOMHTMLCanvasElement canvas;
|
||||
|
||||
// state
|
||||
[binaryname(MozSave)]
|
||||
void save();
|
||||
[binaryname(MozRestore)]
|
||||
void restore();
|
||||
|
||||
// transformations
|
||||
|
@ -93,7 +95,9 @@ enum CanvasMultiGetterType {
|
|||
nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
|
||||
nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, [Null(Stringify)] in DOMString repetition);
|
||||
attribute float lineWidth; /* default 1 */
|
||||
[binaryname(MozLineCap)]
|
||||
attribute DOMString lineCap; /* "butt", "round", "square" (default) */
|
||||
[binaryname(MozLineJoin)]
|
||||
attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
|
||||
attribute float miterLimit; /* default 10 */
|
||||
|
||||
|
@ -105,6 +109,7 @@ enum CanvasMultiGetterType {
|
|||
attribute float shadowOffsetX;
|
||||
attribute float shadowOffsetY;
|
||||
attribute float shadowBlur;
|
||||
[binaryname(MozShadowColor)]
|
||||
attribute DOMString shadowColor;
|
||||
|
||||
// rects
|
||||
|
@ -113,7 +118,9 @@ enum CanvasMultiGetterType {
|
|||
void strokeRect(in float x, in float y, in float w, in float h);
|
||||
|
||||
// path API
|
||||
[binaryname(MozBeginPath)]
|
||||
void beginPath();
|
||||
[binaryname(MozClosePath)]
|
||||
void closePath();
|
||||
|
||||
void moveTo(in float x, in float y);
|
||||
|
@ -124,14 +131,20 @@ enum CanvasMultiGetterType {
|
|||
void arc(in float x, in float y, in float r, in float startAngle, in float endAngle, [optional] in boolean anticlockwise);
|
||||
void rect(in float x, in float y, in float w, in float h);
|
||||
|
||||
[binaryname(MozFill)]
|
||||
void fill();
|
||||
[binaryname(MozStroke)]
|
||||
void stroke();
|
||||
[binaryname(MozClip)]
|
||||
void clip();
|
||||
|
||||
// text api
|
||||
[binaryname(MozFont)]
|
||||
attribute DOMString font; /* default "10px sans-serif" */
|
||||
[binaryname(MozTextAlign)]
|
||||
attribute DOMString textAlign; /* "start" (default), "end", "left", "right",
|
||||
"center" */
|
||||
[binaryname(MozTextBaseline)]
|
||||
attribute DOMString textBaseline; /* "alphabetic" (default), "top", "hanging",
|
||||
"middle", "ideographic", "bottom" */
|
||||
|
||||
|
@ -139,6 +152,7 @@ enum CanvasMultiGetterType {
|
|||
void strokeText(in DOMString text, in float x, in float y, [optional] in float maxWidth);
|
||||
nsIDOMTextMetrics measureText(in DOMString text);
|
||||
|
||||
[binaryname(TextStyle)]
|
||||
attribute DOMString mozTextStyle;
|
||||
|
||||
// image api
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
# 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/.
|
||||
|
||||
# CSP Warnings:
|
||||
# LOCALIZATION NOTE (directiveViolated):
|
||||
# %1$S is the directive that has been violated.
|
||||
directiveViolated = Directive %1$S violated
|
||||
# LOCALIZATION NOTE (directiveViolatedWithURI):
|
||||
# %1$S is the directive that has been violated.
|
||||
# %2$S is the URI of the resource which violated the directive.
|
||||
directiveViolatedWithURI = Directive %1$S violated by %2$S
|
||||
# LOCALIZATION NOTE (triedToSendReport):
|
||||
# %1$S is the URI we attempted to send a report to.
|
||||
triedToSendReport = Tried to send report to invalid URI: "%1$S"
|
||||
# LOCALIZATION NOTE (errorWas):
|
||||
# %1$S is the error resulting from attempting to send the report
|
||||
errorWas = error was: "%1$S"
|
||||
# LOCALIZATION NOTE (couldNotParseReportURI):
|
||||
# %1$S is the report URI that could not be parsed
|
||||
couldNotParseReportURI = couldn't parse report URI: %1$S
|
||||
# LOCALIZATION NOTE (couldNotProcessUnknownDirective):
|
||||
# %1$S is the unknown directive
|
||||
couldNotProcessUnknownDirective = Couldn't process unknown directive '%1$S'
|
||||
# LOCALIZATION NOTE (doNotUnderstandOption):
|
||||
# %1$S is the option that could not be understood
|
||||
doNotUnderstandOption = don't understand option '%1$S'. Ignoring it.
|
||||
# LOCALIZATION NOTE (notETLDPlus1):
|
||||
# %1$S is the ETLD of the report URI that could not be used
|
||||
notETLDPlus1 = can't use report URI from non-matching eTLD+1: %1$S
|
||||
# LOCALIZATION NOTE (notSameScheme):
|
||||
# %1$S is the report URI that could not be used
|
||||
notSameScheme = can't use report URI with different scheme from originating document: %1$S
|
||||
# LOCALIZATION NOTE (notSamePort):
|
||||
# %1$S is the report URI that could not be used
|
||||
notSamePort = can't use report URI with different port from originating document: %1$S
|
||||
# LOCALIZATION NOTE (pageCannotSendReportsTo):
|
||||
# %1$S is the URI of the page with the policy
|
||||
# %2$S is the report URI that could not be used
|
||||
pageCannotSendReportsTo = page on %1$S cannot send reports to %2$S
|
||||
allowOrDefaultSrcRequired = 'allow' or 'default-src' directive required but not present. Reverting to "default-src 'none'"
|
||||
# LOCALIZATION NOTE (failedToParseUnrecognizedSource):
|
||||
# %1$S is the CSP Source that could not be parsed
|
||||
failedToParseUnrecognizedSource = Failed to parse unrecoginzied source %1$S
|
||||
# LOCALIZATION NOTE (reportPostRedirect):
|
||||
# %1$S is the specified report URI before redirect
|
||||
reportPostRedirect = Post of violation report to %1$S failed, as a redirect occurred
|
||||
|
||||
# CSP Errors:
|
||||
policyURINotAlone = policy-uri directive can only appear alone
|
||||
noParentRequest = The policy-uri cannot be fetched without a parent request and a CSP.
|
||||
# LOCALIZATION NOTE (policyURIParseError):
|
||||
# %1$S is the URI that could not be parsed
|
||||
policyURIParseError = could not parse URI in policy URI: %1$S
|
||||
# LOCALIZATION NOTE (nonMatchingHost):
|
||||
# %1$S is the URI host that does not match
|
||||
nonMatchingHost = can't fetch policy uri from non-matching hostname: %1$S
|
||||
# LOCALIZATION NOTE (nonMatchingPort):
|
||||
# %1$S is the URI port that does not match
|
||||
nonMatchingPort = can't fetch policy uri from non-matching port: %1$S
|
||||
# LOCALIZATION NOTE (nonMatchingScheme):
|
||||
# %1$S is the URI scheme that does not match
|
||||
nonMatchingScheme = can't fetch policy uri from non-matching scheme: %1$S
|
||||
# LOCALIZATION NOTE (errorFetchingPolicy):
|
||||
# %1$S is the error that caused fetching to fail
|
||||
errorFetchingPolicy = Error fetching policy-uri: %1$S
|
||||
cspSourceNotURI = Provided argument is not an nsIURI
|
||||
argumentIsNotString = Provided argument is not a string
|
||||
selfDataNotProvided = Can't use 'self' if self data is not provided
|
||||
# LOCALIZATION NOTE (uriWithoutScheme):
|
||||
# %1$S is the URI without a scheme
|
||||
uriWithoutScheme = can't parse a URI without a scheme: %1$S
|
||||
selfKeywordNoSelfData = self keyword used, but no self data specified
|
||||
# LOCALIZATION NOTE (couldntParseInvalidSource):
|
||||
# %1$S is the source that could not be parsed
|
||||
couldntParseInvalidSource = Couldn't parse invalid source %1$S
|
||||
# LOCALIZATION NOTE (hostSourceWithoutData):
|
||||
# %1$S is the source
|
||||
hostSourceWithoutData = Can't create host-only source %1$S without 'self' data
|
||||
# LOCALIZATION NOTE (sourceWithoutData):
|
||||
# %1$S is the source
|
||||
sourceWithoutData = Can't create source %1$S without 'self' data
|
||||
# LOCALIZATION NOTE (couldntParseInvalidHost):
|
||||
# %1$S is the host that's invalid
|
||||
couldntParseInvalidHost = Couldn't parse invalid host %1$S
|
||||
# LOCALIZATION NOTE (couldntParseScheme):
|
||||
# %1$S is the string source
|
||||
couldntParseScheme = Couldn't parse scheme in %1$S
|
||||
# LOCALIZATION NOTE (couldntParsePort):
|
||||
# %1$S is the string source
|
||||
couldntParsePort = Couldn't parse port in %1$S
|
||||
# LOCALIZATION NOTE (notIntersectPort):
|
||||
# %1$S is one source we tried to intersect
|
||||
# %2$S is the other
|
||||
notIntersectPort = Could not intersect %1$S with %2$S due to port problems.
|
||||
# LOCALIZATION NOTE (notIntersectScheme):
|
||||
# %1$S is one source we tried to intersect
|
||||
# %2$S is the other
|
||||
notIntersectScheme = Could not intersect %1$S with %2$S due to scheme problems.
|
||||
# LOCALIZATION NOTE (intersectingSourceWithUndefinedHost):
|
||||
# %1$S is the source
|
||||
intersectingSourceWithUndefinedHost = intersecting source with undefined host: %1$S
|
||||
# LOCALIZATION NOTE (intersectingSourcesWithUndefinedHosts):
|
||||
# %1$S is the first source
|
||||
# %2$S is the second source
|
||||
intersectingSourcesWithUndefinedHosts = intersecting two sources with undefined hosts: %1$S and %2$S
|
|
@ -26,6 +26,7 @@
|
|||
locale/@AB_CD@/global/layout/xmlparser.properties (%chrome/layout/xmlparser.properties)
|
||||
locale/@AB_CD@/global/layout/HtmlForm.properties (%chrome/layout/HtmlForm.properties)
|
||||
locale/@AB_CD@/global/security/caps.properties (%chrome/security/caps.properties)
|
||||
locale/@AB_CD@/global/security/csp.properties (%chrome/security/csp.properties)
|
||||
locale/@AB_CD@/global/xml/prettyprint.dtd (%chrome/xml/prettyprint.dtd)
|
||||
locale/@AB_CD@/global-platform/win/accessible.properties (%chrome/accessibility/win/accessible.properties)
|
||||
locale/@AB_CD@/global-platform/mac/accessible.properties (%chrome/accessibility/mac/accessible.properties)
|
||||
|
|
|
@ -633,23 +633,11 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
|
|||
}
|
||||
#endif
|
||||
|
||||
nsPresContext* presContext = mObjectFrame->PresContext();
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(invalidRect->left),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->top),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left),
|
||||
presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top));
|
||||
if (container) {
|
||||
gfxIntSize newSize = container->GetCurrentSize();
|
||||
if (newSize != oldSize) {
|
||||
// The image size has changed - invalidate the old area too, bug 635405.
|
||||
nsRect oldRect = nsRect(0, 0,
|
||||
presContext->DevPixelsToAppUnits(oldSize.width),
|
||||
presContext->DevPixelsToAppUnits(oldSize.height));
|
||||
rect.UnionRect(rect, oldRect);
|
||||
}
|
||||
}
|
||||
rect.MoveBy(mObjectFrame->GetContentRectRelativeToSelf().TopLeft());
|
||||
mObjectFrame->InvalidateLayer(rect, nsDisplayItem::TYPE_PLUGIN);
|
||||
nsIntRect rect(invalidRect->left,
|
||||
invalidRect->top,
|
||||
invalidRect->right - invalidRect->left,
|
||||
invalidRect->bottom - invalidRect->top);
|
||||
mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -662,7 +650,7 @@ NS_IMETHODIMP
|
|||
nsPluginInstanceOwner::RedrawPlugin()
|
||||
{
|
||||
if (mObjectFrame) {
|
||||
mObjectFrame->InvalidateLayer(mObjectFrame->GetContentRectRelativeToSelf(), nsDisplayItem::TYPE_PLUGIN);
|
||||
mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3768,7 +3756,7 @@ void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
|
|||
mObjectFrame->PrepForDrawing(mWidget);
|
||||
}
|
||||
mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
|
||||
mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
|
||||
mObjectFrame->InvalidateFrame();
|
||||
|
||||
// Scroll position listening is only required for Carbon event model plugins on Mac OS X.
|
||||
#if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
|
||||
|
|
|
@ -94,8 +94,9 @@ function done() {
|
|||
|
||||
function waitForPaint(func) {
|
||||
paint_waiter.last_paint_count = paint_waiter.getPaintCount();
|
||||
// Ensure the waiter has been reflowed with zero height, so that this will
|
||||
// Ensure the waiter has had a style change, so that this will
|
||||
// change its size and cause a paint.
|
||||
paint_waiter.style.backgroundColor = paint_waiter.style.backgroundColor == "blue" ? "yellow" : "blue";
|
||||
var flush = paint_waiter.offsetHeight;
|
||||
paint_waiter.style.height = "1px";
|
||||
waitForPaintHelper(func);
|
||||
|
|
|
@ -9,6 +9,7 @@ var popupNotifications = getPopupNotifications(window.top);
|
|||
var event_listener_loaded = {};
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/Webapps.jsm");
|
||||
|
||||
Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager)
|
||||
|
@ -21,6 +22,9 @@ SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
|
|||
SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', true);
|
||||
SpecialPowers.setBoolPref("dom.mozBrowserFramesWhitelist", "http://www.example.com");
|
||||
|
||||
let originalAAL = DOMApplicationRegistry.allAppsLaunchable;
|
||||
DOMApplicationRegistry.allAppsLaunchable = true;
|
||||
|
||||
var triggered = false;
|
||||
|
||||
function iterateMethods(label, root, suppress) {
|
||||
|
@ -104,5 +108,6 @@ function tearDown() {
|
|||
uninstallAll();
|
||||
popupNotifications.panel.removeEventListener("popupshown", mainCommand, false);
|
||||
SpecialPowers.clearUserPref('browser.mozApps.installer.dry_run');
|
||||
DOMApplicationRegistry.allAppsLaunchable = originalAAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
var expectedMethods = ['navigator.mozApps.QueryInterface',
|
||||
'navigator.mozApps.getInstalled',
|
||||
'navigator.mozApps.getNotInstalled',
|
||||
'navigator.mozApps.getSelf',
|
||||
'navigator.mozApps.install',
|
||||
'navigator.mozApps.mgmt.QueryInterface',
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/
|
||||
*
|
||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||
* Opera Software ASA. You are granted a license to use, reproduce
|
||||
* and create derivative works of this document.
|
||||
*/
|
||||
|
||||
interface CanvasGradient;
|
||||
interface CanvasPattern;
|
||||
interface HitRegionOptions;
|
||||
interface HTMLCanvasElement;
|
||||
interface HTMLImageElement;
|
||||
interface HTMLVideoElement;
|
||||
interface ImageData;
|
||||
interface TextMetrics;
|
||||
interface Window;
|
||||
interface XULElement;
|
||||
|
||||
interface CanvasRenderingContext2D {
|
||||
|
||||
// back-reference to the canvas
|
||||
readonly attribute HTMLCanvasElement canvas;
|
||||
|
||||
// state
|
||||
void save(); // push state on state stack
|
||||
void restore(); // pop state stack and restore state
|
||||
|
||||
// transformations (default transform is the identity matrix)
|
||||
// NOT IMPLEMENTED attribute SVGMatrix currentTransform;
|
||||
void scale(double x, double y);
|
||||
void rotate(double angle);
|
||||
void translate(double x, double y);
|
||||
void transform(double a, double b, double c, double d, double e, double f);
|
||||
void setTransform(double a, double b, double c, double d, double e, double f);
|
||||
// NOT IMPLEMENTED void resetTransform();
|
||||
|
||||
// compositing
|
||||
attribute double globalAlpha; // (default 1.0)
|
||||
attribute DOMString globalCompositeOperation; // (default source-over)
|
||||
|
||||
// colors and styles (see also the CanvasDrawingStyles interface)
|
||||
attribute any strokeStyle; // (default black)
|
||||
attribute any fillStyle; // (default black)
|
||||
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
|
||||
CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
|
||||
CanvasPattern createPattern((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, DOMString repetition);
|
||||
|
||||
// shadows
|
||||
attribute double shadowOffsetX; // (default 0)
|
||||
attribute double shadowOffsetY; // (default 0)
|
||||
attribute double shadowBlur; // (default 0)
|
||||
attribute DOMString shadowColor; // (default transparent black)
|
||||
|
||||
// rects
|
||||
void clearRect(double x, double y, double w, double h);
|
||||
void fillRect(double x, double y, double w, double h);
|
||||
void strokeRect(double x, double y, double w, double h);
|
||||
|
||||
// path API (see also CanvasPathMethods)
|
||||
void beginPath();
|
||||
void fill();
|
||||
// NOT IMPLEMENTED void fill(Path path);
|
||||
void stroke();
|
||||
// NOT IMPLEMENTED void stroke(Path path);
|
||||
// NOT IMPLEMENTED void drawSystemFocusRing(Element element);
|
||||
// NOT IMPLEMENTED void drawSystemFocusRing(Path path, Element element);
|
||||
// NOT IMPLEMENTED boolean drawCustomFocusRing(Element element);
|
||||
// NOT IMPLEMENTED boolean drawCustomFocusRing(Path path, Element element);
|
||||
// NOT IMPLEMENTED void scrollPathIntoView();
|
||||
// NOT IMPLEMENTED void scrollPathIntoView(Path path);
|
||||
void clip();
|
||||
// NOT IMPLEMENTED void clip(Path path);
|
||||
// NOT IMPLEMENTED void resetClip();
|
||||
boolean isPointInPath(double x, double y);
|
||||
// NOT IMPLEMENTED boolean isPointInPath(Path path, double x, double y);
|
||||
|
||||
// text (see also the CanvasDrawingStyles interface)
|
||||
void fillText(DOMString text, double x, double y, optional double maxWidth);
|
||||
void strokeText(DOMString text, double x, double y, optional double maxWidth);
|
||||
TextMetrics measureText(DOMString text);
|
||||
|
||||
// drawing images
|
||||
// NOT IMPLEMENTED attribute boolean imageSmoothingEnabled; // (default true)
|
||||
void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double dx, double dy);
|
||||
void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double dx, double dy, double dw, double dh);
|
||||
void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh);
|
||||
|
||||
// hit regions
|
||||
// NOT IMPLEMENTED void addHitRegion(HitRegionOptions options);
|
||||
|
||||
// pixel manipulation
|
||||
[Creator] ImageData createImageData(double sw, double sh);
|
||||
[Creator] ImageData createImageData(ImageData imagedata);
|
||||
[Creator] ImageData getImageData(double sx, double sy, double sw, double sh);
|
||||
void putImageData(ImageData imagedata, double dx, double dy);
|
||||
void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
|
||||
|
||||
// Mozilla-specific stuff
|
||||
// FIXME Bug 768048 mozCurrentTransform/mozCurrentTransformInverse should return a WebIDL array.
|
||||
attribute object mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
|
||||
attribute object mozCurrentTransformInverse;
|
||||
attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
|
||||
attribute any mozDash; /* default |null| */
|
||||
attribute double mozDashOffset; /* default 0.0 */
|
||||
attribute DOMString mozTextStyle;
|
||||
|
||||
// image smoothing mode -- if disabled, images won't be smoothed
|
||||
// if scaled.
|
||||
attribute boolean mozImageSmoothingEnabled;
|
||||
|
||||
// Show the caret if appropriate when drawing
|
||||
const unsigned long DRAWWINDOW_DRAW_CARET = 0x01;
|
||||
// Don't flush pending layout notifications that could otherwise
|
||||
// be batched up
|
||||
const unsigned long DRAWWINDOW_DO_NOT_FLUSH = 0x02;
|
||||
// Draw scrollbars and scroll the viewport if they are present
|
||||
const unsigned long DRAWWINDOW_DRAW_VIEW = 0x04;
|
||||
// Use the widget layer manager if available. This means hardware
|
||||
// acceleration may be used, but it might actually be slower or
|
||||
// lower quality than normal. It will however more accurately reflect
|
||||
// the pixels rendered to the screen.
|
||||
const unsigned long DRAWWINDOW_USE_WIDGET_LAYERS = 0x08;
|
||||
// Don't synchronously decode images - draw what we have
|
||||
const unsigned long DRAWWINDOW_ASYNC_DECODE_IMAGES = 0x10;
|
||||
|
||||
/**
|
||||
* Renders a region of a window into the canvas. The contents of
|
||||
* the window's viewport are rendered, ignoring viewport clipping
|
||||
* and scrolling.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param w
|
||||
* @param h specify the area of the window to render, in CSS
|
||||
* pixels.
|
||||
*
|
||||
* @param backgroundColor the canvas is filled with this color
|
||||
* before we render the window into it. This color may be
|
||||
* transparent/translucent. It is given as a CSS color string
|
||||
* (e.g., rgb() or rgba()).
|
||||
*
|
||||
* @param flags Used to better control the drawWindow call.
|
||||
* Flags can be ORed together.
|
||||
*
|
||||
* Of course, the rendering obeys the current scale, transform and
|
||||
* globalAlpha values.
|
||||
*
|
||||
* Hints:
|
||||
* -- If 'rgba(0,0,0,0)' is used for the background color, the
|
||||
* drawing will be transparent wherever the window is transparent.
|
||||
* -- Top-level browsed documents are usually not transparent
|
||||
* because the user's background-color preference is applied,
|
||||
* but IFRAMEs are transparent if the page doesn't set a background.
|
||||
* -- If an opaque color is used for the background color, rendering
|
||||
* will be faster because we won't have to compute the window's
|
||||
* transparency.
|
||||
*
|
||||
* This API cannot currently be used by Web content. It is chrome
|
||||
* only.
|
||||
* FIXME Bug 767931 - Mark drawWindow and asyncDrawXULElement as ChromeOnly
|
||||
* in WebIDL
|
||||
*/
|
||||
void drawWindow(Window window, double x, double y, double w, double h,
|
||||
DOMString bgColor, optional unsigned long flags = 0);
|
||||
void asyncDrawXULElement(XULElement elem, double x, double y, double w,
|
||||
double h, DOMString bgColor,
|
||||
optional unsigned long flags = 0);
|
||||
};
|
||||
CanvasRenderingContext2D implements CanvasDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasPathMethods;
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface CanvasDrawingStyles {
|
||||
// line caps/joins
|
||||
attribute double lineWidth; // (default 1)
|
||||
attribute DOMString lineCap; // "butt", "round", "square" (default "butt")
|
||||
attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter")
|
||||
attribute double miterLimit; // (default 10)
|
||||
|
||||
// dashed lines
|
||||
// NOT IMPLEMENTED void setLineDash(sequence<double> segments); // default empty
|
||||
// NOT IMPLEMENTED sequence<double> getLineDash();
|
||||
// NOT IMPLEMENTED attribute double lineDashOffset;
|
||||
|
||||
// text
|
||||
attribute DOMString font; // (default 10px sans-serif)
|
||||
attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start")
|
||||
attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic")
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface CanvasPathMethods {
|
||||
// shared path API methods
|
||||
void closePath();
|
||||
void moveTo(double x, double y);
|
||||
void lineTo(double x, double y);
|
||||
void quadraticCurveTo(double cpx, double cpy, double x, double y);
|
||||
void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y);
|
||||
void arcTo(double x1, double y1, double x2, double y2, double radius);
|
||||
// NOT IMPLEMENTED void arcTo(double x1, double y1, double x2, double y2, double radiusX, double radiusY, double rotation);
|
||||
void rect(double x, double y, double w, double h);
|
||||
void arc(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false);
|
||||
// NOT IMPLEMENTED void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean anticlockwise);
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
webidl_base = $(topsrcdir)/dom/webidl
|
||||
|
||||
webidl_files = \
|
||||
CanvasRenderingContext2D.webidl \
|
||||
Function.webidl \
|
||||
EventListener.webidl \
|
||||
EventTarget.webidl \
|
||||
|
|
|
@ -371,8 +371,8 @@ ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsign
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Don't care about assignments or declarations, bail now.
|
||||
if (aFlags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING)) {
|
||||
// Don't care about assignments, bail now.
|
||||
if (aFlags & JSRESOLVE_ASSIGNING) {
|
||||
*aObjp = nsnull;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ load 615450-1.html
|
|||
load 639736-1.xhtml
|
||||
load 643786-1.html
|
||||
load 682650-1.html
|
||||
load 716456-1.html
|
||||
asserts(0-1) load 716456-1.html
|
||||
load 759748.html
|
||||
load 761861.html
|
||||
load 766305.html
|
||||
|
|
|
@ -45,7 +45,7 @@ fails-if(Android) != spellcheck-input-property-dynamic-override-inherit.html spe
|
|||
random-if(Android) != spellcheck-textarea-attr.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref.html
|
||||
needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref2.html
|
||||
random-if(Android) != spellcheck-textarea-nofocus.html spellcheck-textarea-ref.html
|
||||
random-if(Android) != spellcheck-textarea-disabled.html spellcheck-textarea-ref.html
|
||||
random-if(Android) != spellcheck-textarea-attr-inherit.html spellcheck-textarea-ref.html
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<body>
|
||||
|
||||
<textarea id="testBox" readonly></textarea>
|
||||
<textarea id="testBox" style="padding:2px;" readonly></textarea>
|
||||
<script type="text/javascript">
|
||||
//Adding focus to the textbox should trigger a spellcheck
|
||||
var textbox = document.getElementById("testBox");
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea spellcheck="true" style="padding:2px;">blahblahblah</textarea>
|
||||
<script type="text/javascript">
|
||||
var box = document.getElementsByTagName("textarea")[0];
|
||||
box.focus(); //Bring the textbox into focus, triggering a spellcheck
|
||||
box.blur(); //Blur in order to make things similar to other tests otherwise
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:ts=2:sw=2:et: */
|
||||
/* vim: set ts=2 sw=2 et: */
|
||||
/* 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/. */
|
||||
|
|
|
@ -26,8 +26,16 @@ public:
|
|||
/* Attaches untyped userData associated with key. destroy is called on destruction */
|
||||
void Add(UserDataKey *key, void *userData, destroyFunc destroy)
|
||||
{
|
||||
// XXX we should really warn if user data with key has already been added,
|
||||
// since in that case Get() will return the old user data!
|
||||
for (int i=0; i<count; i++) {
|
||||
if (key == entries[i].key) {
|
||||
if (entries[i].destroy) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
}
|
||||
entries[i].userData = userData;
|
||||
entries[i].destroy = destroy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We could keep entries in a std::vector instead of managing it by hand
|
||||
// but that would propagate an stl dependency out which we'd rather not
|
||||
|
@ -74,12 +82,21 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
~UserData()
|
||||
void Destroy()
|
||||
{
|
||||
for (int i=0; i<count; i++) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
if (entries[i].destroy) {
|
||||
entries[i].destroy(entries[i].userData);
|
||||
}
|
||||
}
|
||||
free(entries);
|
||||
entries = NULL;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
~UserData()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -606,9 +606,10 @@ public:
|
|||
mScaleMode = aMode;
|
||||
}
|
||||
|
||||
|
||||
ImageContainer* GetContainer() { return mContainer; }
|
||||
gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
|
||||
const gfxIntSize& GetScaleToSize() { return mScaleToSize; }
|
||||
ScaleMode GetScaleMode() { return mScaleMode; }
|
||||
|
||||
MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE)
|
||||
|
||||
|
|
|
@ -0,0 +1,331 @@
|
|||
/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "LayerTreeInvalidation.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct LayerPropertiesBase;
|
||||
LayerPropertiesBase* CloneLayerTreePropertiesInternal(Layer* aRoot);
|
||||
|
||||
static nsIntRect
|
||||
TransformRect(const nsIntRect& aRect, const gfx3DMatrix& aTransform)
|
||||
{
|
||||
if (aRect.IsEmpty()) {
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
rect = aTransform.TransformBounds(rect);
|
||||
rect.RoundOut();
|
||||
|
||||
nsIntRect intRect;
|
||||
if (!gfxUtils::GfxRectToIntRect(rect, &intRect)) {
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
return intRect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks over this layer, and all descendant layers.
|
||||
* If any of these are a ContainerLayer that reports invalidations to a PresShell,
|
||||
* then report that the entire bounds have changed.
|
||||
*/
|
||||
static void
|
||||
NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
aLayer->ClearInvalidRect();
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
NotifySubdocumentInvalidationRecursive(aLayer->GetMaskLayer(), aCallback);
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
NotifySubdocumentInvalidationRecursive(child, aCallback);
|
||||
}
|
||||
|
||||
aCallback(container, container->GetVisibleRegion());
|
||||
}
|
||||
|
||||
struct LayerPropertiesBase : public LayerProperties
|
||||
{
|
||||
LayerPropertiesBase(Layer* aLayer)
|
||||
: mLayer(aLayer)
|
||||
, mMaskLayer(nsnull)
|
||||
, mVisibleBounds(aLayer->GetVisibleRegion().GetBounds())
|
||||
, mTransform(aLayer->GetTransform())
|
||||
, mOpacity(aLayer->GetOpacity())
|
||||
, mUseClipRect(!!aLayer->GetClipRect())
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer());
|
||||
}
|
||||
if (mUseClipRect) {
|
||||
mClipRect = *aLayer->GetClipRect();
|
||||
}
|
||||
}
|
||||
LayerPropertiesBase()
|
||||
: mLayer(nsnull)
|
||||
, mMaskLayer(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
}
|
||||
~LayerPropertiesBase()
|
||||
{
|
||||
MOZ_COUNT_DTOR(LayerPropertiesBase);
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeDifferences(Layer* aRoot,
|
||||
NotifySubDocInvalidationFunc aCallback);
|
||||
|
||||
nsIntRect ComputeChange(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
bool transformChanged = mTransform != mLayer->GetTransform();
|
||||
Layer* otherMask = mLayer->GetMaskLayer();
|
||||
const nsIntRect* otherClip = mLayer->GetClipRect();
|
||||
nsIntRect result;
|
||||
if ((mMaskLayer ? mMaskLayer->mLayer : nsnull) != otherMask ||
|
||||
(mUseClipRect != !!otherClip) ||
|
||||
mLayer->GetOpacity() != mOpacity ||
|
||||
transformChanged)
|
||||
{
|
||||
result = OldTransformedBounds();
|
||||
if (transformChanged) {
|
||||
result = result.Union(NewTransformedBounds());
|
||||
}
|
||||
|
||||
// If we don't have to generate invalidations separately for child
|
||||
// layers then we can just stop here since we've already invalidated the entire
|
||||
// old and new bounds.
|
||||
if (!aCallback) {
|
||||
ClearInvalidations(mLayer);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = result.Union(ComputeChangeInternal(aCallback));
|
||||
result = result.Union(TransformRect(mLayer->GetInvalidRegion().GetBounds(), mTransform));
|
||||
|
||||
if (mMaskLayer && otherMask) {
|
||||
nsIntRect maskDiff = mMaskLayer->ComputeChange(aCallback);
|
||||
result = result.Union(TransformRect(maskDiff, mTransform));
|
||||
}
|
||||
|
||||
if (mUseClipRect && otherClip) {
|
||||
if (!mClipRect.IsEqualInterior(*otherClip)) {
|
||||
nsIntRegion tmp;
|
||||
tmp.Xor(mClipRect, *otherClip);
|
||||
result = result.Union(tmp.GetBounds());
|
||||
}
|
||||
}
|
||||
|
||||
mLayer->ClearInvalidRect();
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIntRect NewTransformedBounds()
|
||||
{
|
||||
return TransformRect(mLayer->GetVisibleRegion().GetBounds(), mLayer->GetTransform());
|
||||
}
|
||||
|
||||
nsIntRect OldTransformedBounds()
|
||||
{
|
||||
return TransformRect(mVisibleBounds, mTransform);
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
|
||||
|
||||
Layer* mLayer;
|
||||
nsAutoPtr<LayerPropertiesBase> mMaskLayer;
|
||||
nsIntRect mVisibleBounds;
|
||||
gfx3DMatrix mTransform;
|
||||
float mOpacity;
|
||||
nsIntRect mClipRect;
|
||||
bool mUseClipRect;
|
||||
};
|
||||
|
||||
struct ContainerLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ContainerLayerProperties(ContainerLayer* aLayer)
|
||||
: LayerPropertiesBase(aLayer)
|
||||
{
|
||||
for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
|
||||
}
|
||||
}
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ContainerLayer* container = mLayer->AsContainerLayer();
|
||||
nsIntRegion result;
|
||||
|
||||
PRUint32 i = 0;
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
if (i >= mChildren.Length() || child != mChildren[i]->mLayer) {
|
||||
// Child change. Invalidate the full areas.
|
||||
// TODO: We could be smarter here if non-overlapping children
|
||||
// swap order.
|
||||
result.Or(result, TransformRect(child->GetVisibleRegion().GetBounds(), child->GetTransform()));
|
||||
if (i < mChildren.Length()) {
|
||||
result.Or(result, mChildren[i]->OldTransformedBounds());
|
||||
}
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidationRecursive(child, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(child);
|
||||
}
|
||||
} else {
|
||||
// Same child, check for differences within the child
|
||||
result.Or(result, mChildren[i]->ComputeChange(aCallback));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Process remaining removed children.
|
||||
while (i < mChildren.Length()) {
|
||||
result.Or(result, mChildren[i]->OldTransformedBounds());
|
||||
i++;
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback(container, result);
|
||||
}
|
||||
|
||||
return TransformRect(result.GetBounds(), mLayer->GetTransform());
|
||||
}
|
||||
|
||||
nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
|
||||
};
|
||||
|
||||
struct ColorLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ColorLayerProperties(ColorLayer *aLayer)
|
||||
: LayerPropertiesBase(aLayer)
|
||||
, mColor(aLayer->GetColor())
|
||||
{ }
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ColorLayer* color = static_cast<ColorLayer*>(mLayer);
|
||||
|
||||
if (mColor != color->GetColor()) {
|
||||
return NewTransformedBounds();
|
||||
}
|
||||
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
gfxRGBA mColor;
|
||||
};
|
||||
|
||||
struct ImageLayerProperties : public LayerPropertiesBase
|
||||
{
|
||||
ImageLayerProperties(ImageLayer* aImage)
|
||||
: LayerPropertiesBase(aImage)
|
||||
, mVisibleRegion(aImage->GetVisibleRegion())
|
||||
, mContainer(aImage->GetContainer())
|
||||
, mFilter(aImage->GetFilter())
|
||||
, mScaleToSize(aImage->GetScaleToSize())
|
||||
, mScaleMode(aImage->GetScaleMode())
|
||||
{ }
|
||||
|
||||
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
ImageLayer* image = static_cast<ImageLayer*>(mLayer);
|
||||
|
||||
if (!image->GetVisibleRegion().IsEqual(mVisibleRegion)) {
|
||||
nsIntRect result = NewTransformedBounds();
|
||||
result = result.Union(OldTransformedBounds());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (mContainer != image->GetContainer() ||
|
||||
mFilter != image->GetFilter() ||
|
||||
mScaleToSize != image->GetScaleToSize() ||
|
||||
mScaleMode != image->GetScaleMode()) {
|
||||
return NewTransformedBounds();
|
||||
}
|
||||
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
nsIntRegion mVisibleRegion;
|
||||
nsRefPtr<ImageContainer> mContainer;
|
||||
gfxPattern::GraphicsFilter mFilter;
|
||||
gfxIntSize mScaleToSize;
|
||||
ImageLayer::ScaleMode mScaleMode;
|
||||
};
|
||||
|
||||
LayerPropertiesBase*
|
||||
CloneLayerTreePropertiesInternal(Layer* aRoot)
|
||||
{
|
||||
if (!aRoot) {
|
||||
return new LayerPropertiesBase();
|
||||
}
|
||||
|
||||
switch (aRoot->GetType()) {
|
||||
case Layer::TYPE_CONTAINER: return new ContainerLayerProperties(aRoot->AsContainerLayer());
|
||||
case Layer::TYPE_COLOR: return new ColorLayerProperties(static_cast<ColorLayer*>(aRoot));
|
||||
case Layer::TYPE_IMAGE: return new ImageLayerProperties(static_cast<ImageLayer*>(aRoot));
|
||||
default: return new LayerPropertiesBase(aRoot);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* static */ LayerProperties*
|
||||
LayerProperties::CloneFrom(Layer* aRoot)
|
||||
{
|
||||
return CloneLayerTreePropertiesInternal(aRoot);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
LayerProperties::ClearInvalidations(Layer *aLayer)
|
||||
{
|
||||
aLayer->ClearInvalidRect();
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
ClearInvalidations(aLayer->GetMaskLayer());
|
||||
}
|
||||
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
ClearInvalidations(child);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFunc aCallback)
|
||||
{
|
||||
NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
|
||||
if (mLayer != aRoot) {
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidationRecursive(aRoot, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(aRoot);
|
||||
}
|
||||
nsIntRect result = TransformRect(aRoot->GetVisibleRegion().GetBounds(), aRoot->GetTransform());
|
||||
result = result.Union(OldTransformedBounds());
|
||||
return result;
|
||||
} else {
|
||||
return ComputeChange(aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,64 @@
|
|||
/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 GFX_LAYER_TREE_INVALIDATION_H
|
||||
#define GFX_LAYER_TREE_INVALIDATION_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* Callback for ContainerLayer invalidations.
|
||||
*
|
||||
* @param aContainer ContainerLayer being invalidated.
|
||||
* @param aRegion Invalidated region in the ContainerLayer's coordinate
|
||||
* space.
|
||||
*/
|
||||
typedef void (*NotifySubDocInvalidationFunc)(ContainerLayer* aLayer,
|
||||
const nsIntRegion& aRegion);
|
||||
|
||||
/**
|
||||
* A set of cached layer properties (including those of child layers),
|
||||
* used for comparing differences in layer trees.
|
||||
*/
|
||||
struct LayerProperties
|
||||
{
|
||||
virtual ~LayerProperties() {}
|
||||
|
||||
/**
|
||||
* Copies the current layer tree properties into
|
||||
* a new LayerProperties object.
|
||||
*
|
||||
* @param Layer tree to copy, or nsnull if we have no
|
||||
* initial layer tree.
|
||||
*/
|
||||
static LayerProperties* CloneFrom(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Clear all invalidation status from this layer tree.
|
||||
*/
|
||||
static void ClearInvalidations(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Compares a set of existing layer tree properties to the current layer
|
||||
* tree and generates the changed rectangle.
|
||||
*
|
||||
* @param aRoot Root layer of the layer tree to compare against.
|
||||
* @param aCallback If specified, callback to call when ContainerLayers
|
||||
* are invalidated.
|
||||
* @return Painted area changed by the layer tree changes.
|
||||
*/
|
||||
virtual nsIntRect ComputeDifferences(Layer* aRoot,
|
||||
NotifySubDocInvalidationFunc aCallback) = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_LAYER_TREE_INVALIDATON_H */
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче