Beispiel #1
0
XPCVariant::XPCVariant(XPCCallContext& ccx, jsval aJSVal)
    : mJSVal(aJSVal)
{
    nsVariant::Initialize(&mData);
    if(!JSVAL_IS_PRIMITIVE(mJSVal))
    {
        JSObject *obj = JSVAL_TO_OBJECT(mJSVal);
        OBJ_TO_INNER_OBJECT(ccx, obj);

        mJSVal = OBJECT_TO_JSVAL(obj);

        // If the incoming object is an XPCWrappedNative, then it could be a
        // double-wrapped object, and we should return the double-wrapped
        // object back out to script.

        JSObject* proto;
        XPCWrappedNative* wn =
            XPCWrappedNative::GetWrappedNativeOfJSObject(ccx,
                    JSVAL_TO_OBJECT(mJSVal),
                    nsnull,
                    &proto);
        mReturnRawObject = !wn && !proto;
    }
    else
        mReturnRawObject = JS_FALSE;
}
static JSObject *
GetScopeFunction(JSContext *cx, JSObject *outerObj)
{
  jsval v;
  if (!JS_GetReservedSlot(cx, outerObj, sScopeFunSlot, &v)) {
    return nsnull;
  }

  JSObject *unsafeObj = GetUnsafeObject(outerObj);
  JSObject *scopeobj = JS_GetGlobalForObject(cx, unsafeObj);
  OBJ_TO_INNER_OBJECT(cx, scopeobj);
  if (!scopeobj) {
    return nsnull;
  }

  if (JSVAL_IS_OBJECT(v)) {
    JSObject *funobj = JSVAL_TO_OBJECT(v);
    if (JS_GetGlobalForObject(cx, funobj) == scopeobj) {
      return funobj;
    }
  }

  JSFunction *fun = JS_NewFunction(cx, DummyNative, 0, 0, scopeobj,
                                   "SJOWContentBoundary");
  if (!fun) {
    return nsnull;
  }

  JSObject *funobj = JS_GetFunctionObject(fun);
  if (!JS_SetReservedSlot(cx, outerObj, sScopeFunSlot, OBJECT_TO_JSVAL(funobj))) {
    return nsnull;
  }

  return funobj;
}
static XPCWrappedNative *
GetWrappedNative(JSContext *cx, JSObject *obj)
{
    OBJ_TO_INNER_OBJECT(cx, obj);
    return IS_WN_WRAPPER(obj)
           ? static_cast<XPCWrappedNative *>(obj->getPrivate())
           : nsnull;
}
JSBool
WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn)
{
  NS_ASSERTION(XPCPerThreadData::IsMainThread(cx),
               "Can't do this off the main thread!");

  // Our argument should be a wrapped native object, but the caller may have
  // passed it in as an optimization.
  JSObject *wrappedObj;
  if (JSVAL_IS_PRIMITIVE(*vp) ||
      !(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
      wrappedObj->getClass() == &XOWClass) {
    return JS_TRUE;
  }

  if (!wn &&
      !(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, wrappedObj))) {
    return JS_TRUE;
  }

  CheckWindow(wn);

  // The parent must be the inner global object for its scope.
  parent = JS_GetGlobalForObject(cx, parent);
  OBJ_TO_INNER_OBJECT(cx, parent);
  if (!parent) {
    return JS_FALSE;
  }

  XPCWrappedNativeWithXOW *wnxow = nsnull;
  if (wn->NeedsXOW()) {
    JSObject *innerWrappedObj = wrappedObj;
    OBJ_TO_INNER_OBJECT(cx, innerWrappedObj);
    if (!innerWrappedObj) {
      return JS_FALSE;
    }

    if (innerWrappedObj == parent) {
      wnxow = static_cast<XPCWrappedNativeWithXOW *>(wn);
      JSObject *xow = wnxow->GetXOW();
      if (xow) {
        *vp = OBJECT_TO_JSVAL(xow);
        return JS_TRUE;
      }
    }
  }

  XPCWrappedNative *parentwn =
    XPCWrappedNative::GetWrappedNativeOfJSObject(cx, parent);
  XPCWrappedNativeScope *parentScope;
  if (NS_LIKELY(parentwn)) {
    parentScope = parentwn->GetScope();
  } else {
    parentScope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent);
  }

  JSObject *outerObj = nsnull;
  WrappedNative2WrapperMap *map = parentScope->GetWrapperMap();

  outerObj = map->Find(wrappedObj);
  if (outerObj) {
    NS_ASSERTION(outerObj->getClass() == &XOWClass,
                 "What crazy object are we getting here?");
    *vp = OBJECT_TO_JSVAL(outerObj);

    if (wnxow) {
      // NB: wnxow->GetXOW() must have returned false.
      SetFlags(cx, outerObj, AddFlags(GetFlags(cx, outerObj), FLAG_IS_CACHED));
      wnxow->SetXOW(outerObj);
    }

    return JS_TRUE;
  }

  outerObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull,
                                        parent);
  if (!outerObj) {
    return JS_FALSE;
  }

  jsval flags = INT_TO_JSVAL(wnxow ? FLAG_IS_CACHED : 0);
  if (!JS_SetReservedSlot(cx, outerObj, sWrappedObjSlot, *vp) ||
      !JS_SetReservedSlot(cx, outerObj, sFlagsSlot, flags) ||
      !JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot,
                          PRIVATE_TO_JSVAL(parentScope))) {
    return JS_FALSE;
  }

  *vp = OBJECT_TO_JSVAL(outerObj);

  map->Add(wn->GetScope()->GetWrapperMap(), wrappedObj, outerObj);
  if(wnxow) {
    wnxow->SetXOW(outerObj);
  }

  return JS_TRUE;
}
// Returns whether the currently executing code is allowed to access
// the wrapper.  Uses nsIPrincipal::Subsumes.
// |cx| must be the top context on the context stack.
// If the subject is allowed to access the object returns NS_OK. If not,
// returns NS_ERROR_DOM_PROP_ACCESS_DENIED, returns another error code on
// failure.
nsresult
CanAccessWrapper(JSContext *cx, JSObject *outerObj, JSObject *wrappedObj,
                 JSBool *privilegeEnabled)
{
  // Fast path: If the wrapper and the wrapped object have the same global
  // object (or if the wrapped object is a outer for the same inner that
  // the wrapper is parented to), then we don't need to do any more work.

  if (privilegeEnabled) {
    *privilegeEnabled = JS_FALSE;
  }

  if (outerObj) {
    JSObject *outerParent = outerObj->getParent();
    JSObject *innerParent = wrappedObj->getParent();
    if (!innerParent) {
      innerParent = wrappedObj;
      OBJ_TO_INNER_OBJECT(cx, innerParent);
      if (!innerParent) {
        return NS_ERROR_FAILURE;
      }
    } else {
      innerParent = JS_GetGlobalForObject(cx, innerParent);
    }

    if (outerParent == innerParent) {
      return NS_OK;
    }
  }

  // TODO bug 508928: Refactor this with the XOW security checking code.
  // Get the subject principal from the execution stack.
  nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
  if (!ssm) {
    ThrowException(NS_ERROR_NOT_INITIALIZED, cx);
    return NS_ERROR_NOT_INITIALIZED;
  }

  JSStackFrame *fp = nsnull;
  nsIPrincipal *subjectPrin = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp);

  if (!subjectPrin) {
    ThrowException(NS_ERROR_FAILURE, cx);
    return NS_ERROR_FAILURE;
  }

  PRBool isSystem = PR_FALSE;
  nsresult rv = ssm->IsSystemPrincipal(subjectPrin, &isSystem);
  NS_ENSURE_SUCCESS(rv, rv);

  if (privilegeEnabled) {
    *privilegeEnabled = JS_FALSE;
  }

  nsCOMPtr<nsIPrincipal> objectPrin;
  rv = ssm->GetObjectPrincipal(cx, wrappedObj, getter_AddRefs(objectPrin));
  if (NS_FAILED(rv)) {
    return rv;
  }
  NS_ASSERTION(objectPrin, "Object didn't have principals?");

  // Micro-optimization: don't call into caps if we know the answer.
  if (subjectPrin == objectPrin) {
    return NS_OK;
  }

  // Now, we have our two principals, compare them!
  PRBool subsumes;
  rv = subjectPrin->Subsumes(objectPrin, &subsumes);
  if (NS_SUCCEEDED(rv) && !subsumes) {
    // We're about to fail, but make a last effort to see if
    // UniversalXPConnect was enabled anywhere else on the stack.
    rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isSystem);
    if (NS_SUCCEEDED(rv) && isSystem) {
      rv = NS_OK;
      if (privilegeEnabled) {
        *privilegeEnabled = JS_TRUE;
      }
    } else {
      rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
    }
  }
  return rv;
}