예제 #1
0
NS_IMETHODIMP
MobileMessageManager::Delete(const JS::Value& aParam, nsIDOMDOMRequest** aRequest)
{
  if (aParam.isInt32()) {
    return Delete(aParam.toInt32(), aRequest);
  }

  if (!aParam.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }

  nsresult rv;
  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  AutoPushJSContext cx(sc->GetNativeContext());
  NS_ENSURE_STATE(sc);

  int32_t id;
  nsCOMPtr<nsIDOMMozSmsMessage> smsMessage =
    do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, &aParam.toObject()));
  if (smsMessage) {
    smsMessage->GetId(&id);
  } else {
    nsCOMPtr<nsIDOMMozMmsMessage> mmsMessage =
      do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, &aParam.toObject()));
    if (mmsMessage) {
      mmsMessage->GetId(&id);
    } else {
      return NS_ERROR_INVALID_ARG;
    }
  }

  return Delete(id, aRequest);
}
예제 #2
0
NS_IMETHODIMP
nsScreen::MozLockOrientation(const JS::Value& aOrientation, JSContext* aCx,
                             bool* aReturn)
{
  if (aOrientation.isObject() && IsArrayLike(aCx, &aOrientation.toObject())) {
    JSObject* seq = &aOrientation.toObject();
    uint32_t length;
    // JS_GetArrayLength actually works on all objects
    if (!JS_GetArrayLength(aCx, seq, &length)) {
      return NS_ERROR_FAILURE;
    }

    Sequence<nsString> orientations;
    if (!orientations.SetCapacity(length)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    for (uint32_t i = 0; i < length; ++i) {
      JS::Value temp;
      if (!JS_GetElement(aCx, seq, i, &temp)) {
        return NS_ERROR_FAILURE;
      }

      js::RootedString jsString(aCx, JS_ValueToString(aCx, temp));
      if (!jsString) {
        return NS_ERROR_FAILURE;
      }

      nsDependentJSString str;
      if (!str.init(aCx, jsString)) {
        return NS_ERROR_FAILURE;
      }

      *orientations.AppendElement() = str;
    }

    ErrorResult rv;
    *aReturn = MozLockOrientation(orientations, rv);
    return rv.ErrorCode();
  }

  js::RootedString jsString(aCx, JS_ValueToString(aCx, aOrientation));
  if (!jsString) {
    return NS_ERROR_FAILURE;
  }

  nsDependentJSString orientation;
  if (!orientation.init(aCx, jsString)) {
    return NS_ERROR_FAILURE;
  }

  ErrorResult rv;
  *aReturn = MozLockOrientation(orientation, rv);
  return rv.ErrorCode();
}
예제 #3
0
void
nsGeolocationService::HandleMozsettingChanged(const PRUnichar* aData)
{
    // The string that we're interested in will be a JSON string that looks like:
    //  {"key":"gelocation.enabled","value":true}

    SafeAutoJSContext cx;

    nsDependentString dataStr(aData);
    JS::Value val;
    if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) || !val.isObject()) {
      return;
    }

    JSObject &obj(val.toObject());
    JS::Value key;
    if (!JS_GetProperty(cx, &obj, "key", &key) || !key.isString()) {
      return;
    }

    JSBool match;
    if (!JS_StringEqualsAscii(cx, key.toString(), GEO_SETINGS_ENABLED, &match) || (match != JS_TRUE)) {
      return;
    }

    JS::Value value;
    if (!JS_GetProperty(cx, &obj, "value", &value) || !value.isBoolean()) {
      return;
    }

    HandleMozsettingValue(value.toBoolean());
}
NS_IMETHODIMP
TCPSocketChild::Send(const JS::Value& aData,
                     uint32_t aByteOffset,
                     uint32_t aByteLength,
                     JSContext* aCx)
{
  if (aData.isString()) {
    JSString* jsstr = aData.toString();
    nsDependentJSString str;
    bool ok = str.init(aCx, jsstr);
    NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
    SendData(str);

  } else {
    NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_FAILURE);
    JS::Rooted<JSObject*> obj(aCx, &aData.toObject());
    NS_ENSURE_TRUE(JS_IsArrayBufferObject(obj), NS_ERROR_FAILURE);
    uint32_t buflen = JS_GetArrayBufferByteLength(obj);
    aByteOffset = std::min(buflen, aByteOffset);
    uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
    uint8_t* data = JS_GetArrayBufferData(obj);
    if (!data) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
    FallibleTArray<uint8_t> fallibleArr;
    if (!fallibleArr.InsertElementsAt(0, data, nbytes)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
    InfallibleTArray<uint8_t> arr;
    arr.SwapElements(fallibleArr);
    SendData(arr);
  }
  return NS_OK;
}
예제 #5
0
NS_IMETHODIMP
TCPSocketParent::InitJS(const JS::Value& aIntermediary, JSContext* aCx)
{
  MOZ_ASSERT(aIntermediary.isObject());
  mIntermediaryObj = &aIntermediary.toObject();
  return NS_OK;
}
// Helper for weighted regions.
nsresult
CameraControlImpl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
{
  if (aLimit == 0) {
    DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
    return NS_OK;
  }

  if (!aValue.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }

  uint32_t length = 0;

  JSObject* regions = &aValue.toObject();
  if (!JS_GetArrayLength(aCx, regions, &length)) {
    return NS_ERROR_FAILURE;
  }

  DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
  if (length > aLimit) {
    length = aLimit;
  }

  nsTArray<CameraRegion> regionArray;
  regionArray.SetCapacity(length);

  for (uint32_t i = 0; i < length; ++i) {
    JS::Value v;

    if (!JS_GetElement(aCx, regions, i, &v)) {
      return NS_ERROR_FAILURE;
    }

    CameraRegion* r = regionArray.AppendElement();
    /**
     * These are the default values.  We can remove these when the xpidl
     * dictionary parser gains the ability to grok default values.
     */
    r->top = -1000;
    r->left = -1000;
    r->bottom = 1000;
    r->right = 1000;
    r->weight = 1000;

    nsresult rv = r->Init(aCx, &v);
    NS_ENSURE_SUCCESS(rv, rv);

    DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n",
      i,
      r->top,
      r->left,
      r->bottom,
      r->right,
      r->weight
    );
  }
  SetParameter(aKey, regionArray);
  return NS_OK;
}
예제 #7
0
JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
{
    const char src[] =
        "function f() { return 1; }\n"
        "f;\n";

    js::RootedObject global(cx, JS_GetGlobalObject(cx));
    JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
                                                               src, strlen(src), "test", 1,
                                                               JSVERSION_DEFAULT);
    if (!script)
        return NULL;

    if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
        script = FreezeThaw(cx, script);
        if (!script)
            return NULL;
        if (testCase == TEST_SCRIPT)
            return script;
    }

    JS::Value v;
    JSBool ok = JS_ExecuteScript(cx, global, script, &v);
    if (!ok || !v.isObject())
        return NULL;
    js::RootedObject funobj(cx, &v.toObject());
    if (testCase == TEST_FUNCTION) {
        funobj = FreezeThaw(cx, funobj);
        if (!funobj)
            return NULL;
    }
    return GetScript(cx, funobj);
}
// static
JSObject*
DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
{
    MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
    JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
    if (v.isUndefined()) {
        return nullptr;
    }

    if (v.isObject()) {
        js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue());
        xpc::GetObjectScope(obj)->RemoveDOMExpandoObject(obj);
    } else {
        js::ExpandoAndGeneration* expandoAndGeneration =
            static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
        v = expandoAndGeneration->expando;
        if (v.isUndefined()) {
            return nullptr;
        }
        expandoAndGeneration->expando = UndefinedValue();
    }


    return &v.toObject();
}
예제 #9
0
nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object)
{
    if (!object.isObject())
        return NS_OK;

    JS::RootedObject obj(cx, &object.toObject());

    XPCCallContext ccx(NATIVE_CALLER, cx);

    // See if the object is a wrapped native that supports weak references.
    nsISupports* supports =
        nsXPConnect::XPConnect()->GetNativeOfWrapper(cx, obj);
    nsCOMPtr<nsISupportsWeakReference> supportsWeakRef =
        do_QueryInterface(supports);
    if (supportsWeakRef) {
        supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent));
        if (mReferent) {
            return NS_OK;
        }
    }
    // If it's not a wrapped native, or it is a wrapped native that does not
    // support weak references, fall back to getting a weak ref to the object.

    // See if object is a wrapped JSObject.
    nsRefPtr<nsXPCWrappedJS> wrapped;
    nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj,
                                               NS_GET_IID(nsISupports),
                                               getter_AddRefs(wrapped));
    if (!wrapped) {
        NS_ERROR("can't get nsISupportsWeakReference wrapper for obj");
        return rv;
    }

    return wrapped->GetWeakReference(getter_AddRefs(mReferent));
}
예제 #10
0
Promise*
WrapperPromiseCallback::GetDependentPromise()
{
  // Per spec, various algorithms like all() and race() are actually implemented
  // in terms of calling then() but passing it the resolve/reject functions that
  // are passed as arguments to function passed to the Promise constructor.
  // That will cause the promise in question to hold on to a
  // WrapperPromiseCallback, but the dependent promise should really be the one
  // whose constructor those functions came from, not the about-to-be-ignored
  // return value of "then".  So try to determine whether we're in that case and
  // if so go ahead and dig the dependent promise out of the function we have.
  JSObject* callable = mCallback->Callable();
  // Unwrap it, in case it's a cross-compartment wrapper.  Our caller here is
  // system, so it's really ok to just go and unwrap.
  callable = js::UncheckedUnwrap(callable);
  if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
    JS::Value promiseVal =
      js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
    Promise* promise;
    UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
    return promise;
  }

  if (mNextPromise) {
    return mNextPromise;
  }

  Promise* promise;
  if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
    return promise;
  }

  // Oh, well.
  return nullptr;
}
예제 #11
0
NS_IMETHODIMP
SmsManager::Send(const JS::Value& aNumber, const nsAString& aMessage, JS::Value* aReturn)
{
  nsresult rv;
  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  NS_ENSURE_STATE(sc);
  AutoPushJSContext cx(sc->GetNativeContext());
  NS_ASSERTION(cx, "Failed to get a context!");

  if (!aNumber.isString() &&
      !(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) {
    return NS_ERROR_INVALID_ARG;
  }

  JSObject* global = sc->GetNativeGlobal();
  NS_ASSERTION(global, "Failed to get global object!");

  JSAutoRequest ar(cx);
  JSAutoCompartment ac(cx, global);

  if (aNumber.isString()) {
    return Send(cx, global, aNumber.toString(), aMessage, aReturn);
  }

  // Must be an array then.
  JSObject& numbers = aNumber.toObject();

  uint32_t size;
  JS_ALWAYS_TRUE(JS_GetArrayLength(cx, &numbers, &size));

  JS::Value* requests = new JS::Value[size];

  for (uint32_t i=0; i<size; ++i) {
    JS::Value number;
    if (!JS_GetElement(cx, &numbers, i, &number)) {
      return NS_ERROR_INVALID_ARG;
    }

    nsresult rv = Send(cx, global, number.toString(), aMessage, &requests[i]);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  aReturn->setObjectOrNull(JS_NewArrayObject(cx, size, requests));
  NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE);

  return NS_OK;
}
NS_IMETHODIMP
TimeZoneSettingObserver::Observe(nsISupports *aSubject,
                     const char *aTopic,
                     const PRUnichar *aData)
{
  if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
    return NS_OK;
  }

  // Note that this function gets called for any and all settings changes,
  // so we need to carefully check if we have the one we're interested in.
  //
  // The string that we're interested in will be a JSON string that looks like:
  // {"key":"time.timezone","value":"America/Chicago"}

  // Get the safe JS context.
  nsCOMPtr<nsIThreadJSContextStack> stack =
    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
  if (!stack) {
    ERR("Failed to get JSContextStack");
    return NS_OK;
  }
  JSContext *cx = stack->GetSafeJSContext();
  if (!cx) {
    ERR("Failed to GetSafeJSContext");
    return NS_OK;
  }

  // Parse the JSON value.
  nsDependentString dataStr(aData);
  JS::Value val;
  if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
      !val.isObject()) {
    return NS_OK;
  }

  // Get the key, which should be the JS string "time.timezone".
  JSObject &obj(val.toObject());
  JS::Value key;
  if (!JS_GetProperty(cx, &obj, "key", &key) ||
      !key.isString()) {
    return NS_OK;
  }
  JSBool match;
  if (!JS_StringEqualsAscii(cx, key.toString(), TIME_TIMEZONE, &match) ||
      match != JS_TRUE) {
    return NS_OK;
  }

  // Get the value, which should be a JS string like "America/Chicago".
  JS::Value value;
  if (!JS_GetProperty(cx, &obj, "value", &value) ||
      !value.isString()) {
    return NS_OK;
  }

  // Set the system timezone.
  return SetTimeZone(value, cx);
}
bool
ValueHasISupportsPrivate(const JS::Value &v)
{
  if (!v.isObject()) {
    return false;
  }

  const DOMClass* domClass = GetDOMClass(&v.toObject());
  if (domClass) {
    return domClass->mDOMObjectIsISupports;
  }

  JSClass* clasp = ::JS_GetClass(&v.toObject());
  const uint32_t HAS_PRIVATE_NSISUPPORTS =
    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS;
  return (clasp->flags & HAS_PRIVATE_NSISUPPORTS) == HAS_PRIVATE_NSISUPPORTS;
}
예제 #14
0
nsresult
nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
                       nsJSONWriter* writer)
{
  JSAutoRequest ar(cx);

  // Backward compatibility:
  // nsIJSON does not allow to serialize anything other than objects
  if (!aValue.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }

  JSObject* obj = &aValue.toObject();

  JS::Value val = aValue;

  /* Backward compatibility:
   * Manually call toJSON if implemented by the object and check that
   * the result is still an object
   * Note: It is perfectly fine to not implement toJSON, so it is
   * perfectly fine for GetMethod to fail
   */
  JS::Value toJSON;
  if (JS_GetMethod(cx, obj, "toJSON", NULL, &toJSON) &&
      !JSVAL_IS_PRIMITIVE(toJSON) &&
      JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(toJSON))) {
    // If toJSON is implemented, it must not throw
    if (!JS_CallFunctionValue(cx, obj, toJSON, 0, NULL, &val)) {
      if (JS_IsExceptionPending(cx))
        // passing NS_OK will throw the pending exception
        return NS_OK;

      // No exception, but still failed
      return NS_ERROR_FAILURE;
    }

    // Backward compatibility:
    // nsIJSON does not allow to serialize anything other than objects
    if (JSVAL_IS_PRIMITIVE(val))
      return NS_ERROR_INVALID_ARG;
  }
  // GetMethod may have thrown
  else if (JS_IsExceptionPending(cx))
    // passing NS_OK will throw the pending exception
    return NS_OK;

  // Backward compatibility:
  // function shall not pass, just "plain" objects and arrays
  JSType type = JS_TypeOfValue(cx, val);
  if (type == JSTYPE_FUNCTION)
    return NS_ERROR_INVALID_ARG;

  // We're good now; try to stringify
  if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, WriteCallback, writer))
    return NS_ERROR_FAILURE;

  return NS_OK;
}
예제 #15
0
//static
JSObject *
DOMProxyHandler::GetExpandoObject(JSObject *obj)
{
  MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
  JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
  if (v.isObject()) {
    return &v.toObject();
  }

  if (v.isUndefined()) {
    return nullptr;
  }

  js::ExpandoAndGeneration* expandoAndGeneration =
    static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
  v = expandoAndGeneration->expando;
  return v.isUndefined() ? nullptr : &v.toObject();
}
예제 #16
0
NS_IMETHODIMP
nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, uint32_t* aRetVal)
{
  if (!mAudioStream) {
    return NS_ERROR_DOM_INVALID_STATE_ERR;
  }

  if (!aData.isObject()) {
    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
  }

  JSObject* darray = &aData.toObject();
  JS::AutoObjectRooter tvr(aCx);
  JSObject* tsrc = NULL;

  // Allow either Float32Array or plain JS Array
  if (JS_IsFloat32Array(darray)) {
    tsrc = darray;
  } else if (JS_IsArrayObject(aCx, darray)) {
    JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray);
    if (!nobj) {
      return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
    }
    tsrc = nobj;
  } else {
    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
  }
  tvr.setObject(tsrc);

  uint32_t dataLength = JS_GetTypedArrayLength(tsrc);

  // Make sure that we are going to write the correct amount of data based
  // on number of channels.
  if (dataLength % mChannels != 0) {
    return NS_ERROR_DOM_INDEX_SIZE_ERR;
  }

  // Don't write more than can be written without blocking.
  uint32_t writeLen = std::min(mAudioStream->Available(), dataLength / mChannels);

  float* frames = JS_GetFloat32ArrayData(tsrc);
  // Convert the samples back to integers as we are using fixed point audio in
  // the AudioStream.
  // This could be optimized to avoid allocation and memcpy when
  // AudioDataValue is 'float', but it's not worth it for this deprecated API.
  nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[writeLen * mChannels]);
  ConvertAudioSamples(frames, audioData.get(), writeLen * mChannels);
  nsresult rv = mAudioStream->Write(audioData.get(), writeLen);

  if (NS_FAILED(rv)) {
    return rv;
  }

  // Return the actual amount written.
  *aRetVal = writeLen * mChannels;
  return rv;
}
예제 #17
0
// JS-to-native helpers
// Setter for weighted regions: { top, bottom, left, right, weight }
nsresult
nsDOMCameraControl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
{
  if (aLimit == 0) {
    DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
    return NS_OK;
  }

  if (!aValue.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }

  uint32_t length = 0;

  JS::Rooted<JSObject*> regions(aCx, &aValue.toObject());
  if (!JS_GetArrayLength(aCx, regions, &length)) {
    return NS_ERROR_FAILURE;
  }

  DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
  if (length > aLimit) {
    length = aLimit;
  }

  nsTArray<ICameraControl::Region> regionArray;
  regionArray.SetCapacity(length);

  for (uint32_t i = 0; i < length; ++i) {
    JS::Rooted<JS::Value> v(aCx);

    if (!JS_GetElement(aCx, regions, i, &v)) {
      return NS_ERROR_FAILURE;
    }

    CameraRegion region;
    if (!region.Init(aCx, v)) {
      return NS_ERROR_FAILURE;
    }

    ICameraControl::Region* r = regionArray.AppendElement();
    r->top = region.mTop;
    r->left = region.mLeft;
    r->bottom = region.mBottom;
    r->right = region.mRight;
    r->weight = region.mWeight;

    DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%u\n",
      i,
      r->top,
      r->left,
      r->bottom,
      r->right,
      r->weight
    );
  }
  return mCameraControl->Set(aKey, regionArray);
}
nsresult
MobileMessageManager::GetMessageId(AutoPushJSContext &aCx,
                                   const JS::Value &aMessage, int32_t &aId)
{
  nsCOMPtr<nsIDOMMozSmsMessage> smsMessage =
    do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &aMessage.toObject()));
  if (smsMessage) {
    return smsMessage->GetId(&aId);
  }

  nsCOMPtr<nsIDOMMozMmsMessage> mmsMessage =
    do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &aMessage.toObject()));
  if (mmsMessage) {
    return mmsMessage->GetId(&aId);
  }

  return NS_ERROR_INVALID_ARG;
}
예제 #19
0
std::string
gjs_debug_value(JS::Value v)
{
    std::ostringstream out;
    if (v.isNull())
        return "null";
    if (v.isUndefined())
        return "undefined";
    if (v.isInt32()) {
        out << v.toInt32();
        return out.str();
    }
    if (v.isDouble()) {
        out << v.toDouble();
        return out.str();
    }
    if (v.isString()) {
        out << gjs_debug_string(v.toString());
        return out.str();
    }
    if (v.isSymbol()) {
        out << gjs_debug_symbol(v.toSymbol());
        return out.str();
    }
    if (v.isObject() && js::IsFunctionObject(&v.toObject())) {
        JSFunction* fun = JS_GetObjectFunction(&v.toObject());
        JSString *display_name = JS_GetFunctionDisplayId(fun);
        if (display_name)
            out << "<function " << gjs_debug_string(display_name);
        else
            out << "<unnamed function";
        out << " at " << fun << '>';
        return out.str();
    }
    if (v.isObject()) {
        out << gjs_debug_object(&v.toObject());
        return out.str();
    }
    if (v.isBoolean())
        return (v.toBoolean() ? "true" : "false");
    if (v.isMagic())
        return "<magic>";
    return "unexpected value";
}
예제 #20
0
nsresult 
nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
                                  nsIScriptContext* aContext, 
                                  nsIContent* aBoundElement, 
                                  nsIXPConnectJSObjectHolder** aScriptObjectHolder, 
                                  JS::MutableHandle<JSObject*> aTargetClassObject,
                                  bool* aTargetIsNew)
{
  nsresult rv = NS_OK;
  *aScriptObjectHolder = nullptr;
  
  if (!mClassObject) {
    rv = CompilePrototypeMembers(aBinding); // This is the first time we've ever installed this binding on an element.
                                 // We need to go ahead and compile all methods and properties on a class
                                 // in our prototype binding.
    if (NS_FAILED(rv))
      return rv;

    MOZ_ASSERT(mClassObject);
  }

  nsIDocument *ownerDoc = aBoundElement->OwnerDoc();
  nsIGlobalObject *sgo;

  if (!(sgo = ownerDoc->GetScopeObject())) {
    return NS_ERROR_UNEXPECTED;
  }

  // Because our prototype implementation has a class, we need to build up a corresponding
  // class for the concrete implementation in the bound document.
  AutoPushJSContext cx(aContext->GetNativeContext());
  JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
  nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
  JS::Value v;
  rv = nsContentUtils::WrapNative(cx, global, aBoundElement, &v,
                                  getter_AddRefs(wrapper));
  NS_ENSURE_SUCCESS(rv, rv);

  JS::Rooted<JSObject*> value(cx, &v.toObject());

  // All of the above code was just obtaining the bound element's script object and its immediate
  // concrete base class.  We need to alter the object so that our concrete class is interposed
  // between the object and its base class.  We become the new base class of the object, and the
  // object's old base class becomes the new class' base class.
  rv = aBinding->InitClass(mClassName, cx, global, value, aTargetClassObject, aTargetIsNew);
  if (NS_FAILED(rv)) {
    return rv;
  }

  nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement);

  wrapper.swap(*aScriptObjectHolder);
  
  return rv;
}
예제 #21
0
// static
JSObject* DOMProxyHandler::GetExpandoObject(JSObject* obj) {
  CheckDOMProxy(obj);

  JS::Value v = js::GetProxyPrivate(obj);
  if (v.isObject()) {
    CheckExpandoObject(obj, v);
    return &v.toObject();
  }

  if (v.isUndefined()) {
    return nullptr;
  }

  js::ExpandoAndGeneration* expandoAndGeneration =
      static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
  CheckExpandoAndGeneration(obj, expandoAndGeneration);

  v = expandoAndGeneration->expando;
  return v.isUndefined() ? nullptr : &v.toObject();
}
예제 #22
0
nsresult
nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
                       nsJSONWriter* writer)
{
    // Backward compatibility:
    // nsIJSON does not allow to serialize anything other than objects
    if (!aValue.isObject()) {
        return NS_ERROR_INVALID_ARG;
    }
    JS::Rooted<JSObject*> obj(cx, &aValue.toObject());

    /* Backward compatibility:
     * Manually call toJSON if implemented by the object and check that
     * the result is still an object
     * Note: It is perfectly fine to not implement toJSON, so it is
     * perfectly fine for GetMethod to fail
     */
    JS::Rooted<JS::Value> val(cx, aValue);
    JS::Rooted<JS::Value> toJSON(cx);
    if (JS_GetProperty(cx, obj, "toJSON", &toJSON) &&
            toJSON.isObject() &&
            JS_ObjectIsCallable(cx, &toJSON.toObject())) {
        // If toJSON is implemented, it must not throw
        if (!JS_CallFunctionValue(cx, obj, toJSON, JS::HandleValueArray::empty(), &val)) {
            if (JS_IsExceptionPending(cx))
                // passing NS_OK will throw the pending exception
                return NS_OK;

            // No exception, but still failed
            return NS_ERROR_FAILURE;
        }

        // Backward compatibility:
        // nsIJSON does not allow to serialize anything other than objects
        if (val.isPrimitive())
            return NS_ERROR_INVALID_ARG;
    }
    // GetMethod may have thrown
    else if (JS_IsExceptionPending(cx))
        // passing NS_OK will throw the pending exception
        return NS_OK;

    // Backward compatibility:
    // function shall not pass, just "plain" objects and arrays
    JSType type = JS_TypeOfValue(cx, val);
    if (type == JSTYPE_FUNCTION)
        return NS_ERROR_INVALID_ARG;

    // We're good now; try to stringify
    if (!JS_Stringify(cx, &val, JS::NullPtr(), JS::NullHandleValue, WriteCallback, writer))
        return NS_ERROR_FAILURE;

    return NS_OK;
}
예제 #23
0
/**
 * Constraints look like this:
 *
 * {
 *    "mandatory": {"foo":"hello", "bar": false, "baz": 10},
 *    "optional": [{"hello":"foo"}, {"baz": false}]
 * }
 *
 * Optional constraints are ordered, and hence in an array. This function
 * converts a jsval that looks like the above into a MediaConstraints object.
 */
