This commit is contained in:
Ms2ger 2012-06-30 14:50:23 +02:00
Родитель fba607073c f486010303
Коммит afc7a3b381
530 изменённых файлов: 19438 добавлений и 12497 удалений

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

@ -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 */

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