diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 1ba2a603e50a..c0ce356f291d 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1411,6 +1411,12 @@ public: static already_AddRefed GetDocumentFromScriptContext(nsIScriptContext *aScriptContext); + /** + * The method checks whether the caller can access native anonymous content. + * If there is no JS in the stack or privileged JS is running, this + * method returns PR_TRUE, otherwise PR_FALSE. + */ + static PRBool CanAccessNativeAnon(); private: static PRBool InitializeEventTable(); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index c4b035915063..0bc447356c67 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -176,6 +176,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIConsoleService.h" #include "mozAutoDocUpdate.h" +#include "jsinterp.h" const char kLoadAsData[] = "loadAsData"; @@ -4943,3 +4944,55 @@ nsContentTypeParser::GetParameter(const char* aParameterName, nsAString& aResult EmptyCString(), PR_FALSE, nsnull, aResult); } + +/* static */ + +// If you change this code, change also AllowedToAct() in +// XPCSystemOnlyWrapper.cpp! +PRBool +nsContentUtils::CanAccessNativeAnon() +{ + JSContext* cx = nsnull; + sThreadJSContextStack->Peek(&cx); + if (!cx) { + return PR_TRUE; + } + JSStackFrame* fp; + nsIPrincipal* principal = + sSecurityManager->GetCxSubjectPrincipalAndFrame(cx, &fp); + NS_ENSURE_TRUE(principal, PR_FALSE); + + if (!fp) { + if (!JS_FrameIterator(cx, &fp)) { + // No code at all is running. So we must be arriving here as the result + // of C++ code asking us to do something. Allow access. + return PR_TRUE; + } + + // Some code is running, we can't make the assumption, as above, but we + // can't use a native frame, so clear fp. + fp = nsnull; + } + + void *annotation = fp ? JS_GetFrameAnnotation(cx, fp) : nsnull; + PRBool privileged; + if (NS_SUCCEEDED(principal->IsCapabilityEnabled("UniversalXPConnect", + annotation, + &privileged)) && + privileged) { + // UniversalXPConnect things are allowed to touch us. + return PR_TRUE; + } + + // XXX HACK EWW! Allow chrome://global/ access to these things, even + // if they've been cloned into less privileged contexts. + static const char prefix[] = "chrome://global/"; + const char *filename; + if (fp && fp->script && + (filename = fp->script->filename) && + !strncmp(filename, prefix, NS_ARRAY_LENGTH(prefix) - 1)) { + return PR_TRUE; + } + + return PR_FALSE; +} diff --git a/content/events/src/nsDOMMouseEvent.cpp b/content/events/src/nsDOMMouseEvent.cpp index 8b321671d907..d6234ee1421f 100644 --- a/content/events/src/nsDOMMouseEvent.cpp +++ b/content/events/src/nsDOMMouseEvent.cpp @@ -196,6 +196,15 @@ nsDOMMouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget) } if (relatedTarget) { + nsCOMPtr content = do_QueryInterface(relatedTarget); + if (content && content->IsInNativeAnonymousSubtree() && + !nsContentUtils::CanAccessNativeAnon()) { + relatedTarget = content->FindFirstNonNativeAnonymous(); + if (!relatedTarget) { + return NS_OK; + } + } + CallQueryInterface(relatedTarget, aRelatedTarget); } return NS_OK; diff --git a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp index 6fe00ead76b8..0d69f70b61d3 100644 --- a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp +++ b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp @@ -160,6 +160,7 @@ GetWrappedObject(JSContext *cx, JSObject *wrapper) return XPCWrapper::UnwrapGeneric(cx, &sXPC_SOW_JSClass, wrapper); } +// If you change this code, change also nsContentUtils::CanAccessNativeAnon()! JSBool AllowedToAct(JSContext *cx, jsval idval) {