Bug 622301 - Don't use XPCWrappedNative::GetWrappedNativeOfJSObject in quickstub unwrapping. r=mrbkap
authorBobby Holley <bobbyholley@gmail.com>
Fri, 06 Jan 2012 17:29:02 -0800
changeset 85211 668a56be0eef2753c30fecb01bef3961049620bb
parent 85210 c6566c71bea0660c6c953b54494d8410e079413e
child 85212 b1612e3ba9b98fd87061a84357226ca1b54f973c
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs622301
milestone12.0a1
Bug 622301 - Don't use XPCWrappedNative::GetWrappedNativeOfJSObject in quickstub unwrapping. r=mrbkap
js/xpconnect/src/XPCQuickStubs.cpp
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -778,27 +778,63 @@ getNativeFromWrapper(JSContext *cx,
 nsresult
 getWrapper(JSContext *cx,
            JSObject *obj,
            JSObject *callee,
            XPCWrappedNative **wrapper,
            JSObject **cur,
            XPCWrappedNativeTearOff **tearoff)
 {
-    if (XPCWrapper::IsSecurityWrapper(obj) &&
-        !(obj = XPCWrapper::Unwrap(cx, obj))) {
-        return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
+
+    // We can have at most three layers in need of unwrapping here:
+    // * A (possible) security wrapper
+    // * A (possible) Xray waiver
+    // * A (possible) outer window
+    //
+    // The underlying call to js::Unwrap recursively unwraps, but stops if it
+    // hits an outer object. Thus, we need to make at most two unwrapping
+    // calls: one to handle security wrappers and waivers, and one to handle
+    // outer objects.
+    if (js::IsWrapper(obj))
+        obj = XPCWrapper::Unwrap(cx, obj);
+    if (obj && js::IsWrapper(obj)) {
+        MOZ_ASSERT(js::Wrapper::wrapperHandler(obj)->isOuterWindow());
+        obj = XPCWrapper::Unwrap(cx, obj);
     }
 
-    *cur = obj;
+    // The safe unwrap might have failed for SCRIPT_ACCESS_ONLY objects. If it
+    // didn't fail though, we should be done with wrappers.
+    if (!obj)
+        return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
+    MOZ_ASSERT(!js::IsWrapper(obj));
+
+    // Start with sane values.
+    *wrapper = nsnull;
+    *cur = nsnull;
     *tearoff = nsnull;
 
-    *wrapper =
-        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, cur,
-                                                     tearoff);
+    // Handle tearoffs.
+    //
+    // If |obj| is of the tearoff class, that means we're dealing with a JS
+    // object reflection of a particular interface (ie, |foo.nsIBar|). These
+    // JS objects are parented to their wrapper, so we snag the tearoff object
+    // along the way (if desired), and then set |obj| to its parent.
+    if (js::GetObjectClass(obj) == &XPC_WN_Tearoff_JSClass) {
+        *tearoff = (XPCWrappedNativeTearOff*) js::GetObjectPrivate(obj);
+        obj = js::GetObjectParent(obj);
+    }
+
+    // If we've got a WN or slim wrapper, store things the way callers expect.
+    // Otherwise, leave things null and return.
+    if (IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
+        if (IS_WN_WRAPPER_OBJECT(obj))
+            *wrapper = (XPCWrappedNative*) js::GetObjectPrivate(obj);
+        else
+            *cur = obj;
+    }
 
     return NS_OK;
 }
 
 nsresult
 castNative(JSContext *cx,
            XPCWrappedNative *wrapper,
            JSObject *cur,