bug 607767 - Fix rewrapping native objects across compartment boundaries. r=jst

This commit is contained in:
Blake Kaplan 2010-10-29 12:49:32 -07:00
parent 08d8cc3e4e
commit ade40c675c
9 changed files with 63 additions and 93 deletions

View File

@ -74,6 +74,7 @@
// General helper includes
#include "nsGlobalWindow.h"
#include "nsHistory.h"
#include "nsIContent.h"
#include "nsIAttribute.h"
#include "nsIDocument.h"
@ -661,7 +662,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(BarProp, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(History, nsHistorySH,
ARRAY_SCRIPTABLE_FLAGS)
ARRAY_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_PRECREATE)
NS_DEFINE_CLASSINFO_DATA(Screen, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
@ -4582,15 +4584,6 @@ nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsDOMClassInfo::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval)
{
NS_WARNING("nsDOMClassInfo::InnerObject Don't call me!");
return NS_ERROR_UNEXPECTED;
}
static nsresult
GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager,
const nsString &aName,
@ -7097,7 +7090,7 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
if (!sgo) {
NS_WARNING("Refusing to create a location in the wrong scope because the "
"docshell is being destroyed");
"docshell is being destroyed");
return NS_ERROR_UNEXPECTED;
}
@ -9914,6 +9907,28 @@ nsStringArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// History helper
NS_IMETHODIMP
nsHistorySH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
nsHistory *history = (nsHistory *)nativeObj;
nsIDocShell *ds = history->GetDocShell();
if (!ds) {
NS_WARNING("Refusing to create a history object in the wrong scope");
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
if (!sgo) {
NS_WARNING("Refusing to create a history object in the wrong scope because the "
"docshell is being destroyed");
return NS_ERROR_UNEXPECTED;
}
*parentObj = sgo->GetGlobalJSObject();
return NS_OK;
}
NS_IMETHODIMP
nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
@ -9925,19 +9940,6 @@ nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
nsresult rv =
sSecMan->CheckPropertyAccess(cx, obj, mData->mName, sItem_id,
nsIXPCSecurityManager::ACCESS_CALL_METHOD);
if (NS_FAILED(rv)) {
// Let XPConnect know that the access was not granted.
*_retval = PR_FALSE;
return NS_OK;
}
// sec check
return nsStringArraySH::GetProperty(wrapper, cx, obj, id, vp, _retval);
}

View File

@ -1270,6 +1270,8 @@ protected:
nsAString& aResult);
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);

View File

@ -58,6 +58,7 @@ public:
// nsIDOMHistory
NS_DECL_NSIDOMHISTORY
nsIDocShell *GetDocShell() { return mDocShell; }
void SetDocShell(nsIDocShell *aDocShell);
protected:

View File

@ -80,7 +80,7 @@
* to *_retval unless they want to return PR_FALSE.
*/
[uuid(5d309b93-e9b4-4374-bcd5-44245c83408f)]
[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)]
interface nsIXPCScriptable : nsISupports
{
/* bitflags used for 'flags' (only 32 bits available!) */
@ -115,7 +115,6 @@ interface nsIXPCScriptable : nsISupports
const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27;
const PRUint32 WANT_EQUALITY = 1 << 28;
const PRUint32 WANT_OUTER_OBJECT = 1 << 29;
const PRUint32 WANT_INNER_OBJECT = 1 << 30;
// The high order bit is RESERVED for consumers of these flags.
// No implementor of this interface should ever return flags
@ -197,9 +196,6 @@ interface nsIXPCScriptable : nsISupports
JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper,
in JSContextPtr cx, in JSObjectPtr obj);
JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper,
in JSContextPtr cx, in JSObjectPtr obj);
void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
};

View File

