Merge mozilla-central to tracemonkey.
@ -1507,17 +1507,12 @@ SessionStoreService.prototype = {
|
||||
_updateCookieHosts: function sss_updateCookieHosts(aWindow) {
|
||||
var hosts = this._windows[aWindow.__SSi]._hosts = {};
|
||||
|
||||
// get all possible subdomain levels for a given URL
|
||||
var _this = this;
|
||||
// get the domain for each URL
|
||||
function extractHosts(aEntry) {
|
||||
if (/^https?:\/\/(?:[^@\/\s]+@)?([\w.-]+)/.test(aEntry.url) &&
|
||||
!hosts[RegExp.$1] && _this._checkPrivacyLevel(_this._getURIFromString(aEntry.url).schemeIs("https"))) {
|
||||
var host = RegExp.$1;
|
||||
var ix;
|
||||
for (ix = host.indexOf(".") + 1; ix; ix = host.indexOf(".", ix) + 1) {
|
||||
hosts[host.substr(ix)] = true;
|
||||
if (/^https?:\/\/(?:[^@\/\s]+@)?([\w.-]+)/.test(aEntry.url)) {
|
||||
if (!hosts[RegExp.$1] && this._checkPrivacyLevel(this._getURIFromString(aEntry.url).schemeIs("https"))) {
|
||||
hosts[RegExp.$1] = true;
|
||||
}
|
||||
hosts[host] = true;
|
||||
}
|
||||
else if (/^file:\/\/([^\/]*)/.test(aEntry.url)) {
|
||||
hosts[RegExp.$1] = true;
|
||||
@ -1526,8 +1521,8 @@ SessionStoreService.prototype = {
|
||||
aEntry.children.forEach(extractHosts);
|
||||
}
|
||||
}
|
||||
|
||||
this._windows[aWindow.__SSi].tabs.forEach(function(aTabData) { aTabData.entries.forEach(extractHosts); });
|
||||
|
||||
this._windows[aWindow.__SSi].tabs.forEach(function(aTabData) { aTabData.entries.forEach(extractHosts, this); }, this);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1536,36 +1531,59 @@ SessionStoreService.prototype = {
|
||||
* array of Window references
|
||||
*/
|
||||
_updateCookies: function sss_updateCookies(aWindows) {
|
||||
var cookiesEnum = Cc["@mozilla.org/cookiemanager;1"].
|
||||
getService(Ci.nsICookieManager).enumerator;
|
||||
function addCookieToHash(aHash, aHost, aPath, aName, aCookie) {
|
||||
// lazily build up a 3-dimensional hash, with
|
||||
// aHost, aPath, and aName as keys
|
||||
if (!aHash[aHost])
|
||||
aHash[aHost] = {};
|
||||
if (!aHash[aHost][aPath])
|
||||
aHash[aHost][aPath] = {};
|
||||
if (!aHash[aHost][aPath][aName])
|
||||
aHash[aHost][aPath][aName] = {};
|
||||
|
||||
aHash[aHost][aPath][aName] = aCookie;
|
||||
}
|
||||
|
||||
var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
|
||||
// collect the cookies per window
|
||||
for (var i = 0; i < aWindows.length; i++)
|
||||
aWindows[i].cookies = [];
|
||||
|
||||
|
||||
var jscookies = {};
|
||||
// MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
|
||||
var MAX_EXPIRY = Math.pow(2, 62);
|
||||
while (cookiesEnum.hasMoreElements()) {
|
||||
var cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
|
||||
if (cookie.isSession && this._checkPrivacyLevel(cookie.isSecure)) {
|
||||
var jscookie = null;
|
||||
aWindows.forEach(function(aWindow) {
|
||||
if (aWindow._hosts && aWindow._hosts[cookie.rawHost]) {
|
||||
// serialize the cookie when it's first needed
|
||||
if (!jscookie) {
|
||||
jscookie = { host: cookie.host, value: cookie.value };
|
||||
aWindows.forEach(function(aWindow) {
|
||||
for (var host in aWindow._hosts) {
|
||||
var list = cm.getCookiesFromHost(host);
|
||||
while (list.hasMoreElements()) {
|
||||
var cookie = list.getNext().QueryInterface(Ci.nsICookie2);
|
||||
if (cookie.isSession && this._checkPrivacyLevel(cookie.isSecure)) {
|
||||
// use the cookie's host, path, and name as keys into a hash,
|
||||
// to make sure we serialize each cookie only once
|
||||
var isInHash = false;
|
||||
try {
|
||||
if (jscookies[cookie.host][cookie.path][cookie.name])
|
||||
isInHash = true;
|
||||
} catch (e) {
|
||||
// not in hash yet
|
||||
}
|
||||
if (!isInHash) {
|
||||
var jscookie = { "host": cookie.host, "value": cookie.value };
|
||||
// only add attributes with non-default values (saving a few bits)
|
||||
if (cookie.path) jscookie.path = cookie.path;
|
||||
if (cookie.name) jscookie.name = cookie.name;
|
||||
if (cookie.isSecure) jscookie.secure = true;
|
||||
if (cookie.isHttpOnly) jscookie.httponly = true;
|
||||
if (cookie.expiry < MAX_EXPIRY) jscookie.expiry = cookie.expiry;
|
||||
|
||||
addCookieToHash(jscookies, cookie.host, cookie.path, cookie.name, jscookie);
|
||||
}
|
||||
aWindow.cookies.push(jscookie);
|
||||
aWindow.cookies.push(jscookies[cookie.host][cookie.path][cookie.name]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
// don't include empty cookie sections
|
||||
for (i = 0; i < aWindows.length; i++)
|
||||
if (aWindows[i].cookies.length == 0)
|
||||
|
@ -64,6 +64,8 @@ _BROWSER_TEST_FILES = \
|
||||
browser_394759_privatebrowsing.js \
|
||||
browser_408470.js \
|
||||
browser_408470_sample.html \
|
||||
browser_423132.js \
|
||||
browser_423132_sample.html \
|
||||
browser_447951.js \
|
||||
browser_447951_sample.html \
|
||||
browser_448741.js \
|
||||
|
107
browser/components/sessionstore/test/browser/browser_423132.js
Normal file
@ -0,0 +1,107 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Daniel Witte <dwitte@mozilla.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
// test that cookies are stored and restored correctly by sessionstore,
|
||||
// bug 423132.
|
||||
|
||||
// test setup
|
||||
waitForExplicitFinish();
|
||||
|
||||
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
|
||||
cs.removeAll();
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
|
||||
// make sure that sessionstore.js can be forced to be created by setting
|
||||
// the interval pref to 0
|
||||
gPrefService.setIntPref("browser.sessionstore.interval", 0);
|
||||
|
||||
const testURL = "http://localhost:8888/browser/" +
|
||||
"browser/components/sessionstore/test/browser/browser_423132_sample.html";
|
||||
|
||||
// open a new window
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:blank");
|
||||
|
||||
// make sure sessionstore saves the cookie data, then close the window
|
||||
newWin.addEventListener("load", function (aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
newWin.gBrowser.selectedBrowser.loadURI(testURL, null, null);
|
||||
|
||||
newWin.gBrowser.addEventListener("load", function (aEvent) {
|
||||
newWin.gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
// get the sessionstore state for the window
|
||||
let state = ss.getWindowState(newWin);
|
||||
|
||||
// verify our cookie got set during pageload
|
||||
let e = cs.enumerator;
|
||||
let cookie;
|
||||
let i = 0;
|
||||
while (e.hasMoreElements()) {
|
||||
cookie = e.getNext().QueryInterface(Ci.nsICookie);
|
||||
i++;
|
||||
}
|
||||
is(i, 1, "expected one cookie");
|
||||
|
||||
// remove the cookie
|
||||
cs.removeAll();
|
||||
|
||||
// restore the window state
|
||||
ss.setWindowState(newWin, state, true);
|
||||
|
||||
// at this point, the cookie should be restored...
|
||||
e = cs.enumerator;
|
||||
let cookie2;
|
||||
while (e.hasMoreElements()) {
|
||||
cookie2 = e.getNext().QueryInterface(Ci.nsICookie);
|
||||
if (cookie.name == cookie2.name)
|
||||
break;
|
||||
}
|
||||
is(cookie.name, cookie2.name, "cookie name successfully restored");
|
||||
is(cookie.value, cookie2.value, "cookie value successfully restored");
|
||||
is(cookie.path, cookie2.path, "cookie path successfully restored");
|
||||
|
||||
// clean up
|
||||
gPrefService.clearUserPref("browser.sessionstore.interval");
|
||||
cs.removeAll();
|
||||
newWin.close();
|
||||
finish();
|
||||
}, true);
|
||||
}, false);
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
// generate an enormous random number...
|
||||
var r = Math.floor(Math.random() * Math.pow(2, 62)).toString();
|
||||
|
||||
// ... and use it to set a randomly named cookie
|
||||
document.cookie = r + "=value; path=/ohai";
|
||||
</script>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +1,4 @@
|
||||
#
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -85,7 +85,7 @@ nsSMILAnimationController::~nsSMILAnimationController()
|
||||
|
||||
nsSMILAnimationController* NS_NewSMILAnimationController(nsIDocument* aDoc)
|
||||
{
|
||||
nsSMILAnimationController* animationController =
|
||||
nsSMILAnimationController* animationController =
|
||||
new nsSMILAnimationController();
|
||||
NS_ENSURE_TRUE(animationController, nsnull);
|
||||
|
||||
@ -241,7 +241,7 @@ nsSMILAnimationController::StartTimer()
|
||||
// Run the first sample manually
|
||||
Sample();
|
||||
|
||||
//
|
||||
//
|
||||
// XXX Make this self-tuning. Sounds like control theory to me and not
|
||||
// something I'm familiar with.
|
||||
//
|
||||
@ -267,7 +267,7 @@ RemoveCompositorFromTable(nsSMILCompositor* aCompositor,
|
||||
void* aData)
|
||||
{
|
||||
nsSMILCompositorTable* lastCompositorTable =
|
||||
static_cast<nsSMILCompositorTable*>(aData);
|
||||
static_cast<nsSMILCompositorTable*>(aData);
|
||||
lastCompositorTable->RemoveEntry(aCompositor->GetKey());
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
@ -312,7 +312,7 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
|
||||
// STEP 2: (i) Sample the timed elements AND
|
||||
// (ii) Create a table of compositors
|
||||
//
|
||||
//
|
||||
// (i) Here we sample the timed elements (fetched from the
|
||||
// nsISMILAnimationElements) which determine from the active time if the
|
||||
// element is active and what its simple time etc. is. This information is
|
||||
@ -331,7 +331,7 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
// save iterating over the animation elements twice.
|
||||
|
||||
// Create the compositor table
|
||||
nsAutoPtr<nsSMILCompositorTable>
|
||||
nsAutoPtr<nsSMILCompositorTable>
|
||||
currentCompositorTable(new nsSMILCompositorTable());
|
||||
if (!currentCompositorTable)
|
||||
return;
|
||||
@ -371,12 +371,12 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
/*static*/ PR_CALLBACK PLDHashOperator
|
||||
nsSMILAnimationController::SampleTimeContainer(TimeContainerPtrKey* aKey,
|
||||
void* aData)
|
||||
{
|
||||
{
|
||||
NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
|
||||
NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
|
||||
NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);
|
||||
|
||||
SampleTimeContainerParams* params =
|
||||
SampleTimeContainerParams* params =
|
||||
static_cast<SampleTimeContainerParams*>(aData);
|
||||
|
||||
nsSMILTimeContainer* container = aKey->GetKey();
|
||||
@ -441,7 +441,7 @@ nsSMILAnimationController::AddAnimationToCompositorTable(
|
||||
return;
|
||||
|
||||
nsSMILCompositor* result = aCompositorTable->PutEntry(key);
|
||||
|
||||
|
||||
// Add this animationElement's animation function to the compositor's list of
|
||||
// animation functions.
|
||||
result->AddAnimationFunction(&aElement->AnimationFunction());
|
||||
@ -506,7 +506,7 @@ nsSMILAnimationController::AddChild(nsSMILTimeContainer& aChild)
|
||||
if (!mPauseState && mChildContainerTable.Count() == 1) {
|
||||
StartTimer();
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ class nsIDocument;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSMILAnimationController
|
||||
//
|
||||
//
|
||||
// The animation controller maintains the animation timer and determines the
|
||||
// sample times and sample rate for all SMIL animations in a document. There is
|
||||
// at most one animation controller per nsDocument so that frame-rate tuning can
|
||||
@ -74,7 +74,7 @@ public:
|
||||
virtual void Pause(PRUint32 aType);
|
||||
virtual void Resume(PRUint32 aType);
|
||||
virtual nsSMILTime GetParentTime() const;
|
||||
|
||||
|
||||
// Methods for registering and enumerating animation elements
|
||||
void RegisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
|
||||
void UnregisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
|
||||
@ -118,7 +118,7 @@ protected:
|
||||
TimeContainerHashtable* mActiveContainers;
|
||||
nsSMILCompositorTable* mCompositorTable;
|
||||
};
|
||||
|
||||
|
||||
// Factory methods
|
||||
friend nsSMILAnimationController*
|
||||
NS_NewSMILAnimationController(nsIDocument* aDoc);
|
||||
@ -159,14 +159,14 @@ protected:
|
||||
AnimationElementHashtable mAnimationElementTable;
|
||||
TimeContainerHashtable mChildContainerTable;
|
||||
PRPackedBool mResampleNeeded;
|
||||
|
||||
|
||||
// Store raw ptr to mDocument. It owns the controller, so controller
|
||||
// shouldn't outlive it
|
||||
nsIDocument* mDocument;
|
||||
|
||||
// Contains compositors used in our last sample. We keep this around
|
||||
// so we can detect when an element/attribute used to be animated,
|
||||
// but isn't anymore for some reason. (e.g. if its <animate> element is
|
||||
// but isn't anymore for some reason. (e.g. if its <animate> element is
|
||||
// removed or retargeted)
|
||||
nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
|
||||
};
|
||||
|
@ -188,8 +188,8 @@ nsSMILAnimationFunction::SampleAt(nsSMILTime aSampleTime,
|
||||
const nsSMILTimeValue& aSimpleDuration,
|
||||
PRUint32 aRepeatIteration)
|
||||
{
|
||||
if (mHasChanged || mLastValue || mSampleTime != aSampleTime ||
|
||||
mSimpleDuration.CompareTo(aSimpleDuration) ||
|
||||
if (mHasChanged || mLastValue || mSampleTime != aSampleTime ||
|
||||
mSimpleDuration.CompareTo(aSimpleDuration) ||
|
||||
mRepeatIteration != aRepeatIteration) {
|
||||
mHasChanged = PR_TRUE;
|
||||
}
|
||||
@ -250,12 +250,12 @@ nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr,
|
||||
// (Otherwise, we're probably just frozen.)
|
||||
if (mIsActive) {
|
||||
NS_ENSURE_TRUE(mSampleTime >= 0,);
|
||||
NS_ENSURE_TRUE(mSimpleDuration.IsResolved() ||
|
||||
NS_ENSURE_TRUE(mSimpleDuration.IsResolved() ||
|
||||
mSimpleDuration.IsIndefinite(),);
|
||||
}
|
||||
|
||||
nsSMILValue result(aResult.mType);
|
||||
|
||||
|
||||
if (mSimpleDuration.IsIndefinite() ||
|
||||
(HasAttr(nsGkAtoms::values) && values.Length() == 1)) {
|
||||
|
||||
@ -339,7 +339,7 @@ nsSMILAnimationFunction::WillReplace() const
|
||||
* here we return false for to animation as it builds on the underlying value
|
||||
* unless its a frozen to animation.
|
||||
*/
|
||||
return !(IsAdditive() || IsToAnimation()) ||
|
||||
return !(IsAdditive() || IsToAnimation()) ||
|
||||
(IsToAnimation() && mIsFrozen && !mHasChanged);
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if ((!IsToAnimation() && aValues.Length() < 2) ||
|
||||
if ((!IsToAnimation() && aValues.Length() < 2) ||
|
||||
(IsToAnimation() && aValues.Length() != 1)) {
|
||||
NS_ERROR("Unexpected number of values.");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -411,7 +411,7 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
|
||||
(PRUint32) floor(simpleProgress * (aValues.Length()));
|
||||
aResult = aValues[index];
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the normalised progress between adjacent values
|
||||
double intervalProgress;
|
||||
@ -423,7 +423,7 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
|
||||
intervalProgress = simpleProgress;
|
||||
ScaleIntervalProgress(intervalProgress, 0, 1);
|
||||
} else {
|
||||
if (GetCalcMode() == CALC_PACED) {
|
||||
if (GetCalcMode() == CALC_PACED) {
|
||||
rv = ComputePacedPosition(aValues, simpleProgress, intervalProgress,
|
||||
from, to);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
@ -588,7 +588,7 @@ nsSMILAnimationFunction::ScaleSimpleProgress(double& aProgress)
|
||||
return;
|
||||
}
|
||||
|
||||
aProgress = (i + (aProgress - intervalStart) / intervalLength) *
|
||||
aProgress = (i + (aProgress - intervalStart) / intervalLength) *
|
||||
1.0 / double(numTimes - 1);
|
||||
}
|
||||
|
||||
@ -607,7 +607,7 @@ nsSMILAnimationFunction::ScaleIntervalProgress(double& aProgress,
|
||||
if (!HasAttr(nsGkAtoms::keySplines))
|
||||
return;
|
||||
|
||||
NS_ASSERTION(aIntervalIndex >= 0 &&
|
||||
NS_ASSERTION(aIntervalIndex >= 0 &&
|
||||
aIntervalIndex < (PRUint32)mKeySplines.Length(),
|
||||
"Invalid interval index.");
|
||||
NS_ASSERTION(aNumIntervals >= 1, "Invalid number of intervals.");
|
||||
@ -656,7 +656,7 @@ nsSMILAnimationFunction::ParseAttr(nsIAtom* aAttName,
|
||||
{
|
||||
nsAutoString attValue;
|
||||
if (GetAttr(aAttName, attValue)) {
|
||||
nsresult rv =
|
||||
nsresult rv =
|
||||
aSMILAttr.ValueFromString(attValue, mAnimationElement, aResult);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
@ -740,14 +740,14 @@ nsSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
|
||||
CheckKeySplines(result.Length());
|
||||
|
||||
result.SwapElements(aResult);
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
nsSMILAnimationFunction::IsToAnimation() const
|
||||
{
|
||||
return !HasAttr(nsGkAtoms::values) &&
|
||||
return !HasAttr(nsGkAtoms::values) &&
|
||||
HasAttr(nsGkAtoms::to) &&
|
||||
!HasAttr(nsGkAtoms::from);
|
||||
}
|
||||
@ -894,7 +894,7 @@ nsSMILAnimationFunction::SetAccumulate(const nsAString& aAccumulate,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
mHasChanged = PR_TRUE;
|
||||
PRBool parseResult =
|
||||
PRBool parseResult =
|
||||
aResult.ParseEnumValue(aAccumulate, sAccumulateTable, PR_TRUE);
|
||||
SET_FLAG(mErrorFlags, BF_ACCUMULATE, !parseResult);
|
||||
return parseResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -912,7 +912,7 @@ nsSMILAnimationFunction::SetAdditive(const nsAString& aAdditive,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
mHasChanged = PR_TRUE;
|
||||
PRBool parseResult
|
||||
PRBool parseResult
|
||||
= aResult.ParseEnumValue(aAdditive, sAdditiveTable, PR_TRUE);
|
||||
SET_FLAG(mErrorFlags, BF_ADDITIVE, !parseResult);
|
||||
return parseResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -930,7 +930,7 @@ nsSMILAnimationFunction::SetCalcMode(const nsAString& aCalcMode,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
mHasChanged = PR_TRUE;
|
||||
PRBool parseResult
|
||||
PRBool parseResult
|
||||
= aResult.ParseEnumValue(aCalcMode, sCalcModeTable, PR_TRUE);
|
||||
SET_FLAG(mErrorFlags, BF_CALC_MODE, !parseResult);
|
||||
return parseResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
@ -174,7 +174,7 @@ public:
|
||||
* operations by only composing those animation that will affect the final
|
||||
* result.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if the animation is currently active. Inactive animations will
|
||||
* not contribute to the composed result.
|
||||
@ -183,7 +183,7 @@ public:
|
||||
*/
|
||||
PRBool IsActive() const
|
||||
{
|
||||
/*
|
||||
/*
|
||||
* - Frozen animations should be considered active for the purposes of
|
||||
* compositing.
|
||||
* - This function does not assume that our nsSMILValues (by/from/to/values)
|
||||
@ -323,7 +323,7 @@ protected:
|
||||
PRPackedBool mHasChanged;
|
||||
|
||||
nsSMILTime mBeginTime; // document time
|
||||
|
||||
|
||||
// The owning animation element. This is used for sorting based on document
|
||||
// position and for fetching attribute values stored in the element.
|
||||
// Raw pointer is OK here, because this nsSMILAnimationFunction can't outlive
|
||||
|
@ -136,7 +136,7 @@ nsSMILCompositor::ComposeAttribute()
|
||||
changed = PR_TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (curAnimFunc->WillReplace()) {
|
||||
--i;
|
||||
break;
|
||||
@ -165,7 +165,7 @@ nsSMILCompositor::ComposeAttribute()
|
||||
nsresult rv = smilAttr->SetAnimValue(resultValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsISMILAttr::SetAnimValue failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
|
||||
// Adds the given animation function to this Compositor's list of functions
|
||||
void AddAnimationFunction(nsSMILAnimationFunction* aFunc);
|
||||
|
||||
|
||||
// Composes the attribute's current value with the list of animation
|
||||
// functions, and assigns the resulting value to this compositor's target
|
||||
// attribute
|
||||
|
@ -88,7 +88,7 @@ nsSMILFloatType::ComputeDistance(const nsSMILValue& aFrom,
|
||||
{
|
||||
NS_PRECONDITION(aFrom.mType == aTo.mType,"Trying to compare different types");
|
||||
NS_PRECONDITION(aFrom.mType == this, "Unexpected source type");
|
||||
|
||||
|
||||
const double &from = aFrom.mU.mDouble;
|
||||
const double &to = aTo.mU.mDouble;
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
//
|
||||
// This class is essentially a structure consisting of a begin and end time. It
|
||||
// is used for representing the current interval and also for storing past
|
||||
// intervals for the purpose of hyperlinking back in time.
|
||||
// intervals for the purpose of hyperlinking back in time.
|
||||
//
|
||||
// For an overview of how this class is related to other SMIL time classes see
|
||||
// the documentstation in nsSMILTimeValue.h
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#define NEWTON_ITERATIONS 4
|
||||
|
||||
const double nsSMILKeySpline::kSampleStepSize =
|
||||
const double nsSMILKeySpline::kSampleStepSize =
|
||||
1.0 / double(kSplineTableSize - 1);
|
||||
|
||||
nsSMILKeySpline::nsSMILKeySpline(double aX1,
|
||||
@ -78,7 +78,8 @@ nsSMILKeySpline::CalcBezier(double aT,
|
||||
double aA1,
|
||||
double aA2)
|
||||
{
|
||||
return A(aA1, aA2) * pow(aT,3) + B(aA1, aA2)*aT*aT + C(aA1) * aT;
|
||||
// use Horner's scheme to evaluate the Bezier polynomial
|
||||
return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
|
||||
}
|
||||
|
||||
/*static*/ double
|
||||
@ -86,7 +87,7 @@ nsSMILKeySpline::GetSlope(double aT,
|
||||
double aA1,
|
||||
double aA2)
|
||||
{
|
||||
double denom = (3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1));
|
||||
double denom = (3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1));
|
||||
return (denom == 0.0) ? 0.0 : 1.0 / denom;
|
||||
}
|
||||
|
||||
@ -102,7 +103,7 @@ nsSMILKeySpline::GetTForX(double aX) const
|
||||
// to converge to a good accuracy. By taking an initial guess in this way we
|
||||
// only need 3~4 iterations depending on the size of the table.
|
||||
for (i = 0; i < kSplineTableSize - 2 && mSampleValues[i] < aX; ++i);
|
||||
double currentT =
|
||||
double currentT =
|
||||
double(i) * kSampleStepSize + (aX - mSampleValues[i]) * kSampleStepSize;
|
||||
|
||||
// Refine with Newton-Raphson iteration
|
||||
|
@ -80,7 +80,7 @@ private:
|
||||
{
|
||||
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
|
||||
}
|
||||
|
||||
|
||||
static double
|
||||
B(double aA1, double aA2)
|
||||
{
|
||||
|
@ -223,7 +223,7 @@ nsSMILParserUtils::ParseKeyTimes(const nsAString& aSpec,
|
||||
SkipWsp(start, end);
|
||||
if (start == end)
|
||||
break;
|
||||
|
||||
|
||||
if (*start++ != ';') {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
@ -238,7 +238,7 @@ nsSMILParserUtils::ParseKeyTimes(const nsAString& aSpec,
|
||||
nsresult
|
||||
nsSMILParserUtils::ParseValues(const nsAString& aSpec,
|
||||
const nsISMILAnimationElement* aSrcElement,
|
||||
const nsISMILAttr& aAttribute,
|
||||
const nsISMILAttr& aAttribute,
|
||||
nsTArray<nsSMILValue>& aValuesArray)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
@ -275,7 +275,7 @@ nsSMILParserUtils::ParseValues(const nsAString& aSpec,
|
||||
++substr_end;
|
||||
|
||||
nsSMILValue newValue;
|
||||
rv = aAttribute.ValueFromString(Substring(start, substr_end),
|
||||
rv = aAttribute.ValueFromString(Substring(start, substr_end),
|
||||
aSrcElement, newValue);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
@ -305,7 +305,7 @@ nsSMILParserUtils::ParseRepeatCount(const nsAString& aSpec,
|
||||
spec.EndReading(end);
|
||||
|
||||
SkipWsp(start, end);
|
||||
|
||||
|
||||
if (start != end)
|
||||
{
|
||||
if (ConsumeSubstring(start, end, "indefinite")) {
|
||||
@ -343,7 +343,7 @@ nsSMILParserUtils::ParseRepeatCount(const nsAString& aSpec,
|
||||
|
||||
nsresult
|
||||
nsSMILParserUtils::ParseClockValue(const nsAString& aSpec,
|
||||
nsSMILTimeValue* aResult,
|
||||
nsSMILTimeValue* aResult,
|
||||
PRUint32 aFlags, // = 0
|
||||
PRBool* aIsMedia) // = nsnull
|
||||
{
|
||||
@ -568,7 +568,7 @@ nsSMILParserUtils::ParseMetricMultiplicand(nsACString::const_iterator& aSpec,
|
||||
|
||||
size_t len = aEnd.get() - aSpec.get();
|
||||
nsACString::const_iterator spec(aSpec);
|
||||
|
||||
|
||||
if (len) {
|
||||
switch (*spec++)
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
* (according to aFlags), an error code otherwise.
|
||||
*/
|
||||
static nsresult ParseClockValue(const nsAString& aSpec,
|
||||
nsSMILTimeValue* aResult,
|
||||
nsSMILTimeValue* aResult,
|
||||
PRUint32 aFlags = 0,
|
||||
PRBool* aIsMedia = nsnull);
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSMILTimeContainer
|
||||
//
|
||||
//
|
||||
// Common base class for a time base that can be paused, resumed, and sampled.
|
||||
//
|
||||
class nsSMILTimeContainer
|
||||
|
@ -91,10 +91,10 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec)
|
||||
|
||||
if (NS_FAILED(rv) || (!clockTime.IsResolved() && !clockTime.IsIndefinite()))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
||||
if (clockTime.IsResolved())
|
||||
mOffset = clockTime.GetMillis();
|
||||
|
||||
|
||||
if (mOwner) {
|
||||
nsSMILInstanceTime instance(clockTime, this);
|
||||
mOwner->AddInstanceTime(instance, mIsBegin);
|
||||
|
@ -185,7 +185,7 @@ nsSMILTimedElement::GetStartTime() const
|
||||
if (!startTime.IsResolved()) {
|
||||
startTime.SetIndefinite();
|
||||
}
|
||||
|
||||
|
||||
return startTime;
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ nsSMILTimedElement::SampleAt(nsSMILTime aDocumentTime)
|
||||
nsSMILTimeValue beginAfter;
|
||||
beginAfter.SetMillis(LL_MININT);
|
||||
|
||||
mElementState =
|
||||
mElementState =
|
||||
(NS_SUCCEEDED(GetNextInterval(beginAfter, PR_TRUE, mCurrentInterval)))
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
@ -262,7 +262,7 @@ nsSMILTimedElement::SampleAt(nsSMILTime aDocumentTime)
|
||||
CheckForEarlyEnd(docTime);
|
||||
if (mCurrentInterval.mEnd.CompareTo(docTime) <= 0) {
|
||||
nsSMILInterval newInterval;
|
||||
mElementState =
|
||||
mElementState =
|
||||
(NS_SUCCEEDED(GetNextInterval(mCurrentInterval.mEnd,
|
||||
PR_FALSE,
|
||||
newInterval)))
|
||||
@ -442,7 +442,7 @@ nsSMILTimedElement::SetSimpleDuration(const nsAString& aDurSpec)
|
||||
nsSMILTimeValue duration;
|
||||
PRBool isMedia;
|
||||
nsresult rv;
|
||||
|
||||
|
||||
rv = nsSMILParserUtils::ParseClockValue(aDurSpec, &duration,
|
||||
nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
|
||||
|
||||
@ -450,7 +450,7 @@ nsSMILTimedElement::SetSimpleDuration(const nsAString& aDurSpec)
|
||||
mSimpleDur.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (duration.IsResolved() && duration.GetMillis() == 0L) {
|
||||
mSimpleDur.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -487,7 +487,7 @@ nsSMILTimedElement::SetMin(const nsAString& aMinSpec)
|
||||
nsSMILTimeValue duration;
|
||||
PRBool isMedia;
|
||||
nsresult rv;
|
||||
|
||||
|
||||
rv = nsSMILParserUtils::ParseClockValue(aMinSpec, &duration, 0, &isMedia);
|
||||
|
||||
if (isMedia) {
|
||||
@ -498,7 +498,7 @@ nsSMILTimedElement::SetMin(const nsAString& aMinSpec)
|
||||
mMin.SetMillis(0L);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (duration.GetMillis() < 0L) {
|
||||
mMin.SetMillis(0L);
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -523,7 +523,7 @@ nsSMILTimedElement::SetMax(const nsAString& aMaxSpec)
|
||||
nsSMILTimeValue duration;
|
||||
PRBool isMedia;
|
||||
nsresult rv;
|
||||
|
||||
|
||||
rv = nsSMILParserUtils::ParseClockValue(aMaxSpec, &duration,
|
||||
nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
|
||||
|
||||
@ -534,7 +534,7 @@ nsSMILTimedElement::SetMax(const nsAString& aMaxSpec)
|
||||
mMax.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (duration.IsResolved() && duration.GetMillis() <= 0L) {
|
||||
mMax.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -557,7 +557,7 @@ nsresult
|
||||
nsSMILTimedElement::SetRestart(const nsAString& aRestartSpec)
|
||||
{
|
||||
nsAttrValue temp;
|
||||
PRBool parseResult
|
||||
PRBool parseResult
|
||||
= temp.ParseEnumValue(aRestartSpec, sRestartModeTable, PR_TRUE);
|
||||
mRestartMode = parseResult
|
||||
? nsSMILRestartMode(temp.GetEnumValue())
|
||||
@ -577,7 +577,7 @@ nsresult
|
||||
nsSMILTimedElement::SetRepeatCount(const nsAString& aRepeatCountSpec)
|
||||
{
|
||||
nsSMILRepeatCount newRepeatCount;
|
||||
nsresult rv =
|
||||
nsresult rv =
|
||||
nsSMILParserUtils::ParseRepeatCount(aRepeatCountSpec, newRepeatCount);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -587,7 +587,7 @@ nsSMILTimedElement::SetRepeatCount(const nsAString& aRepeatCountSpec)
|
||||
}
|
||||
|
||||
UpdateCurrentInterval();
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ nsSMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec)
|
||||
mRepeatDur.SetUnresolved();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
mRepeatDur = duration;
|
||||
UpdateCurrentInterval();
|
||||
|
||||
@ -631,7 +631,7 @@ nsSMILTimedElement::SetFillMode(const nsAString& aFillModeSpec)
|
||||
PRUint16 previousFillMode = mFillMode;
|
||||
|
||||
nsAttrValue temp;
|
||||
PRBool parseResult =
|
||||
PRBool parseResult =
|
||||
temp.ParseEnumValue(aFillModeSpec, sFillModeTable, PR_TRUE);
|
||||
mFillMode = parseResult
|
||||
? nsSMILFillMode(temp.GetEnumValue())
|
||||
@ -665,7 +665,7 @@ nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
|
||||
{
|
||||
nsRefPtr<nsSMILTimeValueSpec> spec;
|
||||
SMILTimeValueSpecList& timeSpecsList = aIsBegin ? mBeginSpecs : mEndSpecs;
|
||||
nsTArray<nsSMILInstanceTime>& instancesList
|
||||
nsTArray<nsSMILInstanceTime>& instancesList
|
||||
= aIsBegin ? mBeginInstances : mEndInstances;
|
||||
|
||||
timeSpecsList.Clear();
|
||||
@ -712,7 +712,7 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
{
|
||||
static nsSMILTimeValue zeroTime;
|
||||
zeroTime.SetMillis(0L);
|
||||
|
||||
|
||||
nsSMILTimeValue beginAfter = aBeginAfter;
|
||||
nsSMILTimeValue tempBegin;
|
||||
nsSMILTimeValue tempEnd;
|
||||
@ -751,7 +751,7 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
|
||||
tempEnd = CalcActiveEnd(tempBegin, indefiniteEnd);
|
||||
} else {
|
||||
//
|
||||
//
|
||||
// Start searching from the beginning again.
|
||||
//
|
||||
endPos = 0;
|
||||
@ -760,9 +760,9 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
endPos, tempEnd);
|
||||
|
||||
if ((!aFirstInterval && tempEnd.CompareTo(aBeginAfter) == 0) ||
|
||||
(aFirstInterval && tempEnd.CompareTo(tempBegin) == 0 &&
|
||||
(aFirstInterval && tempEnd.CompareTo(tempBegin) == 0 &&
|
||||
endPos <= endMaxPos)) {
|
||||
endFound =
|
||||
endFound =
|
||||
GetNextGreaterOrEqual(mEndInstances, tempBegin, endPos, tempEnd);
|
||||
}
|
||||
|
||||
@ -772,12 +772,12 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
if (mEndHasEventConditions || mEndInstances.Length() == 0) {
|
||||
tempEnd.SetUnresolved();
|
||||
} else {
|
||||
//
|
||||
//
|
||||
// This is a little counter-intuitive but according to SMILANIM, if
|
||||
// all the ends are before the begin, we _don't_ just assume an
|
||||
// infinite end, it's actually a bad interval. ASV however will just
|
||||
// use an infinite end.
|
||||
//
|
||||
//
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -928,7 +928,7 @@ nsSMILTimedElement::ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
|
||||
if (mSimpleDur.IsIndefinite() || mSimpleDur.GetMillis() == 0L) {
|
||||
aRepeatIteration = 0;
|
||||
result = aActiveTime;
|
||||
} else {
|
||||
} else {
|
||||
result = aActiveTime % mSimpleDur.GetMillis();
|
||||
aRepeatIteration = (PRUint32)(aActiveTime / mSimpleDur.GetMillis());
|
||||
}
|
||||
@ -960,8 +960,8 @@ nsSMILTimedElement::CheckForEarlyEnd(const nsSMILTimeValue& aDocumentTime)
|
||||
while (GetNextGreaterOrEqual(mBeginInstances, mCurrentInterval.mBegin,
|
||||
position, nextBegin)
|
||||
&& nextBegin.CompareTo(mCurrentInterval.mBegin) == 0);
|
||||
|
||||
if (nextBegin.IsResolved() &&
|
||||
|
||||
if (nextBegin.IsResolved() &&
|
||||
nextBegin.CompareTo(mCurrentInterval.mBegin) > 0 &&
|
||||
nextBegin.CompareTo(mCurrentInterval.mEnd) < 0 &&
|
||||
nextBegin.CompareTo(aDocumentTime) <= 0) {
|
||||
@ -1027,7 +1027,7 @@ nsSMILTimedElement::SampleSimpleTime(nsSMILTime aActiveTime)
|
||||
{
|
||||
if (mClient) {
|
||||
PRUint32 repeatIteration;
|
||||
nsSMILTime simpleTime =
|
||||
nsSMILTime simpleTime =
|
||||
ActiveTimeToSimpleTime(aActiveTime, repeatIteration);
|
||||
mClient->SampleAt(simpleTime, mSimpleDur, repeatIteration);
|
||||
}
|
||||
@ -1043,10 +1043,10 @@ nsSMILTimedElement::SampleFillValue()
|
||||
return;
|
||||
|
||||
PRUint32 repeatIteration;
|
||||
nsSMILTime activeTime =
|
||||
nsSMILTime activeTime =
|
||||
mCurrentInterval.mEnd.GetMillis() - mCurrentInterval.mBegin.GetMillis();
|
||||
|
||||
nsSMILTime simpleTime =
|
||||
nsSMILTime simpleTime =
|
||||
ActiveTimeToSimpleTime(activeTime, repeatIteration);
|
||||
|
||||
if (simpleTime == 0L) {
|
||||
|
@ -60,7 +60,7 @@ class nsSMILTimedElement
|
||||
public:
|
||||
nsSMILTimedElement();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Methods for supporting the nsIDOMElementTimeControl interface.
|
||||
*/
|
||||
|
||||
@ -92,7 +92,7 @@ public:
|
||||
nsresult EndElementAt(double aOffsetSeconds,
|
||||
const nsSMILTimeContainer* aContainer);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Methods for supporting the nsSVGAnimationElement interface.
|
||||
*/
|
||||
|
||||
@ -130,7 +130,7 @@ public:
|
||||
return mSimpleDur;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Internal SMIL methods
|
||||
*/
|
||||
|
||||
|
@ -49,16 +49,29 @@
|
||||
NS_IMPL_ADDREF_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
|
||||
NS_IMPL_RELEASE_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSVGAnimationElement)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAnimationElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimationElementBase)
|
||||
|
||||
// Cycle collection magic -- based on nsSVGUseElement
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGAnimationElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGAnimationElement,
|
||||
nsSVGAnimationElementBase)
|
||||
tmp->mHrefTarget.Unlink();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGAnimationElement,
|
||||
nsSVGAnimationElementBase)
|
||||
tmp->mHrefTarget.Traverse(&cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
nsSVGAnimationElement::nsSVGAnimationElement(nsINodeInfo *aNodeInfo)
|
||||
: nsSVGAnimationElementBase(aNodeInfo),
|
||||
mHrefTarget(this),
|
||||
mTimedDocumentRoot(nsnull)
|
||||
{
|
||||
}
|
||||
@ -100,17 +113,13 @@ nsIContent*
|
||||
nsSVGAnimationElement::GetTargetElementContent()
|
||||
{
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
// XXXdholbert: Use xlink:href attr to look up target element here.
|
||||
|
||||
// Note: Need to check for updated target element each sample, because
|
||||
// the existing target's ID might've changed, or another element
|
||||
// with the same ID might've been inserted earlier in the DOM tree.
|
||||
NS_NOTYETIMPLEMENTED("nsSVGAnimationElement::GetTargetElementContent for "
|
||||
"xlink:href-targeted animations");
|
||||
return nsnull;
|
||||
return mHrefTarget.get();
|
||||
}
|
||||
NS_ABORT_IF_FALSE(!mHrefTarget.get(),
|
||||
"We shouldn't have an xlink:href target "
|
||||
"if we don't have an xlink:href attribute");
|
||||
|
||||
// No "xlink:href" attribute --> target is my parent.
|
||||
// No "xlink:href" attribute --> I should target my parent.
|
||||
return nsSVGUtils::GetParentElement(this);
|
||||
}
|
||||
|
||||
@ -223,6 +232,9 @@ nsSVGAnimationElement::BindToTree(nsIDocument* aDocument,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mHrefTarget.get(),
|
||||
"Shouldn't have href-target yet "
|
||||
"(or it should've been cleared)");
|
||||
nsresult rv = nsSVGAnimationElementBase::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
@ -252,6 +264,17 @@ nsSVGAnimationElement::BindToTree(nsIDocument* aDocument,
|
||||
if (controller) {
|
||||
controller->RegisterAnimationElement(this);
|
||||
}
|
||||
const nsAttrValue* href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
|
||||
kNameSpaceID_XLink);
|
||||
if (href) {
|
||||
nsAutoString hrefStr;
|
||||
href->ToString(hrefStr);
|
||||
|
||||
// Pass in |aParent| instead of |this| -- first argument is only used
|
||||
// for a call to GetCurrentDoc(), and |this| might not have a current
|
||||
// document yet.
|
||||
UpdateHrefTarget(aParent, hrefStr);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNeedsResample();
|
||||
@ -274,6 +297,8 @@ nsSVGAnimationElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
mTimedDocumentRoot = nsnull;
|
||||
}
|
||||
|
||||
mHrefTarget.Unlink();
|
||||
|
||||
AnimationNeedsResample();
|
||||
|
||||
nsSVGAnimationElementBase::UnbindFromTree(aDeep, aNullParent);
|
||||
@ -300,7 +325,7 @@ nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// First let the animation function try to parse it...
|
||||
PRBool foundMatch =
|
||||
PRBool foundMatch =
|
||||
AnimationFunction().SetAttr(aAttribute, aValue, aResult, &rv);
|
||||
|
||||
// ... and if that didn't recognize the attribute, let the timed element
|
||||
@ -308,7 +333,7 @@ nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
if (!foundMatch) {
|
||||
foundMatch = mTimedElement.SetAttr(aAttribute, aValue, aResult, &rv);
|
||||
}
|
||||
|
||||
|
||||
if (foundMatch) {
|
||||
AnimationNeedsResample();
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -319,8 +344,17 @@ nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
}
|
||||
}
|
||||
|
||||
return nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
||||
aValue, aResult);
|
||||
PRBool returnVal =
|
||||
nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
||||
aValue, aResult);
|
||||
if (aNamespaceID == kNameSpaceID_XLink &&
|
||||
aAttribute == nsGkAtoms::href &&
|
||||
IsInDoc()) {
|
||||
// NOTE: If we fail the IsInDoc call, it's ok -- we'll update the target
|
||||
// on next BindToTree call.
|
||||
UpdateHrefTarget(this, aValue);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -336,6 +370,10 @@ nsSVGAnimationElement::UnsetAttr(PRInt32 aNamespaceID,
|
||||
mTimedElement.UnsetAttr(aAttribute)) {
|
||||
AnimationNeedsResample();
|
||||
}
|
||||
} else if (aNamespaceID == kNameSpaceID_XLink) {
|
||||
if (aAttribute == nsGkAtoms::href) {
|
||||
mHrefTarget.Unlink();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -395,3 +433,14 @@ nsSVGAnimationElement::EndElementAt(float offset)
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr)
|
||||
{
|
||||
nsCOMPtr<nsIURI> targetURI;
|
||||
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
|
||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
|
||||
aHrefStr, GetOwnerDoc(), baseURI);
|
||||
mHrefTarget.Reset(aNodeForContext, targetURI);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsReferencedElement.h"
|
||||
#include "nsIDOMSVGAnimationElement.h"
|
||||
#include "nsIDOMElementTimeControl.h"
|
||||
#include "nsISMILAnimationElement.h"
|
||||
@ -59,8 +60,11 @@ protected:
|
||||
nsresult Init();
|
||||
|
||||
public:
|
||||
// interfaces:
|
||||
// interfaces:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSVGAnimationElement,
|
||||
nsSVGAnimationElementBase)
|
||||
NS_DECL_NSIDOMSVGANIMATIONELEMENT
|
||||
NS_DECL_NSIDOMELEMENTTIMECONTROL
|
||||
|
||||
@ -91,6 +95,30 @@ public:
|
||||
virtual nsSMILTimeContainer* GetTimeContainer();
|
||||
|
||||
protected:
|
||||
void UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr);
|
||||
|
||||
class TargetReference : public nsReferencedElement {
|
||||
public:
|
||||
TargetReference(nsSVGAnimationElement* aAnimationElement) :
|
||||
mAnimationElement(aAnimationElement) {}
|
||||
protected:
|
||||
// We need to be notified when target changes, in order to request a
|
||||
// sample (which will clear animation effects from old target and apply
|
||||
// them to the new target).
|
||||
virtual void ContentChanged(nsIContent* aFrom, nsIContent* aTo) {
|
||||
nsReferencedElement::ContentChanged(aFrom, aTo);
|
||||
mAnimationElement->AnimationNeedsResample();
|
||||
}
|
||||
|
||||
// We need to override IsPersistent to get persistent tracking (beyond the
|
||||
// first time the target changes)
|
||||
virtual PRBool IsPersistent() { return PR_TRUE; }
|
||||
private:
|
||||
nsSVGAnimationElement* const mAnimationElement;
|
||||
};
|
||||
|
||||
TargetReference mHrefTarget;
|
||||
nsSMILTimedElement mTimedElement;
|
||||
nsSMILTimeContainer* mTimedDocumentRoot;
|
||||
};
|
||||
|
@ -101,9 +101,9 @@ public:
|
||||
mParams[i] = aParams[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TransformType mTransformType;
|
||||
|
||||
|
||||
float mParams[6];
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ nsSVGTransformSMILAttr::GetBaseValue() const
|
||||
nsSMILValue val(type);
|
||||
if (val.IsNull())
|
||||
return val;
|
||||
|
||||
|
||||
nsIDOMSVGTransformList *list = mVal->mBaseVal.get();
|
||||
|
||||
PRUint32 numItems = 0;
|
||||
@ -104,7 +104,7 @@ nsSVGTransformSMILAttr::GetBaseValue() const
|
||||
NS_ENSURE_SUCCESS(rv,nsSMILValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
|
||||
float params[3] = { 0.f };
|
||||
PRInt32 numParsed = ParseParameterList(aSpec, params, 3);
|
||||
nsSVGSMILTransform::TransformType transformType;
|
||||
|
||||
|
||||
if (aTransformType == nsGkAtoms::translate) {
|
||||
// tx [ty=0]
|
||||
if (numParsed != 1 && numParsed != 2)
|
||||
@ -343,7 +343,7 @@ nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue(
|
||||
}
|
||||
|
||||
if (transformType != nsSVGSMILTransform::TRANSFORM_MATRIX) {
|
||||
rv =
|
||||
rv =
|
||||
type->AppendTransform(nsSVGSMILTransform(transformType, params), aValue);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ nsSVGTransformSMILType::Init(nsSMILValue &aValue) const
|
||||
"Invalid nsSMILValue of SVG transform type: NULL data member.");
|
||||
|
||||
if (aValue.mType != this || !aValue.mU.mPtr) {
|
||||
// Different type, or no data member: allocate memory and set type
|
||||
// Different type, or no data member: allocate memory and set type
|
||||
TransformArray* transforms = new TransformArray(1);
|
||||
NS_ENSURE_TRUE(transforms, NS_ERROR_OUT_OF_MEMORY);
|
||||
aValue.mU.mPtr = transforms;
|
||||
@ -85,7 +85,7 @@ nsSVGTransformSMILType::Assign(nsSMILValue& aDest,
|
||||
NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
|
||||
NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value.");
|
||||
|
||||
const TransformArray* srcTransforms =
|
||||
const TransformArray* srcTransforms =
|
||||
static_cast<const TransformArray*>(aSrc.mU.mPtr);
|
||||
TransformArray* dstTransforms = static_cast<TransformArray*>(aDest.mU.mPtr);
|
||||
|
||||
@ -181,13 +181,13 @@ nsSVGTransformSMILType::ComputeDistance(const nsSMILValue& aFrom,
|
||||
const nsSMILValue& aTo,
|
||||
double& aDistance) const
|
||||
{
|
||||
NS_PRECONDITION(aFrom.mType == aTo.mType,
|
||||
NS_PRECONDITION(aFrom.mType == aTo.mType,
|
||||
"Can't compute difference between different SMIL types.");
|
||||
NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type.");
|
||||
|
||||
const TransformArray* fromTransforms =
|
||||
const TransformArray* fromTransforms =
|
||||
static_cast<const TransformArray*>(aFrom.mU.mPtr);
|
||||
const TransformArray* toTransforms =
|
||||
const TransformArray* toTransforms =
|
||||
static_cast<const TransformArray*>(aTo.mU.mPtr);
|
||||
|
||||
// ComputeDistance is only used for calculating distances between single
|
||||
@ -252,9 +252,9 @@ nsSVGTransformSMILType::Interpolate(const nsSMILValue& aStartVal,
|
||||
"Unexpected type for interpolation.");
|
||||
NS_PRECONDITION(aResult.mType == this, "Unexpected result type.");
|
||||
|
||||
const TransformArray& startTransforms =
|
||||
const TransformArray& startTransforms =
|
||||
(*static_cast<const TransformArray*>(aStartVal.mU.mPtr));
|
||||
const TransformArray& endTransforms
|
||||
const TransformArray& endTransforms
|
||||
(*static_cast<const TransformArray*>(aEndVal.mU.mPtr));
|
||||
|
||||
// We may have 0..n transforms in the start transform array (the base
|
||||
@ -284,7 +284,7 @@ nsSVGTransformSMILType::Interpolate(const nsSMILValue& aStartVal,
|
||||
if (!startParams) {
|
||||
startParams = identityParams;
|
||||
}
|
||||
|
||||
|
||||
const float* endParams = endTransform.mParams;
|
||||
|
||||
// Interpolate between the params
|
||||
@ -299,7 +299,7 @@ nsSVGTransformSMILType::Interpolate(const nsSMILValue& aStartVal,
|
||||
nsSVGSMILTransform resultTransform(endTransform.mTransformType, newParams);
|
||||
|
||||
// Clear the way for it in the result array
|
||||
TransformArray& dstTransforms =
|
||||
TransformArray& dstTransforms =
|
||||
(*static_cast<TransformArray*>(aResult.mU.mPtr));
|
||||
dstTransforms.Clear();
|
||||
|
||||
@ -318,9 +318,9 @@ nsSVGTransformSMILType::GetNumTransforms(const nsSMILValue& aValue) const
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
|
||||
|
||||
const TransformArray& transforms =
|
||||
const TransformArray& transforms =
|
||||
*static_cast<const TransformArray*>(aValue.mU.mPtr);
|
||||
|
||||
|
||||
return transforms.Length();
|
||||
}
|
||||
|
||||
@ -330,14 +330,14 @@ nsSVGTransformSMILType::GetTransformAt(PRUint32 aIndex,
|
||||
{
|
||||
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
|
||||
|
||||
const TransformArray& transforms =
|
||||
const TransformArray& transforms =
|
||||
*static_cast<const TransformArray*>(aValue.mU.mPtr);
|
||||
|
||||
if (aIndex >= transforms.Length()) {
|
||||
NS_ERROR("Attempting to access invalid transform.");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
return &transforms[aIndex];
|
||||
}
|
||||
|
||||
|
@ -686,7 +686,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLBaseFontElement, nsHTMLElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLBodyElement, nsHTMLElementSH,
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLBodyElement, nsHTMLBodyElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(HTMLButtonElement, nsHTMLElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
@ -5203,6 +5203,74 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLBodyElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext
|
||||
*cx, JSObject *obj, jsval id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
if (id == sOnhashchange_id) {
|
||||
// Special handling so |"onhashchange" in document.body| returns true.
|
||||
jsid interned_id;
|
||||
|
||||
if (!JS_ValueToId(cx, id, &interned_id) ||
|
||||
!JS_DefinePropertyById(cx, obj, interned_id, JSVAL_VOID,
|
||||
nsnull, nsnull, JSPROP_ENUMERATE)) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*objp = obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsHTMLElementSH::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLBodyElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj, jsval id,
|
||||
jsval *vp, PRBool *_retval)
|
||||
{
|
||||
if (id == sOnhashchange_id) {
|
||||
// Forward the request to the Window.
|
||||
jsid interned_id;
|
||||
|
||||
if (!JS_ValueToId(cx, id, &interned_id) ||
|
||||
!JS_GetPropertyById(cx, JS_GetGlobalForObject(cx, obj),
|
||||
interned_id, vp)) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsHTMLElementSH::GetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLBodyElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext *cx, JSObject *obj,
|
||||
jsval id, jsval *vp, PRBool *_retval)
|
||||
{
|
||||
if (id == sOnhashchange_id) {
|
||||
// Forward the request to the Window.
|
||||
jsid interned_id;
|
||||
|
||||
if (!JS_ValueToId(cx, id, &interned_id) ||
|
||||
!JS_SetPropertyById(cx, JS_GetGlobalForObject(cx, obj),
|
||||
interned_id, vp)) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsHTMLElementSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
|
||||
}
|
||||
|
||||
class nsDOMConstructor : public nsIDOMDOMConstructor
|
||||
{
|
||||
protected:
|
||||
@ -6383,6 +6451,21 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (id == sOnhashchange_id) {
|
||||
// Special handling so |"onhashchange" in window| returns true
|
||||
jsid interned_id;
|
||||
|
||||
if (!JS_ValueToId(cx, id, &interned_id) ||
|
||||
!JS_DefinePropertyById(cx, obj, interned_id, JSVAL_VOID,
|
||||
nsnull, nsnull, JSPROP_ENUMERATE)) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*objp = obj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (flags & JSRESOLVE_ASSIGNING) {
|
||||
if (IsReadonlyReplaceable(id) ||
|
||||
(!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) {
|
||||
|
@ -999,6 +999,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class nsHTMLBodyElementSH : public nsHTMLElementSH
|
||||
{
|
||||
protected:
|
||||
nsHTMLBodyElementSH(nsDOMClassInfoData* aData) : nsHTMLElementSH(aData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~nsHTMLBodyElementSH()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, jsval *vp,
|
||||
PRBool *_retval);
|
||||
|
||||
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsHTMLBodyElementSH(aData);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// HTMLFormElement helper
|
||||
|
||||
|
@ -51,6 +51,7 @@ _TEST_FILES = test_offsets.html \
|
||||
test_domWindowUtils_scrollXY.html \
|
||||
test_497898.html \
|
||||
497633.html \
|
||||
test_bug504220.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
67
dom/tests/mochitest/general/test_bug504220.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=504220
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 504220</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload="run_test();">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504220">Mozilla Bug 504220</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
|
||||
<div id="status" style="display: none"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 504220 **/
|
||||
|
||||
function run_test() {
|
||||
ok("onhashchange" in document.body,
|
||||
"document.body should contain 'onhashchange'.");
|
||||
|
||||
ok("onhashchange" in window, "window should contain 'onhashchange'.");
|
||||
|
||||
// window.onhashchange should mirror document.body.onhashchange.
|
||||
var func = function() { return 42; };
|
||||
document.body.onhashchange = func;
|
||||
is(window.onhashchange, func);
|
||||
|
||||
// Likewise, document.body.hashchange should mirror window.onhashchange
|
||||
numEvents = 0;
|
||||
var func2 = function() { numEvents++; gGen.next() };
|
||||
window.onhashchange = func2;
|
||||
is(document.body.onhashchange, func2);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function waitForHashchange() {
|
||||
// Change the document's hash. If we've been running this test manually,
|
||||
// the hash might already be "#foo", so we need to check in order to be
|
||||
// sure we trigger a hashchange.
|
||||
if (location.hash != "#foo")
|
||||
location.hash = "#foo";
|
||||
else
|
||||
location.hash = "#bar";
|
||||
|
||||
yield;
|
||||
|
||||
is(numEvents, 1, "Exactly one hashchange should have been fired.");
|
||||
SimpleTest.finish();
|
||||
yield;
|
||||
}
|
||||
|
||||
var gGen = waitForHashchange();
|
||||
gGen.next();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -109,7 +109,7 @@ public:
|
||||
// clean up static objects that may have been cached
|
||||
static void Shutdown();
|
||||
|
||||
static CTFontRef CreateCopyWithDisabledLigatures(CTFontRef aFont);
|
||||
static CTFontRef CreateCTFontWithDisabledLigatures(ATSFontRef aFont, CGFloat aSize);
|
||||
|
||||
protected:
|
||||
const gfxFontStyle *mFontStyle;
|
||||
|
@ -77,6 +77,26 @@ static PRLogModuleInfo *gCoreTextTextRunLog = PR_NewLogModule("coreTextTextRun")
|
||||
CTFontDescriptorRef gfxCoreTextFont::sDefaultFeaturesDescriptor = NULL;
|
||||
CTFontDescriptorRef gfxCoreTextFont::sDisableLigaturesDescriptor = NULL;
|
||||
|
||||
#ifdef DEBUG_jonathan
|
||||
static void dumpFontDescCallback(const void *key, const void *value, void *context)
|
||||
{
|
||||
CFStringRef attribute = (CFStringRef)key;
|
||||
CFTypeRef setting = (CFTypeRef)value;
|
||||
fprintf(stderr, "attr: "); CFShow(attribute);
|
||||
fprintf(stderr, " = "); CFShow(setting);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpFontDescriptor(CTFontRef font)
|
||||
{
|
||||
CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);
|
||||
CFDictionaryRef dict = CTFontDescriptorCopyAttributes(desc);
|
||||
CFRelease(desc);
|
||||
CFDictionaryApplyFunction(dict, &dumpFontDescCallback, 0);
|
||||
CFRelease(dict);
|
||||
}
|
||||
#endif
|
||||
|
||||
gfxCoreTextFont::gfxCoreTextFont(MacOSFontEntry *aFontEntry,
|
||||
const gfxFontStyle *aFontStyle,
|
||||
@ -451,9 +471,9 @@ gfxCoreTextFont::CreateDefaultFeaturesDescriptor()
|
||||
CFRelease(attributesDict);
|
||||
}
|
||||
|
||||
// Create a copy of a CTFontRef, with the Common Ligatures feature disabled [static]
|
||||
// Create a CTFontRef for an ATS font ref, with the Common Ligatures feature disabled [static]
|
||||
CTFontRef
|
||||
gfxCoreTextFont::CreateCopyWithDisabledLigatures(CTFontRef aFontRef)
|
||||
gfxCoreTextFont::CreateCTFontWithDisabledLigatures(ATSFontRef aFontRef, CGFloat aSize)
|
||||
{
|
||||
if (sDisableLigaturesDescriptor == NULL) {
|
||||
// initialize cached descriptor to turn off the Common Ligatures feature
|
||||
@ -499,16 +519,11 @@ gfxCoreTextFont::CreateCopyWithDisabledLigatures(CTFontRef aFontRef)
|
||||
CFRelease(featuresArray);
|
||||
|
||||
sDisableLigaturesDescriptor =
|
||||
CTFontDescriptorCreateWithAttributes(attributesDict);
|
||||
CTFontDescriptorCreateCopyWithAttributes(GetDefaultFeaturesDescriptor(), attributesDict);
|
||||
CFRelease(attributesDict);
|
||||
}
|
||||
|
||||
aFontRef =
|
||||
CTFontCreateCopyWithAttributes(aFontRef,
|
||||
0.0,
|
||||
NULL,
|
||||
sDisableLigaturesDescriptor);
|
||||
return aFontRef;
|
||||
|
||||
return CTFontCreateWithPlatformFont(aFontRef, aSize, NULL, sDisableLigaturesDescriptor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -759,19 +774,20 @@ gfxCoreTextFontGroup::InitTextRun(gfxTextRun *aTextRun,
|
||||
if (disableLigatures) {
|
||||
// For letterspacing (or maybe other situations) we need to make a copy of the CTFont
|
||||
// with the ligature feature disabled
|
||||
CTFontRef mainCTFont = mainFont->GetCTFont();
|
||||
mainCTFont = gfxCoreTextFont::CreateCopyWithDisabledLigatures(mainCTFont);
|
||||
CTFontRef ctFont =
|
||||
gfxCoreTextFont::CreateCTFontWithDisabledLigatures(mainFont->GetATSFont(),
|
||||
CTFontGetSize(mainFont->GetCTFont()));
|
||||
|
||||
// Set up the initial font, for the (common) case of a monostyled textRun
|
||||
attrObj =
|
||||
CFDictionaryCreate(kCFAllocatorDefault,
|
||||
(const void**) &kCTFontAttributeName,
|
||||
(const void**) &mainCTFont,
|
||||
(const void**) &ctFont,
|
||||
1, // count of attributes
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
// Having created the dict, we're finished with our modified copy of the CTFont
|
||||
CFRelease(mainCTFont);
|
||||
// Having created the dict, we're finished with our ligature-disabled CTFontRef
|
||||
CFRelease(ctFont);
|
||||
} else {
|
||||
attrObj = mainFont->GetAttributesDictionary();
|
||||
CFRetain(attrObj);
|
||||
@ -813,7 +829,8 @@ gfxCoreTextFontGroup::InitTextRun(gfxTextRun *aTextRun,
|
||||
if (matchedFont != mainFont) {
|
||||
CTFontRef matchedCTFont = matchedFont->GetCTFont();
|
||||
if (disableLigatures)
|
||||
matchedCTFont = gfxCoreTextFont::CreateCopyWithDisabledLigatures(matchedCTFont);
|
||||
matchedCTFont = gfxCoreTextFont::CreateCTFontWithDisabledLigatures(matchedFont->GetATSFont(),
|
||||
CTFontGetSize(matchedCTFont));
|
||||
// if necessary, make a mutable copy of the string
|
||||
if (!mutableStringObj) {
|
||||
mutableStringObj =
|
||||
|
@ -163,7 +163,7 @@ public:
|
||||
void clear();
|
||||
};
|
||||
|
||||
#ifdef JS_JIT_SPEW
|
||||
#if defined(JS_JIT_SPEW) || defined(MOZ_NO_VARADIC_MACROS)
|
||||
|
||||
enum LC_TMBits {
|
||||
/* Output control bits for all non-Nanojit code. Only use bits 16
|
||||
@ -177,6 +177,16 @@ enum LC_TMBits {
|
||||
LC_TMRegexp = 1<<22
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_NO_VARADIC_MACROS
|
||||
|
||||
#define debug_only_stmt(action) /* */
|
||||
static void debug_only_printf(int mask, const char *fmt, ...) {}
|
||||
#define debug_only_print0(mask, str) /* */
|
||||
|
||||
#elif defined(JS_JIT_SPEW)
|
||||
|
||||
// Top level logging controller object.
|
||||
extern nanojit::LogControl js_LogController;
|
||||
|
||||
@ -228,8 +238,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ >= 4)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400 || (defined(__GNUC__) && __GNUC__ >= 4)
|
||||
#define USE_TRACE_TYPE_ENUM
|
||||
#endif
|
||||
|
||||
@ -246,7 +255,7 @@ public:
|
||||
* this requirement is correctly enforced by these compilers.
|
||||
*/
|
||||
enum JSTraceType_
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
: int8_t
|
||||
#endif
|
||||
{
|
||||
|
@ -92,6 +92,13 @@
|
||||
# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
|
||||
# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
# define JS_EXTERN_API(__type) extern EXPORT_C __type
|
||||
# define JS_EXPORT_API(__type) EXPORT_C __type
|
||||
# define JS_EXTERN_DATA(__type) extern EXPORT_C __type
|
||||
# define JS_EXPORT_DATA(__type) EXPORT_C __type
|
||||
|
||||
#else /* Unix */
|
||||
|
||||
# ifdef HAVE_VISIBILITY_ATTRIBUTE
|
||||
@ -117,6 +124,8 @@
|
||||
# endif
|
||||
#elif defined(XP_OS2) && defined(__declspec)
|
||||
# define JS_IMPORT_API(__x) __declspec(dllimport) __x
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# define JS_IMPORT_API(__x) IMPORT_C __x
|
||||
#else
|
||||
# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
|
||||
#endif
|
||||
@ -125,6 +134,12 @@
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
#elif defined(XP_OS2) && defined(__declspec)
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# if defined(__CW32__)
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
# else
|
||||
# define JS_IMPORT_DATA(__x) IMPORT_C __x
|
||||
# endif
|
||||
#else
|
||||
# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
|
||||
#endif
|
||||
@ -280,6 +295,9 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "jscpucfg.h" /* We can't auto-detect MSVC configuration */
|
||||
# if _MSC_VER < 1400
|
||||
# define MOZ_NO_VARADIC_MACROS
|
||||
# endif
|
||||
#else
|
||||
# include "jsautocfg.h" /* Use auto-detected configuration */
|
||||
#endif
|
||||
|
@ -790,9 +790,9 @@ namespace nanojit
|
||||
|
||||
// Used for debug printing, if needed
|
||||
verbose_only(
|
||||
ReverseLister *pp_init = NULL,
|
||||
*pp_after_sf1 = NULL,
|
||||
*pp_after_sf2 = NULL;
|
||||
ReverseLister *pp_init = NULL;
|
||||
ReverseLister *pp_after_sf1 = NULL;
|
||||
ReverseLister *pp_after_sf2 = NULL;
|
||||
)
|
||||
|
||||
// set up backwards pipeline: assembler -> StackFilter -> LirReader
|
||||
|
@ -95,7 +95,7 @@ namespace nanojit {
|
||||
|
||||
#define isSPorFP(r) ( (r)==SP || (r)==FP )
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
||||
#ifdef MOZ_NO_VARADIC_MACROS
|
||||
static void asm_output(const char *f, ...) {}
|
||||
#define gpn(r) regNames[(r)]
|
||||
#define fpn(r) regNames[(r)]
|
||||
|
@ -76,7 +76,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) || defined(_MSC_VER) && _MSC_VER < 1400
|
||||
#if defined(DEBUG) || defined(MOZ_NO_VARADIC_MACROS)
|
||||
#if !defined _DEBUG
|
||||
#define _DEBUG
|
||||
#endif
|
||||
|
@ -131,7 +131,7 @@ namespace nanojit
|
||||
|
||||
const uint32_t MAXARGS = 8;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
||||
#ifdef MOZ_NO_VARADIC_MACROS
|
||||
static void NanoAssertMsgf(bool a,const char *f,...) {}
|
||||
static void NanoAssertMsg(bool a,const char *m) {}
|
||||
static void NanoAssert(bool a) {}
|
||||
@ -180,7 +180,7 @@ namespace nanojit
|
||||
#define NJ_PROFILE 1
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
||||
#ifdef MOZ_NO_VARADIC_MACROS
|
||||
#include <stdio.h>
|
||||
#define verbose_outputf if (_logc->lcbits & LC_Assembly) \
|
||||
Assembler::outputf
|
||||
|
18
layout/reftests/bugs/502795-1-ref.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>bug 502795 - letterspace with downloaded font</title>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/MarkA.ttf);
|
||||
}
|
||||
p {
|
||||
font-family: test;
|
||||
font-size: 24pt;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<p>A</p>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/bugs/502795-1.html
Normal file
@ -0,0 +1,21 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>bug 502795 - letterspace with downloaded font</title>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/MarkA.ttf);
|
||||
}
|
||||
p {
|
||||
font-family: test;
|
||||
font-size: 24pt;
|
||||
letter-spacing: 10px;
|
||||
}
|
||||
</style>
|
||||
<!-- with letterspacing, the downloaded font will fail to render
|
||||
via coretext due to bug 502795 -->
|
||||
<body>
|
||||
<p>A</p>
|
||||
</body>
|
||||
</html>
|
@ -1275,5 +1275,6 @@ fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") == 488692-1.html 488692-1-ref.html # needs
|
||||
== 495385-5.html 495385-5-ref.html
|
||||
== 498228-1.xul 498228-1-ref.xul
|
||||
== 496032-1.html 496032-1-ref.html
|
||||
== 502795-1.html 502795-1-ref.html
|
||||
== 503364-1a.html 503364-1-ref.html
|
||||
== 503364-1b.html 503364-1-ref.html
|
||||
|
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS 2.1: Font matching algorithm (reference)</title>
|
||||
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
|
||||
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS 2.1: Font matching algorithm</title>
|
||||
<link rel="author" title="L. David Baron" href="http://dbaron.org/" />
|
||||
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#algorithm" />
|
||||
<meta name="assert" content="That the 'UA-dependent default 'font-family'' described in step (5) does not vary based on the ancestor's font-family property." />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div style="font-family: Arial, Helvetica, sans-serif">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Arial, Helvetica">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Arial">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Times New Roman, Times, serif">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Times New Roman, Times">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Times New Roman">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Courier New, Courier, monospace">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-family: Verdana">
|
||||
<div style="font-family: FontDoesNotExist">
|
||||
Every line of text in this page should be in the same font.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
1
layout/reftests/font-matching/reftest.list
Normal file
@ -0,0 +1 @@
|
||||
== CSS21-t1502-no-inherited-font-family.xhtml CSS21-t1502-no-inherited-font-family-ref.xhtml
|
@ -71,6 +71,9 @@ include floats/reftest.list
|
||||
# font-face
|
||||
include font-face/reftest.list
|
||||
|
||||
# font matching
|
||||
include font-matching/reftest.list
|
||||
|
||||
# forms
|
||||
include forms/reftest.list
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(2.5, false)">
|
||||
<!-- This test checks a basic animation with "xlink:href" targeting -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<rect id="theRect" x="15" y="15" width="200" height="50" fill="blue" />
|
||||
<animate xlink:href="#theRect" attributeName="height"
|
||||
from="50" to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="100" fill="blue"/>
|
||||
<animate xlink:href="#blueRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 490 B |
18
layout/reftests/svg/smil/anim-targethref-2.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior when "xlink:href" is modified -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var anim = document.getElementById("anim");
|
||||
anim.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#blueRect");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="redRect" x="15" y="15" width="200" height="100" fill="red"/>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="100" fill="blue"/>
|
||||
<animate id="anim" xlink:href="#redRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
After Width: | Height: | Size: 782 B |
15
layout/reftests/svg/smil/anim-targethref-3.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(2.5, false)">
|
||||
<!-- This test checks our behavior with animations that target nodes
|
||||
other than their parents. -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="100" fill="blue"/>
|
||||
<animate id="anim" xlink:href="#redRect" attributeName="height"
|
||||
to="0" begin="0s" dur="2s" fill="freeze"/>
|
||||
<rect id="redRect" x="15" y="215" width="200" height="100" fill="red">
|
||||
<animate id="anim" xlink:href="#blueRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 746 B |
20
layout/reftests/svg/smil/anim-targethref-4.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with animations that are initially
|
||||
href-targeted, but lose their href attribute. -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var anim = document.getElementById("anim");
|
||||
anim.removeAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="100" fill="blue">
|
||||
<animate id="anim" xlink:href="#redRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</rect>
|
||||
<rect id="redRect" x="15" y="215" width="200" height="0" fill="red"/>
|
||||
</svg>
|
After Width: | Height: | Size: 843 B |
21
layout/reftests/svg/smil/anim-targethref-5.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with animations that initially
|
||||
have no 'xlink:href' attribute, but receive one via scripting. -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var anim = document.getElementById("anim");
|
||||
anim.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#blueRect");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="100" fill="blue">
|
||||
</rect>
|
||||
<rect id="redRect" x="15" y="215" width="200" height="0" fill="red">
|
||||
<animate id="anim" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</rect>
|
||||
</svg>
|
After Width: | Height: | Size: 852 B |
18
layout/reftests/svg/smil/anim-targethref-6.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with an 'xlink:href'-targeted animation
|
||||
when the target's ID is changed (which makes it no longer the target) -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var rect = document.getElementById("blueRect");
|
||||
rect.setAttributeNS(null, "id", "differentBlueRect");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="200" fill="blue"/>
|
||||
<animate id="anim" xlink:href="#blueRect" attributeName="height"
|
||||
to="0" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
After Width: | Height: | Size: 779 B |
18
layout/reftests/svg/smil/anim-targethref-7.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with an 'xlink:href'-targeted animation
|
||||
when the target's ID is removed (which makes it no longer the target) -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var rect = document.getElementById("blueRect");
|
||||
rect.removeAttributeNS(null, "id");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="blueRect" x="15" y="15" width="200" height="200" fill="blue"/>
|
||||
<animate id="anim" xlink:href="#blueRect" attributeName="height"
|
||||
to="0" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
After Width: | Height: | Size: 761 B |
20
layout/reftests/svg/smil/anim-targethref-8.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with an 'xlink:href'-targeted animation
|
||||
when an earlier node suddenly obtains the target ID string (thereby
|
||||
becoming the new animation target). -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var rect = document.getElementById("myLaterRect");
|
||||
rect.setAttributeNS(null, "id", "myRect");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="myLaterRect" x="15" y="15" width="200" height="0" fill="blue"/>
|
||||
<rect id="myRect" x="15" y="215" width="200" height="0" fill="red"/>
|
||||
<animate id="anim" xlink:href="#myRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
After Width: | Height: | Size: 884 B |
19
layout/reftests/svg/smil/anim-targethref-9.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="go()">
|
||||
<!-- This test checks our behavior with an 'xlink:href'-targeted animation
|
||||
where there's initially no matching target, but then an element's ID is
|
||||
set to match (making it the target) -->
|
||||
<script xlink:href="smil-util.js" type="text/javascript"/>
|
||||
<script type="text/javascript">
|
||||
function go() {
|
||||
var rect = document.getElementById("rect");
|
||||
rect.setAttributeNS(null, "id", "blueRect");
|
||||
setTimeAndSnapshot(2.5, false)
|
||||
}
|
||||
</script>
|
||||
<rect id="rect" x="15" y="15" width="200" height="100" fill="blue"/>
|
||||
<animate id="anim" xlink:href="#blueRect" attributeName="height"
|
||||
to="200" begin="0s" dur="2s" fill="freeze"/>
|
||||
</svg>
|
After Width: | Height: | Size: 809 B |
@ -69,16 +69,25 @@ fails == anim-fillopacity-1.svg anim-standard-ref.svg # non-length-numeric va
|
||||
== anim-remove-7.svg anim-standard-ref.svg
|
||||
== anim-retarget-1.svg anim-standard-ref.svg
|
||||
== anim-retarget-2.svg anim-standard-ref.svg
|
||||
fails == anim-retarget-3.svg anim-standard-ref.svg # href support
|
||||
== anim-retarget-3.svg anim-standard-ref.svg
|
||||
== anim-retarget-4.svg anim-standard-ref.svg
|
||||
fails == anim-retarget-5.svg anim-standard-ref.svg # href support
|
||||
fails == anim-retarget-6.svg anim-standard-ref.svg # href support
|
||||
fails == anim-retarget-7.svg anim-standard-ref.svg # href support
|
||||
== anim-retarget-5.svg anim-standard-ref.svg
|
||||
== anim-retarget-6.svg anim-standard-ref.svg
|
||||
== anim-retarget-7.svg anim-standard-ref.svg
|
||||
== anim-retarget-8.svg anim-standard-ref.svg
|
||||
|
||||
fails == anim-strokecolor-1.svg anim-standard-ref.svg # color support
|
||||
fails == anim-strokewidth-1.svg anim-standard-ref.svg # color support
|
||||
fails == anim-targethref-1.svg anim-standard-ref.svg # href support
|
||||
|
||||
== anim-targethref-1.svg anim-standard-ref.svg
|
||||
== anim-targethref-2.svg anim-standard-ref.svg
|
||||
== anim-targethref-3.svg anim-standard-ref.svg
|
||||
== anim-targethref-4.svg anim-standard-ref.svg
|
||||
== anim-targethref-5.svg anim-standard-ref.svg
|
||||
== anim-targethref-6.svg anim-standard-ref.svg
|
||||
== anim-targethref-7.svg anim-standard-ref.svg
|
||||
== anim-targethref-8.svg anim-standard-ref.svg
|
||||
== anim-targethref-9.svg anim-standard-ref.svg
|
||||
|
||||
== anim-width-done-1a.svg anim-standard-ref.svg
|
||||
== anim-width-done-1b.svg anim-standard-ref.svg
|
||||
|
@ -215,31 +215,21 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
// XXX Are there other things like this?
|
||||
aRuleData->mFontData->mFamilyFromHTML = PR_FALSE;
|
||||
}
|
||||
else if (iProp == eCSSProperty_color ||
|
||||
iProp == eCSSProperty_background_color ||
|
||||
iProp == eCSSProperty_border_top_color ||
|
||||
iProp == eCSSProperty_border_right_color_value ||
|
||||
iProp == eCSSProperty_border_right_color_ltr_source ||
|
||||
iProp == eCSSProperty_border_right_color_rtl_source ||
|
||||
iProp == eCSSProperty_border_bottom_color ||
|
||||
iProp == eCSSProperty_border_left_color_value ||
|
||||
iProp == eCSSProperty_border_left_color_ltr_source ||
|
||||
iProp == eCSSProperty_border_left_color_rtl_source ||
|
||||
iProp == eCSSProperty__moz_column_rule_color ||
|
||||
iProp == eCSSProperty_outline_color) {
|
||||
if (ShouldIgnoreColors(aRuleData)) {
|
||||
if (iProp == eCSSProperty_background_color) {
|
||||
// Force non-'transparent' background
|
||||
// colors to the user's default.
|
||||
if (target->IsNonTransparentColor()) {
|
||||
target->SetColorValue(aRuleData->
|
||||
mPresContext->
|
||||
DefaultBackgroundColor());
|
||||
}
|
||||
} else {
|
||||
// Ignore 'color', 'border-*-color', etc.
|
||||
*target = nsCSSValue();
|
||||
if (nsCSSProps::PropHasFlags(iProp,
|
||||
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
|
||||
ShouldIgnoreColors(aRuleData))
|
||||
{
|
||||
if (iProp == eCSSProperty_background_color) {
|
||||
// Force non-'transparent' background
|
||||
// colors to the user's default.
|
||||
if (target->IsNonTransparentColor()) {
|
||||
target->SetColorValue(aRuleData->
|
||||
mPresContext->
|
||||
DefaultBackgroundColor());
|
||||
}
|
||||
} else {
|
||||
// Ignore 'color', 'border-*-color', etc.
|
||||
*target = nsCSSValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,6 +237,9 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
} break;
|
||||
|
||||
case eCSSType_Rect: {
|
||||
NS_ABORT_IF_FALSE(!nsCSSProps::PropHasFlags(iProp,
|
||||
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED),
|
||||
"this case needs to handle color properties");
|
||||
const nsCSSRect* val = RectAtCursor(cursor);
|
||||
NS_ASSERTION(val->HasValue(), "oops");
|
||||
nsCSSRect* target = static_cast<nsCSSRect*>(prop);
|
||||
@ -262,6 +255,9 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
} break;
|
||||
|
||||
case eCSSType_ValuePair: {
|
||||
NS_ABORT_IF_FALSE(!nsCSSProps::PropHasFlags(iProp,
|
||||
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED),
|
||||
"this case needs to handle color properties");
|
||||
const nsCSSValuePair* val = ValuePairAtCursor(cursor);
|
||||
NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null ||
|
||||
val->mYValue.GetUnit() != eCSSUnit_Null, "oops");
|
||||
@ -305,14 +301,11 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
NS_ASSERTION(val, "oops");
|
||||
*target = val;
|
||||
|
||||
if (iProp == eCSSProperty_background_image ||
|
||||
iProp == eCSSProperty_border_top_colors ||
|
||||
iProp == eCSSProperty_border_right_colors ||
|
||||
iProp == eCSSProperty_border_bottom_colors ||
|
||||
iProp == eCSSProperty_border_left_colors) {
|
||||
if (ShouldIgnoreColors(aRuleData)) {
|
||||
*target = nsnull;
|
||||
}
|
||||
if (nsCSSProps::PropHasFlags(iProp,
|
||||
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
|
||||
ShouldIgnoreColors(aRuleData))
|
||||
{
|
||||
*target = nsnull;
|
||||
}
|
||||
}
|
||||
cursor += CDBPointerStorage_advance;
|
||||
|
@ -60,6 +60,9 @@
|
||||
#define CSS_PROPERTY_APPLIES_TO_FIRST_LINE (1<<3)
|
||||
#define CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE \
|
||||
(CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | CSS_PROPERTY_APPLIES_TO_FIRST_LINE)
|
||||
// Note that 'background-color' is ignored differently from the other
|
||||
// properties that have this set, but that's just special-cased.
|
||||
#define CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED (1<<4)
|
||||
|
||||
class nsCSSProps {
|
||||
public:
|
||||
|
@ -9,7 +9,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style type="text/css">
|
||||
|
||||
#one, #three { background: blue; color: yellow; border: thin solid red; -moz-column-rule: 2px solid green; }
|
||||
#one, #three { background: blue; color: yellow; border: thin solid red; -moz-column-rule: 2px solid green; text-shadow: 2px 2px green; }
|
||||
#two { background: transparent; border: thin solid; }
|
||||
#five, #six {border: thick solid red; -moz-border-start-color:green; -moz-border-end-color:blue}
|
||||
#seven {
|
||||
@ -90,7 +90,9 @@ function part1()
|
||||
isnot(cs1.borderBottomColor, cs2.borderBottomColor,
|
||||
"border-top-color applies");
|
||||
isnot(cs1.MozColumnRuleColor, cs2.MozColumnRuleColor,
|
||||
"-moz-column-rule-color applies");
|
||||
"-moz-column-rule-color applies");
|
||||
isnot(cs1.textShadow, cs2.textShadow,
|
||||
"text-shadow applies");
|
||||
is(cs1.borderTopColor, cs3.borderTopColor, "border-top-color applies");
|
||||
is(cs1.borderRightColor, cs3.borderRightColor,
|
||||
"border-right-color applies");
|
||||
@ -100,6 +102,8 @@ function part1()
|
||||
"border-top-color applies");
|
||||
is(cs1.MozColumnRuleColor, cs3.MozColumnRuleColor,
|
||||
"-moz-column-rule-color applies");
|
||||
is(cs1.TextShadow, cs3.TextShadow,
|
||||
"text-shadow applies");
|
||||
isnot(cs5.borderRightColor, cs2.borderRightColor,
|
||||
"-moz-border-end-color applies");
|
||||
isnot(cs5.borderLeftColor, cs2.borderLeftColor,
|
||||
@ -168,6 +172,8 @@ function part2()
|
||||
"border-bottom-color is blocked");
|
||||
is(cs1.MozColumnRuleColor, cs2.MozColumnRuleColor,
|
||||
"-moz-column-rule-color is blocked");
|
||||
is(cs1.TextShadow, cs2.TextShadow,
|
||||
"text-shadow is blocked");
|
||||
is(cs3.backgroundColor, cs1.backgroundColor, "background-color transparency preserved (opaque)");
|
||||
is(cs3.color, cs4.color, "color is blocked");
|
||||
is(cs3.borderTopColor, cs4.borderTopColor, "border-top-color is blocked");
|
||||
|
@ -38,10 +38,12 @@ function run() {
|
||||
|
||||
function should_apply(q) {
|
||||
ok(query_applies(q), q + " should apply");
|
||||
test_serialization(q, true, true);
|
||||
}
|
||||
|
||||
function should_not_apply(q) {
|
||||
ok(!query_applies(q), q + " should not apply");
|
||||
test_serialization(q, true, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -69,6 +71,7 @@ function run() {
|
||||
|
||||
function query_should_be_parseable(q) {
|
||||
ok(query_is_parseable(q), "query " + q + " should be parseable");
|
||||
test_serialization(q, false, false);
|
||||
}
|
||||
|
||||
function query_should_not_be_parseable(q) {
|
||||
@ -86,6 +89,7 @@ function run() {
|
||||
function expression_should_be_parseable(e) {
|
||||
ok(expression_is_parseable(e),
|
||||
"expression " + e + " should be parseable");
|
||||
test_serialization("all and (" + e + ")", false, false);
|
||||
}
|
||||
|
||||
function expression_should_not_be_parseable(e) {
|
||||
@ -93,6 +97,20 @@ function run() {
|
||||
"expression " + e + " should not be parseable");
|
||||
}
|
||||
|
||||
function test_serialization(q, test_application, should_apply) {
|
||||
style.setAttribute("media", q);
|
||||
var ser1 = style.sheet.media.mediaText;
|
||||
isnot(ser1, "", "serialization of '" + q + "' should not be empty");
|
||||
style.setAttribute("media", ser1);
|
||||
var ser2 = style.sheet.media.mediaText;
|
||||
is(ser2, ser1, "parse+serialize of '" + q + "' should be idempotent");
|
||||
if (test_application) {
|
||||
var applies = body_cs.getPropertyValue("text-decoration") == "underline";
|
||||
is(applies, should_apply,
|
||||
"Media query '" + q + "' should apply after serialize + reparse");
|
||||
}
|
||||
}
|
||||
|
||||
// The no-type syntax doesn't mix with the not and only keywords.
|
||||
query_should_be_parseable("(orientation)");
|
||||
query_should_not_be_parseable("not (orientation)");
|
||||
@ -276,7 +294,9 @@ function run() {
|
||||
}
|
||||
|
||||
var is_monochrome = query_applies("all and (min-monochrome: 1)");
|
||||
test_serialization("all and (min-monochrome: 1)", true, is_monochrome);
|
||||
var is_color = query_applies("all and (min-color: 1)");
|
||||
test_serialization("all and (min-color: 1)", true, is_color);
|
||||
isnot(is_monochrome, is_color, "should be either monochrome or color");
|
||||
|
||||
function depth_query(prefix, depth) {
|
||||
|
@ -7,28 +7,27 @@
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="run()">
|
||||
<p id="display"><iframe id="iframe" src="about:blank"></iframe></p>
|
||||
<p id="display"><iframe id="iframe" src="about:blank"></iframe><iframe id="cloneiframe" src="about:blank"></iframe></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var cloneiframe;
|
||||
|
||||
function run() {
|
||||
|
||||
var iframe = document.getElementById("iframe");
|
||||
var ifwin = iframe.contentWindow;
|
||||
var ifdoc = iframe.contentDocument;
|
||||
|
||||
function setup_style() {
|
||||
var style_elem = ifdoc.createElement("style");
|
||||
style_elem.setAttribute("type", "text/css");
|
||||
ifdoc.getElementsByTagName("head")[0].appendChild(style_elem);
|
||||
var style_text = ifdoc.createTextNode("");
|
||||
style_elem.appendChild(style_text);
|
||||
return style_text;
|
||||
}
|
||||
cloneiframe = document.getElementById("cloneiframe");
|
||||
|
||||
var style_text = setup_style();
|
||||
var style_elem = ifdoc.createElement("style");
|
||||
style_elem.setAttribute("type", "text/css");
|
||||
ifdoc.getElementsByTagName("head")[0].appendChild(style_elem);
|
||||
var style_text = ifdoc.createTextNode("");
|
||||
style_elem.appendChild(style_text);
|
||||
|
||||
var gCounter = 0;
|
||||
|
||||
@ -104,6 +103,52 @@ function run() {
|
||||
|
||||
ifdoc.body.innerHTML = "";
|
||||
style_text.data = "";
|
||||
|
||||
// And now test that when we clone the style sheet, we end up
|
||||
// with the same selector (serializes to same string, and
|
||||
// matches the same things).
|
||||
zi = ++gCounter;
|
||||
var style_sheet = "data:text/css," +
|
||||
escape(namespaces + selector + "{ z-index: " + zi + " }");
|
||||
var style_sheet_link =
|
||||
"<link rel='stylesheet' href='" + style_sheet + "'>";
|
||||
var html_doc = "<!DOCTYPE HTML>" +
|
||||
style_sheet_link + style_sheet_link +
|
||||
"<body>" + body_contents;
|
||||
var docurl = "data:text/html," + escape(html_doc);
|
||||
defer_clonedoc_tests(docurl, function() {
|
||||
var clonedoc = cloneiframe.contentDocument;
|
||||
var clonewin = cloneiframe.contentWindow;
|
||||
var links = clonedoc.getElementsByTagName("link");
|
||||
// cause a clone
|
||||
links[1].sheet.insertRule("#nonexistent { color: purple}", idx + 1);
|
||||
// remove the uncloned sheet
|
||||
links[0].parentNode.removeChild(links[0]);
|
||||
|
||||
var should_match = match_fn(clonedoc);
|
||||
var should_not_match = notmatch_fn(clonedoc);
|
||||
|
||||
if (should_match.length + should_not_match.length == 0) {
|
||||
ok(false, "nothing to check");
|
||||
}
|
||||
|
||||
for (var i = 0; i < should_match.length; ++i) {
|
||||
var e = should_match[i];
|
||||
is(clonewin.getComputedStyle(e, "").zIndex, zi,
|
||||
"element in " + body_contents + " matched clone of " +
|
||||
selector);
|
||||
}
|
||||
for (var i = 0; i < should_not_match.length; ++i) {
|
||||
var e = should_not_match[i];
|
||||
is(clonewin.getComputedStyle(e, "").zIndex, "auto",
|
||||
"element in " + body_contents + " did not match clone of " +
|
||||
selector);
|
||||
}
|
||||
|
||||
var ser3 = links[0].sheet.cssRules[idx].selectorText;
|
||||
is(ser3, ser1,
|
||||
"selector " + selector + " serializes correctly after cloning");
|
||||
});
|
||||
}
|
||||
|
||||
function should_serialize_to(selector, serialization)
|
||||
@ -117,14 +162,55 @@ function run() {
|
||||
|
||||
function test_parseable(selector)
|
||||
{
|
||||
var zi = ++gCounter;
|
||||
ifdoc.body.innerHTML = "<p></p>";
|
||||
|
||||
var zi = ++gCounter;
|
||||
style_text.data = "p, " + selector + "{ z-index: " + zi + " }";
|
||||
var should_match = ifdoc.getElementsByTagName("p")[0];
|
||||
is(ifwin.getComputedStyle(should_match, "").zIndex, zi,
|
||||
"selector " + selector + " was parsed");
|
||||
|
||||
// Test that it serializes to something that is also parseable.
|
||||
var ser1 = style_elem.sheet.cssRules[0].selectorText;
|
||||
zi = ++gCounter;
|
||||
style_text.data = ser1 + "{ z-index: " + zi + " }";
|
||||
is(ifwin.getComputedStyle(should_match, "").zIndex, zi,
|
||||
"serialization " + ser1 + " of selector p, " + selector +
|
||||
" was parsed");
|
||||
var ser2 = style_elem.sheet.cssRules[0].selectorText;
|
||||
is(ser2, ser1,
|
||||
"parse+serialize of selector " + selector + " is idempotent");
|
||||
|
||||
ifdoc.body.innerHTML = "";
|
||||
style_text.data = "";
|
||||
|
||||
// Test that it clones to the same thing it serializes to.
|
||||
zi = ++gCounter;
|
||||
var style_sheet = "data:text/css," +
|
||||
escape("p, " + selector + "{ z-index: " + zi + " }");
|
||||
var style_sheet_link =
|
||||
"<link rel='stylesheet' href='" + style_sheet + "'>";
|
||||
var html_doc = "<!DOCTYPE HTML>" +
|
||||
style_sheet_link + style_sheet_link +
|
||||
"<p></p>";
|
||||
var docurl = "data:text/html," + escape(html_doc);
|
||||
|
||||
defer_clonedoc_tests(docurl, function() {
|
||||
var clonedoc = cloneiframe.contentDocument;
|
||||
var clonewin = cloneiframe.contentWindow;
|
||||
var links = clonedoc.getElementsByTagName("link");
|
||||
// cause a clone
|
||||
links[1].sheet.insertRule("#nonexistent { color: purple}", 0);
|
||||
// remove the uncloned sheet
|
||||
links[0].parentNode.removeChild(links[0]);
|
||||
|
||||
should_match = clonedoc.getElementsByTagName("p")[0];
|
||||
is(clonewin.getComputedStyle(should_match, "").zIndex, zi,
|
||||
"selector " + selector + " was cloned correctly");
|
||||
var ser3 = links[0].sheet.cssRules[1].selectorText;
|
||||
is(ser3, ser1,
|
||||
"selector " + selector + " serializes correctly after cloning");
|
||||
});
|
||||
}
|
||||
|
||||
function test_balanced_unparseable(selector)
|
||||
@ -513,8 +599,8 @@ function run() {
|
||||
xul_default_ns);
|
||||
test_selector_in_html("html|a", single_a, set_single, empty_set,
|
||||
xul_default_ns + html_ns);
|
||||
// Type selectors inside :not() bring in default namespaces, but
|
||||
// non-type selectors don't.
|
||||
// Type selectors inside :not() bring in default namespaces, but
|
||||
// non-type selectors don't.
|
||||
test_selector_in_html("*|a:not(*)", single_a, set_single, empty_set,
|
||||
xul_default_ns);
|
||||
test_selector_in_html("*|a:not(a)", single_a, set_single, empty_set,
|
||||
@ -546,7 +632,36 @@ function run() {
|
||||
test_selector_in_html("html|a:not(*|a)", single_a, empty_set, set_single,
|
||||
xul_default_ns + html_ns);
|
||||
|
||||
SimpleTest.finish();
|
||||
run_deferred_tests();
|
||||
}
|
||||
|
||||
var deferred_tests = [];
|
||||
|
||||
function defer_clonedoc_tests(docurl, onloadfunc)
|
||||
{
|
||||
deferred_tests.push( { docurl: docurl, onloadfunc: onloadfunc } );
|
||||
}
|
||||
|
||||
function run_deferred_tests()
|
||||
{
|
||||
if (deferred_tests.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
cloneiframe.onload = deferred_tests_onload;
|
||||
cloneiframe.src = deferred_tests[0].docurl;
|
||||
}
|
||||
|
||||
function deferred_tests_onload(event)
|
||||
{
|
||||
if (event.target != cloneiframe)
|
||||
return;
|
||||
|
||||
deferred_tests[0].onloadfunc();
|
||||
deferred_tests.shift();
|
||||
|
||||
run_deferred_tests();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -44,7 +44,7 @@
|
||||
* access of cookie objects
|
||||
*/
|
||||
|
||||
[scriptable, uuid(8587f4e0-870c-11dd-ad8b-0800200c9a66)]
|
||||
[scriptable, uuid(05c420e5-03d0-4c7b-a605-df7ebe5ca326)]
|
||||
|
||||
interface nsICookie2 : nsICookie
|
||||
{
|
||||
@ -84,5 +84,13 @@ interface nsICookie2 : nsICookie
|
||||
*/
|
||||
readonly attribute PRInt64 creationTime;
|
||||
|
||||
/**
|
||||
* the last time the cookie was accessed (i.e. created,
|
||||
* modified, or read by the server), in microseconds
|
||||
* since midnight (00:00:00), January 1, 1970 UTC.
|
||||
*
|
||||
* note that this time may be approximate.
|
||||
*/
|
||||
readonly attribute PRInt64 lastAccessed;
|
||||
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ interface nsIFile;
|
||||
* Additions to the frozen nsICookieManager
|
||||
*/
|
||||
|
||||
[scriptable, uuid(5047cab4-9cb2-4927-a4ab-77422bc3bc67)]
|
||||
[scriptable, uuid(d1e9e50f-b78b-4e3b-a474-f3cbca59b013)]
|
||||
interface nsICookieManager2 : nsICookieManager
|
||||
{
|
||||
/**
|
||||
@ -110,6 +110,24 @@ interface nsICookieManager2 : nsICookieManager
|
||||
*/
|
||||
unsigned long countCookiesFromHost(in ACString aHost);
|
||||
|
||||
/**
|
||||
* Returns an enumerator of cookies that would be returned to a given host,
|
||||
* ignoring the cookie flags isDomain, isSecure, and isHttpOnly. Thus, for a
|
||||
* host "weather.yahoo.com", host or domain cookies for "weather.yahoo.com"
|
||||
* and "yahoo.com" would be returned, while a cookie for "my.weather.yahoo.com"
|
||||
* would not.
|
||||
*
|
||||
* @param aHost
|
||||
* the host string to look for, e.g. "google.com". this should consist
|
||||
* of only the host portion of a URI, and should not contain a leading
|
||||
* dot, a port, etc.
|
||||
*
|
||||
* @return an nsISimpleEnumerator of nsICookie2 objects.
|
||||
*
|
||||
* @see countCookiesFromHost
|
||||
*/
|
||||
nsISimpleEnumerator getCookiesFromHost(in ACString aHost);
|
||||
|
||||
/**
|
||||
* Import an old-style cookie file. Imported cookies will be added to the
|
||||
* existing database. If the database contains any cookies the same as those
|
||||
|
@ -143,6 +143,7 @@ NS_IMETHODIMP nsCookie::GetIsHttpOnly(PRBool *aHttpOnly) { *aHttpOnly = IsHttp
|
||||
NS_IMETHODIMP nsCookie::GetStatus(nsCookieStatus *aStatus) { *aStatus = 0; return NS_OK; }
|
||||
NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; }
|
||||
NS_IMETHODIMP nsCookie::GetCreationTime(PRInt64 *aCreation){ *aCreation = CreationID(); return NS_OK; }
|
||||
NS_IMETHODIMP nsCookie::GetLastAccessed(PRInt64 *aTime) { *aTime = LastAccessed(); return NS_OK; }
|
||||
|
||||
// compatibility method, for use with the legacy nsICookie interface.
|
||||
// here, expires == 0 denotes a session cookie.
|
||||
|
@ -139,6 +139,7 @@ struct nsListIter
|
||||
{
|
||||
nsListIter() {}
|
||||
|
||||
explicit
|
||||
nsListIter(nsCookieEntry *aEntry)
|
||||
: entry(aEntry)
|
||||
, prev(nsnull)
|
||||
@ -2169,6 +2170,35 @@ nsCookieService::CountCookiesFromHost(const nsACString &aHost,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// get an enumerator of cookies stored by a particular host. this is provided by the
|
||||
// nsICookieManager2 interface.
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookiesFromHost(const nsACString &aHost,
|
||||
nsISimpleEnumerator **aEnumerator)
|
||||
{
|
||||
nsCOMArray<nsICookie> cookieList(mMaxCookiesPerHost);
|
||||
nsCAutoString hostWithDot(NS_LITERAL_CSTRING(".") + aHost);
|
||||
PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
|
||||
|
||||
const char *currentDot = hostWithDot.get();
|
||||
const char *nextDot = currentDot + 1;
|
||||
do {
|
||||
nsCookieEntry *entry = mHostTable->GetEntry(currentDot);
|
||||
for (nsListIter iter(entry); iter.current; ++iter) {
|
||||
// only append non-expired cookies
|
||||
if (iter.current->Expiry() > currentTime)
|
||||
cookieList.AppendObject(iter.current);
|
||||
}
|
||||
|
||||
currentDot = nextDot;
|
||||
if (currentDot)
|
||||
nextDot = strchr(currentDot + 1, '.');
|
||||
|
||||
} while (currentDot);
|
||||
|
||||
return NS_NewArrayEnumerator(aEnumerator, cookieList);
|
||||
}
|
||||
|
||||
// find an exact cookie specified by host, name, and path that hasn't expired.
|
||||
PRBool
|
||||
nsCookieService::FindCookie(const nsAFlatCString &aHost,
|
||||
|
@ -74,6 +74,7 @@ class nsCookieEntry : public PLDHashEntryHdr
|
||||
typedef const char* KeyTypePointer;
|
||||
|
||||
// do nothing with aHost - we require mHead to be set before we're live!
|
||||
explicit
|
||||
nsCookieEntry(KeyTypePointer aHost)
|
||||
: mHead(nsnull)
|
||||
{
|
||||
|