nsresult
PeerConnectionImpl::ConvertConstraints(
  const JS::Value& aConstraints, MediaConstraints* aObj, JSContext* aCx)
{
  size_t i;
  jsval mandatory, optional;
  JSObject& constraints = aConstraints.toObject();

  // Mandatory constraints.
  if (JS_GetProperty(aCx, &constraints, "mandatory", &mandatory)) {
    if (mandatory.isObject()) {
      JSObject* opts = JSVAL_TO_OBJECT(mandatory);
      JS::AutoIdArray mandatoryOpts(aCx, JS_Enumerate(aCx, opts));

      // Iterate over each property.
      for (i = 0; i < mandatoryOpts.length(); i++) {
        jsval option, optionName;
        if (JS_GetPropertyById(aCx, opts, mandatoryOpts[i], &option)) {
          if (JS_IdToValue(aCx, mandatoryOpts[i], &optionName)) {
            // We only support boolean constraints for now.
            if (JSVAL_IS_BOOLEAN(option)) {
              JSString* optionNameString = JS_ValueToString(aCx, optionName);
              NS_ConvertUTF16toUTF8 stringVal(JS_GetStringCharsZ(aCx, optionNameString));
              aObj->setBooleanConstraint(stringVal.get(), JSVAL_TO_BOOLEAN(option), true);
            }
          }
        }
      }
    }
  }

  // Optional constraints.
  if (JS_GetProperty(aCx, &constraints, "optional", &optional)) {
    if (optional.isObject()) {
      JSObject* opts = JSVAL_TO_OBJECT(optional);
      if (JS_IsArrayObject(aCx, opts)) {
        uint32_t length;
        if (!JS_GetArrayLength(aCx, opts, &length)) {
          return NS_ERROR_FAILURE;
        }
        for (i = 0; i < length; i++) {
          jsval val;
          JS_GetElement(aCx, opts, i, &val);
          if (val.isObject()) {
            // Extract name & value and store.
            // FIXME: MediaConstraints does not support optional constraints?
          }
        }
      }
    }
  }

  return NS_OK;
}
예제 #24
0
Promise*
GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
{
  JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc, SLOT_PROMISE);

  MOZ_ASSERT(promiseVal.isObject());

  Promise* promise;
  UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
  return promise;
}
NS_IMETHODIMP
AutoMounterSetting::Observe(nsISupports* aSubject,
                            const char* aTopic,
                            const PRUnichar* aData)
{
  if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
    return NS_OK;
  }

  // Note that this function gets called for any and all settings changes,
  // so we need to carefully check if we have the one we're interested in.
  //
  // The string that we're interested in will be a JSON string that looks like:
  //  {"key":"ums.autoMount","value":true}

  nsCOMPtr<nsIThreadJSContextStack> stack =
    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
  if (!stack) {
    ERR("Failed to get JSContextStack");
    return NS_OK;
  }
  JSContext* cx = stack->GetSafeJSContext();
  if (!cx) {
    ERR("Failed to GetSafeJSContext");
    return NS_OK;
  }
  nsDependentString dataStr(aData);
  JS::Value val;
  if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
      !val.isObject()) {
    return NS_OK;
  }
  JSObject& obj(val.toObject());
  JS::Value key;
  if (!JS_GetProperty(cx, &obj, "key", &key) ||
      !key.isString()) {
    return NS_OK;
  }
  JSBool match;
  if (!JS_StringEqualsAscii(cx, key.toString(), UMS_MODE, &match) ||
      (match != JS_TRUE)) {
    return NS_OK;
  }
  JS::Value value;
  if (!JS_GetProperty(cx, &obj, "value", &value) ||
      !value.isInt32()) {
    return NS_OK;
  }
  int32_t mode = value.toInt32();
  SetAutoMounterMode(mode);

  return NS_OK;
}
예제 #26
0
JSObject*
XPCWrappedNativeScope::EnsureXBLScope(JSContext *cx)
{
    JSObject *global = GetGlobalJSObject();
    MOZ_ASSERT(js::IsObjectInContextCompartment(global, cx));
    MOZ_ASSERT(!mIsXBLScope);
    MOZ_ASSERT(strcmp(js::GetObjectClass(global)->name,
                      "nsXBLPrototypeScript compilation scope"));

    // If we already have a special XBL scope object, we know what to use.
    if (mXBLScope)
        return mXBLScope;

    // If this scope doesn't need an XBL scope, just return the global.
    if (!mUseXBLScope)
        return global;

    // Set up the sandbox options. Note that we use the DOM global as the
    // sandboxPrototype so that the XBL scope can access all the DOM objects
    // it's accustomed to accessing.
    //
    // NB: One would think that wantXrays wouldn't make a difference here.
    // However, wantXrays lives a secret double life, and one of its other
    // hobbies is to waive Xray on the returned sandbox when set to false.
    // So make sure to keep this set to true, here.
    SandboxOptions options;
    options.wantXrays = true;
    options.wantComponents = true;
    options.wantXHRConstructor = false;
    options.proto = global;
    options.sameZoneAs = global;

    // Use an nsExpandedPrincipal to create asymmetric security.
    nsIPrincipal *principal = GetPrincipal();
    nsCOMPtr<nsIExpandedPrincipal> ep;
    MOZ_ASSERT(!(ep = do_QueryInterface(principal)));
    nsTArray< nsCOMPtr<nsIPrincipal> > principalAsArray(1);
    principalAsArray.AppendElement(principal);
    ep = new nsExpandedPrincipal(principalAsArray);

    // Create the sandbox.
    JSAutoRequest ar(cx);
    JS::Value v = JS::UndefinedValue();
    nsresult rv = xpc_CreateSandboxObject(cx, &v, ep, options);
    NS_ENSURE_SUCCESS(rv, nullptr);
    mXBLScope = &v.toObject();

    // Tag it.
    EnsureCompartmentPrivate(js::UnwrapObject(mXBLScope))->scope->mIsXBLScope = true;

    // Good to go!
    return mXBLScope;
}
NS_IMETHODIMP
TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal *aSocket,
                          const JS::Value& aWindowObj,
                          JSContext* aCx)
{
  mSocket = aSocket;
  MOZ_ASSERT(aWindowObj.isObject());
  mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
  if (!mWindowObj) {
    return NS_ERROR_FAILURE;
  }
  return NS_OK;
}
nsresult
DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
                                      JSContext* aCx,
                                      const JS::Value& aValue)
{
  RefPtr<EventHandlerNonNull> handler;
  JS::Rooted<JSObject*> callable(aCx);
  if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
    handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal());
  }
  SetEventHandler(aType, EmptyString(), handler);
  return NS_OK;
}
예제 #29
0
void
nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVal)
{
  if (!aVal.isObject()) {
    return;
  }

  // clear the list of apps that are always precise
  mAlwaysPreciseApps.Clear();

  // root the object and get the global
  JS::Rooted<JSObject*> obj(nsContentUtils::RootingCx(), &aVal.toObject());
  MOZ_ASSERT(obj);
  nsIGlobalObject* global = xpc::NativeGlobal(obj);
  NS_ENSURE_TRUE_VOID(global && global->GetGlobalJSObject());

  // the spec requires calling getters when accessing array by index
  AutoEntryScript aes(global, "geolocation.always_precise indexing");
  aes.TakeOwnershipOfErrorReporting();
  JSContext *cx = aes.cx();

  if (!JS_IsArrayObject(cx, obj)) {
    return;
  }

  uint32_t length;
  if (!JS_GetArrayLength(cx, obj, &length)) {
    return;
  }

  // process the list of apps...
  for (uint32_t i = 0; i < length; ++i) {
    JS::RootedValue value(cx);

    if (!JS_GetElement(cx, obj, i, &value) || !value.isString()) {
      continue;
    }

    nsAutoJSString origin;
    if (!origin.init(cx, value)) {
      continue;
    }

    GPSLOG("adding always precise for %s", NS_ConvertUTF16toUTF8(origin).get());

    // add the origin to the list of apps that will always receive
    // precise location information
    mAlwaysPreciseApps.AppendElement(origin);
  }
}
예제 #30
0
NS_IMETHODIMP
nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint32* aRetVal)
{
    if (!mAudioStream) {
        return NS_ERROR_DOM_INVALID_STATE_ERR;
    }

    if (!aData.isObject()) {
        return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
    }

    JSObject* darray = &aData.toObject();
    JS::AutoObjectRooter tvr(aCx);
    JSObject* tsrc = NULL;

    // Allow either Float32Array or plain JS Array
    if (JS_IsFloat32Array(darray, aCx)) {
        tsrc = darray;
    } else if (JS_IsArrayObject(aCx, darray)) {
        JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray);
        if (!nobj) {
            return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
        }
        tsrc = nobj;
    } else {
        return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
    }
    tvr.setObject(tsrc);

    PRUint32 dataLength = JS_GetTypedArrayLength(tsrc, aCx);

    // Make sure that we are going to write the correct amount of data based
    // on number of channels.
    if (dataLength % mChannels != 0) {
        return NS_ERROR_DOM_INDEX_SIZE_ERR;
    }

    // Don't write more than can be written without blocking.
    PRUint32 writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels);

    nsresult rv = mAudioStream->Write(JS_GetFloat32ArrayData(tsrc, aCx), writeLen);
    if (NS_FAILED(rv)) {
        return rv;
    }

    // Return the actual amount written.
    *aRetVal = writeLen * mChannels;
    return rv;
}