@ -118,10 +118,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags)
#ifdef XPC_MAP_WANT_OUTER_OBJECT
nsIXPCScriptable::WANT_OUTER_OBJECT |
#endif
#ifdef XPC_MAP_WANT_INNER_OBJECT
nsIXPCScriptable::WANT_INNER_OBJECT |
#endif
#ifdef XPC_MAP_FLAGS
XPC_MAP_FLAGS |
#endif
@ -227,11 +223,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::OuterObject(nsIXPConnectWrappedNative *wrapper,
{NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
#endif
#ifndef XPC_MAP_WANT_INNER_OBJECT
NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval)
{NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
#endif
#ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *proto)
{return NS_OK;}

View File

@ -2004,7 +2004,6 @@ public:
JSBool WantTrace() GET_IT(WANT_TRACE)
JSBool WantEquality() GET_IT(WANT_EQUALITY)
JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT)
JSBool WantInnerObject() GET_IT(WANT_INNER_OBJECT)
JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY)
JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY)
JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY)
@ -2546,10 +2545,10 @@ public:
XPCNativeSet*
GetSet() const {XPCAutoLock al(GetLock()); return mSet;}
private:
void
SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
private:
inline void
ExpireWrapper()
{mMaybeScope = (XPCWrappedNativeScope*)

View File

@ -857,45 +857,6 @@ XPC_WN_OuterObject(JSContext *cx, JSObject *obj)
return obj;
}
static JSObject *
XPC_WN_InnerObject(JSContext *cx, JSObject *obj)
{
XPCWrappedNative *wrapper =
static_cast<XPCWrappedNative *>(obj->getPrivate());
if(!wrapper)
{
Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
return nsnull;
}
if(!wrapper->IsValid())
{
Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);
return nsnull;
}
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
if(si && si->GetFlags().WantInnerObject())
{
JSObject *newThis;
nsresult rv =
si->GetCallback()->InnerObject(wrapper, cx, obj, &newThis);
if(NS_FAILED(rv))
{
Throw(rv, cx);
return nsnull;
}
obj = newThis;
}
return obj;
}
js::Class XPC_WN_NoHelper_JSClass = {
"XPCWrappedNative_NoHelper", // name;
WRAPPER_SLOTS |
@ -925,8 +886,8 @@ js::Class XPC_WN_NoHelper_JSClass = {
// ClassExtension
{
JS_VALUEIFY(js::EqualityOp, XPC_WN_Equality),
XPC_WN_OuterObject,
XPC_WN_InnerObject,
nsnull, // outerObject
nsnull, // innerObject
nsnull, // iteratorObject
nsnull, // wrappedObject
},
@ -1589,11 +1550,8 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal)
if(mFlags.WantOuterObject())
mJSClass.base.ext.outerObject = XPC_WN_OuterObject;
if(mFlags.WantInnerObject())
mJSClass.base.ext.innerObject = XPC_WN_InnerObject;
if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT |
nsIXPCScriptable::WANT_INNER_OBJECT)))
if(!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT))
mCanBeSlim = JS_TRUE;
}

View File

@ -126,10 +126,6 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj
if (!wn->GetClassInfo())
return DoubleWrap(cx, obj, flags);
// We know that DOM objects only allow one object, we can return early.
if (wn->HasProto() && wn->GetProto()->ClassIsDOMObject())
return DoubleWrap(cx, obj, flags);
XPCCallContext ccx(JS_CALLER, cx, obj);
if (NATIVE_HAS_FLAG(&ccx, WantPreCreate)) {
// We have a precreate hook. This object might enforce that we only
@ -159,13 +155,38 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj
if (!ac.enter(cx, scope))
return nsnull;
// NB: Passing a holder here inhibits slim wrappers under
// WrapNativeToJSVal.
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v;
nsresult rv =
nsXPConnect::FastGetXPConnect()->WrapNativeToJSVal(cx, scope, wn->Native(), nsnull,
&NS_GET_IID(nsISupports), PR_FALSE,
&v, nsnull);
if (NS_SUCCEEDED(rv))
&v, getter_AddRefs(holder));
if (NS_SUCCEEDED(rv)) {
obj = JSVAL_TO_OBJECT(v);
NS_ASSERTION(IS_WN_WRAPPER(obj), "bad object");
XPCWrappedNative *newwn = static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
if (newwn->GetSet()->GetInterfaceCount() == 1) {
// Some objects claim to implement nsIClassInfo, but don't
// actually implement GetInterfaces. In those cases, the
// newly-created WN will not have any useful functions or
// properties on it. We detect that here and use the old WN's
// set on the new wrapper.
#ifdef DEBUG
{
XPCNativeInterface *iface = newwn->GetSet()->GetInterfaceAt(0);
JSString *name = JSID_TO_STRING(iface->GetName());
NS_ASSERTION(!strcmp("nsISupports", JS_GetStringBytes(name)), "weird interface");
}
#endif
newwn->SetSet(wn->GetSet());
}
}
return DoubleWrap(cx, obj, flags);
}

View File

@ -69,9 +69,9 @@ function testErrorsAfterPageReload(aEvent) {
Services.console.registerListener(consoleObserver);
var button = content.document.querySelector("button").wrappedJSObject;
var clickEvent = content.wrappedJSObject.document.createEvent("MouseEvents").wrappedJSObject;
var clickEvent = content.document.createEvent("MouseEvents");
clickEvent.initMouseEvent("click", true, true,
content.wrappedJSObject, 0, 0, 0, 0, 0, false, false,
content, 0, 0, 0, 0, 0, false, false,
false, false, 0, null);
executeSoon(function() {