Make anonymous content inaccessible to web content (bug 96537), r=sicking@bigfoot.com, sr=jst@netscape.com

This commit is contained in:
jkeiser%netscape.com 2002-08-28 08:19:43 +00:00
Родитель f2a9de6bbf
Коммит 8aa6968431
14 изменённых файлов: 148 добавлений и 24 удалений

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

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