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;
|
||||
@ -1527,7 +1522,7 @@ SessionStoreService.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
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,35 +1531,58 @@ 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 };
|
||||
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++)
|
||||
|
@ -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>
|
@ -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
|
||||
|
@ -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);
|
||||
@ -319,8 +344,17 @@ nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
|
||||
}
|
||||
}
|
||||
|
||||
return nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
||||
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"
|
||||
@ -61,6 +62,9 @@ protected:
|
||||
public:
|
||||
// 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;
|
||||
};
|
||||
|
@ -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,19 +215,10 @@ 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 (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.
|
||||
@ -242,11 +233,13 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor += CDBValueStorage_advance;
|
||||
} 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,16 +301,13 @@ 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)) {
|
||||
if (nsCSSProps::PropHasFlags(iProp,
|
||||
CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) &&
|
||||
ShouldIgnoreColors(aRuleData))
|
||||
{
|
||||
*target = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor += CDBPointerStorage_advance;
|
||||
} break;
|
||||
}
|
||||
|
@ -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 {
|
||||
@ -91,6 +91,8 @@ function part1()
|
||||
"border-top-color applies");
|
||||
isnot(cs1.MozColumnRuleColor, cs2.MozColumnRuleColor,
|
||||
"-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() {
|
||||
cloneiframe = document.getElementById("cloneiframe");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
var style_text = setup_style();
|
||||
|
||||
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)
|
||||
@ -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);
|
||||
|
||||
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)
|
||||
{
|
||||
|