зеркало из https://github.com/mozilla/gecko-dev.git
Make anonymous content inaccessible to web content (bug 96537), r=sicking@bigfoot.com, sr=jst@netscape.com
This commit is contained in:
Родитель
f2a9de6bbf
Коммит
8aa6968431
|
@ -45,6 +45,7 @@ REQUIRES = xpcom \
|
|||
intl \
|
||||
docshell \
|
||||
windowwatcher \
|
||||
content \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
static NS_DEFINE_IID(kIStringBundleServiceIID, NS_ISTRINGBUNDLESERVICE_IID);
|
||||
static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
@ -99,21 +100,48 @@ JSValIDToString(JSContext *cx, const jsval idval) {
|
|||
return NS_REINTERPRET_CAST(PRUnichar*, JS_GetStringChars(str));
|
||||
}
|
||||
|
||||
static inline PRBool
|
||||
IsDOMClass(nsIClassInfo* aClassInfo)
|
||||
// Helper class to get stuff from the ClassInfo and not waste extra time with
|
||||
// virtual method calls for things it has already gotten
|
||||
class ClassInfoData
|
||||
{
|
||||
if (!aClassInfo)
|
||||
return PR_FALSE;
|
||||
public:
|
||||
ClassInfoData(nsIClassInfo *aClassInfo)
|
||||
: mClassInfo(aClassInfo), mDidGetFlags(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
PRUint32 classFlags;
|
||||
nsresult rv = aClassInfo->GetFlags(&classFlags);
|
||||
PRUint32 GetFlags()
|
||||
{
|
||||
if (!mDidGetFlags) {
|
||||
if (mClassInfo) {
|
||||
mDidGetFlags = PR_TRUE;
|
||||
nsresult rv = mClassInfo->GetFlags(&mFlags);
|
||||
if (NS_FAILED(rv)) {
|
||||
mFlags = 0;
|
||||
}
|
||||
} else {
|
||||
mFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv) && (classFlags & nsIClassInfo::DOM_OBJECT);
|
||||
}
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
// Convenience method to get the current js context stack.
|
||||
// Uses cached JSContextStack service instead of calling through
|
||||
// to the service manager.
|
||||
PRBool IsDOMClass()
|
||||
{
|
||||
return GetFlags() & nsIClassInfo::DOM_OBJECT;
|
||||
}
|
||||
PRBool IsContentNode()
|
||||
{
|
||||
return GetFlags() & nsIClassInfo::CONTENT_NODE;
|
||||
}
|
||||
|
||||
private:
|
||||
nsIClassInfo *mClassInfo; // WEAK
|
||||
PRBool mDidGetFlags;
|
||||
PRUint32 mFlags;
|
||||
};
|
||||
|
||||
JSContext *
|
||||
nsScriptSecurityManager::GetCurrentJSContext()
|
||||
{
|
||||
|
@ -634,13 +662,17 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
|||
securityLevel = GetPropertyPolicy(aProperty, cpolicy, aAction);
|
||||
}
|
||||
|
||||
// Hold the class info data here so we don't have to go back to virtual
|
||||
// methods all the time
|
||||
ClassInfoData classInfoData(aClassInfo);
|
||||
|
||||
if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
|
||||
{
|
||||
// No policy found for this property so use the default of last resort.
|
||||
// If we were called from somewhere other than XPConnect
|
||||
// (no XPC call context), assume this is a DOM class. Otherwise,
|
||||
// ask the ClassInfo.
|
||||
if (!aCallContext || IsDOMClass(aClassInfo))
|
||||
if (!aCallContext || classInfoData.IsDOMClass())
|
||||
securityLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS;
|
||||
else
|
||||
securityLevel.level = SCRIPT_SECURITY_NO_ACCESS;
|
||||
|
@ -715,7 +747,18 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
|||
rv = NS_OK;
|
||||
}
|
||||
|
||||
if NS_SUCCEEDED(rv)
|
||||
if (NS_SUCCEEDED(rv) && classInfoData.IsContentNode())
|
||||
{
|
||||
// No access to anonymous content from the web! (bug 164086)
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aObj));
|
||||
NS_ASSERTION(content, "classinfo had CONTENT_NODE set but node did not"
|
||||
"implement nsIContent! Fasten your seat belt.");
|
||||
if (content->IsNativeAnonymous()) {
|
||||
rv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
#ifdef DEBUG_mstoltz
|
||||
printf(" GRANTED.\n");
|
||||
|
@ -2264,7 +2307,7 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
|
|||
PR_FREEIF(iidStr);
|
||||
#endif
|
||||
// XXX Special case for nsIXPCException ?
|
||||
if (IsDOMClass(aClassInfo))
|
||||
if (ClassInfoData(aClassInfo).IsDOMClass())
|
||||
{
|
||||
#if 0
|
||||
printf("DOM class - GRANTED.\n");
|
||||
|
|
|
@ -98,6 +98,20 @@ public:
|
|||
*/
|
||||
NS_IMETHOD SetParent(nsIContent* aParent) = 0;
|
||||
|
||||
/**
|
||||
* Get whether this content is C++-generated anonymous content
|
||||
* @see nsIAnonymousContentCreator
|
||||
* @return whether this content is anonymous
|
||||
*/
|
||||
NS_IMETHOD_(PRBool) IsNativeAnonymous() const = 0;
|
||||
|
||||
/**
|
||||
* Set whether this content is anonymous
|
||||
* @see nsIAnonymousContentCreator
|
||||
* @param aAnonymous whether this content is anonymous
|
||||
*/
|
||||
NS_IMETHOD_(void) SetNativeAnonymous(PRBool aAnonymous) = 0;
|
||||
|
||||
/**
|
||||
* Get the namespace that this element's tag is defined in
|
||||
* @param aResult the namespace [OUT]
|
||||
|
|
|
@ -678,6 +678,19 @@ nsGenericDOMDataNode::SetParent(nsIContent* aParent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsGenericDOMDataNode::IsNativeAnonymous() const
|
||||
{
|
||||
nsIContent* parent = GetParentWeak();
|
||||
return parent && parent->IsNativeAnonymous();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsGenericDOMDataNode::SetNativeAnonymous(PRBool aAnonymous)
|
||||
{
|
||||
// XXX Need to fix this to do something - bug 165110
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericDOMDataNode::GetNameSpaceID(PRInt32& aID) const
|
||||
{
|
||||
|
|
|
@ -173,6 +173,8 @@ public:
|
|||
PRBool aCompileEventHandlers);
|
||||
NS_IMETHOD GetParent(nsIContent*& aResult) const;
|
||||
NS_IMETHOD SetParent(nsIContent* aParent);
|
||||
NS_IMETHOD_(PRBool) IsNativeAnonymous() const;
|
||||
NS_IMETHOD_(void) SetNativeAnonymous(PRBool aAnonymous);
|
||||
NS_IMETHOD GetNameSpaceID(PRInt32& aID) const;
|
||||
NS_IMETHOD NormalizeAttrString(const nsAString& aStr,
|
||||
nsINodeInfo*& aNodeInfo);
|
||||
|
|
|
@ -1856,6 +1856,22 @@ nsGenericElement::SetParent(nsIContent* aParent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsGenericElement::IsNativeAnonymous() const
|
||||
{
|
||||
return !!(GetFlags() & GENERIC_ELEMENT_IS_ANONYMOUS);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsGenericElement::SetNativeAnonymous(PRBool aAnonymous)
|
||||
{
|
||||
if (aAnonymous) {
|
||||
SetFlags(GENERIC_ELEMENT_IS_ANONYMOUS);
|
||||
} else {
|
||||
UnsetFlags(GENERIC_ELEMENT_IS_ANONYMOUS);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericElement::GetNameSpaceID(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
|
|
|
@ -71,26 +71,34 @@ class nsINodeInfo;
|
|||
|
||||
typedef unsigned long PtrBits;
|
||||
|
||||
// This bit will be set if the nsGenericElement has nsDOMSlots
|
||||
/** This bit will be set if the nsGenericElement has nsDOMSlots */
|
||||
#define GENERIC_ELEMENT_DOESNT_HAVE_DOMSLOTS 0x00000001U
|
||||
|
||||
// This bit will be set if the element has a range list in the range
|
||||
// list hash
|
||||
/**
|
||||
* This bit will be set if the element has a range list in the range list hash
|
||||
*/
|
||||
#define GENERIC_ELEMENT_HAS_RANGELIST 0x00000002U
|
||||
|
||||
// This bit will be set if the element has a listener manager in the
|
||||
// listener manager hash
|
||||
/**
|
||||
* This bit will be set if the element has a listener manager in the listener
|
||||
* manager hash
|
||||
*/
|
||||
#define GENERIC_ELEMENT_HAS_LISTENERMANAGER 0x00000004U
|
||||
|
||||
// The number of bits to shift the bit field to get at the content ID
|
||||
#define GENERIC_ELEMENT_CONTENT_ID_BITS_OFFSET 3
|
||||
/** Whether this content is anonymous */
|
||||
#define GENERIC_ELEMENT_IS_ANONYMOUS 0x00000008U
|
||||
|
||||
// This mask masks out the bits that are used for the content ID
|
||||
/** The number of bits to shift the bit field to get at the content ID */
|
||||
#define GENERIC_ELEMENT_CONTENT_ID_BITS_OFFSET 4
|
||||
|
||||
/** This mask masks out the bits that are used for the content ID */
|
||||
#define GENERIC_ELEMENT_CONTENT_ID_MASK \
|
||||
((~PtrBits(0)) << GENERIC_ELEMENT_CONTENT_ID_BITS_OFFSET)
|
||||
|
||||
// The largest value for content ID that fits in
|
||||
// GENERIC_ELEMENT_CONTENT_ID_MASK
|
||||
/**
|
||||
* The largest value for content ID that fits in
|
||||
* GENERIC_ELEMENT_CONTENT_ID_MASK
|
||||
*/
|
||||
#define GENERIC_ELEMENT_CONTENT_ID_MAX_VALUE \
|
||||
((~PtrBits(0)) >> GENERIC_ELEMENT_CONTENT_ID_BITS_OFFSET)
|
||||
|
||||
|
@ -339,6 +347,8 @@ public:
|
|||
PRBool aCompileEventHandlers);
|
||||
NS_IMETHOD GetParent(nsIContent*& aResult) const;
|
||||
NS_IMETHOD SetParent(nsIContent* aParent);
|
||||
NS_IMETHOD_(PRBool) IsNativeAnonymous() const;
|
||||
NS_IMETHOD_(void) SetNativeAnonymous(PRBool aAnonymous);
|
||||
NS_IMETHOD GetNameSpaceID(PRInt32& aNameSpaceID) const;
|
||||
NS_IMETHOD GetTag(nsIAtom*& aResult) const;
|
||||
NS_IMETHOD GetNodeInfo(nsINodeInfo*& aResult) const;
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers);
|
||||
NS_IMETHOD GetParent(nsIContent*& aResult) const;
|
||||
NS_IMETHOD SetParent(nsIContent* aParent);
|
||||
NS_IMETHOD_(PRBool) IsNativeAnonymous() const { return PR_TRUE; }
|
||||
NS_IMETHOD_(void) SetNativeAnonymous(PRBool aAnonymous) { }
|
||||
|
||||
NS_IMETHOD GetNameSpaceID(PRInt32& aID) const {
|
||||
aID = kNameSpaceID_None;
|
||||
|
|
|
@ -2170,6 +2170,18 @@ nsXULElement::SetParent(nsIContent* aParent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsXULElement::IsNativeAnonymous() const
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsXULElement::SetNativeAnonymous(PRBool aAnonymous)
|
||||
{
|
||||
// XXX Need to make this actually do something - bug 165110
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::CanContainChildren(PRBool& aResult) const
|
||||
{
|
||||
|
|
|
@ -411,6 +411,8 @@ public:
|
|||
NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers);
|
||||
NS_IMETHOD GetParent(nsIContent*& aResult) const;
|
||||
NS_IMETHOD SetParent(nsIContent* aParent);
|
||||
NS_IMETHOD_(PRBool) IsNativeAnonymous() const;
|
||||
NS_IMETHOD_(void) SetNativeAnonymous(PRBool aAnonymous);
|
||||
NS_IMETHOD CanContainChildren(PRBool& aResult) const;
|
||||
NS_IMETHOD ChildCount(PRInt32& aResult) const;
|
||||
NS_IMETHOD ChildAt(PRInt32 aIndex, nsIContent*& aResult) const;
|
||||
|
|
|
@ -383,6 +383,7 @@ public:
|
|||
JSObject *globalObj, JSObject **parentObj);
|
||||
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
|
@ -600,6 +601,7 @@ public:
|
|||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD GetFlags(PRUint32* aFlags);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
|
|
|
@ -5211,6 +5211,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell
|
|||
if (NS_FAILED(anonymousItems->QueryElementAt(i, NS_GET_IID(nsIContent), getter_AddRefs(content))))
|
||||
continue;
|
||||
|
||||
content->SetNativeAnonymous(PR_TRUE);
|
||||
content->SetParent(aParent);
|
||||
content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
|
||||
|
||||
|
|
|
@ -5211,6 +5211,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell
|
|||
if (NS_FAILED(anonymousItems->QueryElementAt(i, NS_GET_IID(nsIContent), getter_AddRefs(content))))
|
||||
continue;
|
||||
|
||||
content->SetNativeAnonymous(PR_TRUE);
|
||||
content->SetParent(aParent);
|
||||
content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
|
||||
|
||||
|
|
|
@ -101,6 +101,11 @@ interface nsIClassInfo : nsISupports
|
|||
const PRUint32 DOM_OBJECT = 1 << 3;
|
||||
const PRUint32 PLUGIN_OBJECT = 1 << 4;
|
||||
const PRUint32 EAGER_CLASSINFO = 1 << 5;
|
||||
/**
|
||||
* 'flags' attribute bitflag: whether objects of this type implement
|
||||
* nsIContent.
|
||||
*/
|
||||
const PRUint32 CONTENT_NODE = 1 << 6;
|
||||
|
||||
// The high order bit is RESERVED for consumers of these flags.
|
||||
// No implementor of this interface should ever return flags
|
||||
|
|
Загрузка…
Ссылка в новой задаче