Esempio n. 1
0
bool
ChromeObjectWrapper::get(JSContext *cx, JS::Handle<JSObject*> wrapper,
                         JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
                         JS::MutableHandle<JS::Value> vp)
{
    assertEnteredPolicy(cx, wrapper, id);
    vp.setUndefined();
    JSPropertyDescriptor desc;
    // Only call through to the get trap on the underlying object if we're
    // allowed to see the property, and if what we'll find is not on a standard
    // prototype.
    if (AllowedByBase(cx, wrapper, id, js::Wrapper::GET) &&
        !PropIsFromStandardPrototype(cx, wrapper, id))
    {
        // Call the get trap.
        if (!ChromeObjectWrapperBase::get(cx, wrapper, receiver, id, vp))
            return false;
        // If we found something, we're done.
        if (!vp.isUndefined())
            return true;
    }

    // If we have no proto, we're done.
    JSObject *wrapperProto;
    if (!JS_GetPrototype(cx, wrapper, &wrapperProto))
        return false;
    if (!wrapperProto)
        return true;

    // Try the prototype.
    MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
    return js::GetGeneric(cx, wrapperProto, receiver, id, vp.address());
}
Esempio n. 2
0
nsresult
XBL_DeserializeFunction(nsIObjectInputStream* aStream,
                        JS::MutableHandle<JSObject*> aFunctionObjectp)
{
  AssertInCompilationScope();
  AutoJSContext cx;
  return nsContentUtils::XPConnect()->ReadFunction(aStream, cx,
                                                   aFunctionObjectp.address());
}
Esempio n. 3
0
bool
CallbackInterface::GetCallableProperty(JSContext* cx, const char* aPropName,
                                       JS::MutableHandle<JS::Value> aCallable)
{
  if (!JS_GetProperty(cx, mCallback, aPropName, aCallable.address())) {
    return false;
  }
  if (!aCallable.isObject() ||
      !JS_ObjectIsCallable(cx, &aCallable.toObject())) {
    nsPrintfCString description("Property '%s'", aPropName);
    ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
    return false;
  }

  return true;
}
// Define a shadowing property on |this| for the XBL field defined by the
// contents of the callee's reserved slots.  If the property was defined,
// *installed will be true, and idp will be set to the property name that was
// defined.
static bool
InstallXBLField(JSContext* cx,
                JS::Handle<JSObject*> callee, JS::Handle<JSObject*> thisObj,
                JS::MutableHandle<jsid> idp, bool* installed)
{
  *installed = false;

  // First ensure |this| is a reasonable XBL bound node.
  //
  // FieldAccessorGuard already determined whether |thisObj| was acceptable as
  // |this| in terms of not throwing a TypeError.  Assert this for good measure.
  MOZ_ASSERT(ValueHasISupportsPrivate(JS::ObjectValue(*thisObj)));

  // But there are some cases where we must accept |thisObj| but not install a
  // property on it, or otherwise touch it.  Hence this split of |this|-vetting
  // duties.
  nsISupports* native =
    nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, thisObj);
  if (!native) {
    // Looks like whatever |thisObj| is it's not our nsIContent.  It might well
    // be the proto our binding installed, however, where the private is the
    // nsXBLDocumentInfo, so just baul out quietly.  Do NOT throw an exception
    // here.
    //
    // We could make this stricter by checking the class maybe, but whatever.
    return true;
  }

  nsCOMPtr<nsIContent> xblNode = do_QueryInterface(native);
  if (!xblNode) {
    xpc::Throw(cx, NS_ERROR_UNEXPECTED);
    return false;
  }

  // Now that |this| is okay, actually install the field.

  // Because of the possibility (due to XBL binding inheritance, because each
  // XBL binding lives in its own global object) that |this| might be in a
  // different compartment from the callee (not to mention that this method can
  // be called with an arbitrary |this| regardless of how insane XBL is), and
  // because in this method we've entered |this|'s compartment (see in
  // Field[GS]etter where we attempt a cross-compartment call), we must enter
  // the callee's compartment to access its reserved slots.
  nsXBLPrototypeBinding* protoBinding;
  nsDependentJSString fieldName;
  {
    JSAutoCompartment ac(cx, callee);

    JS::Rooted<JSObject*> xblProto(cx);
    xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();

    JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT));
    JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
    fieldName.init(fieldStr);

    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp.address()));

    // If a separate XBL scope is being used, the callee is not same-compartment
    // with the xbl prototype, and the object is a cross-compartment wrapper.
    xblProto = js::UncheckedUnwrap(xblProto);
    JSAutoCompartment ac2(cx, xblProto);
    JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
    protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
    MOZ_ASSERT(protoBinding);
  }

  nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
  MOZ_ASSERT(field);

  // This mirrors code in nsXBLProtoImpl::InstallImplementation
  nsCOMPtr<nsIScriptGlobalObject> global =
    do_QueryInterface(xblNode->OwnerDoc()->GetWindow());
  if (!global) {
    return true;
  }

  nsCOMPtr<nsIScriptContext> context = global->GetContext();
  if (!context) {
    return true;
  }

  nsresult rv = field->InstallField(context, thisObj, protoBinding->DocURI(),
                                    installed);
  if (NS_SUCCEEDED(rv)) {
    return true;
  }

  if (!::JS_IsExceptionPending(cx)) {
    xpc::Throw(cx, rv);
  }
  return false;
}
Esempio n. 5
0
nsresult
nsJSON::DecodeInternal(JSContext* cx,
                       nsIInputStream *aStream,
                       int32_t aContentLength,
                       bool aNeedsConverter,
                       JS::MutableHandle<JS::Value> aRetval)
{
    // Consume the stream
    nsCOMPtr<nsIChannel> jsonChannel;
    if (!mURI) {
        NS_NewURI(getter_AddRefs(mURI), NS_LITERAL_CSTRING("about:blank"), 0, 0 );
        if (!mURI)
            return NS_ERROR_OUT_OF_MEMORY;
    }

    nsresult rv =
        NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream,
                                 NS_LITERAL_CSTRING("application/json"));
    if (!jsonChannel || NS_FAILED(rv))
        return NS_ERROR_FAILURE;

    nsRefPtr<nsJSONListener> jsonListener =
        new nsJSONListener(cx, aRetval.address(), aNeedsConverter);

    //XXX this stream pattern should be consolidated in netwerk
    rv = jsonListener->OnStartRequest(jsonChannel, nullptr);
    if (NS_FAILED(rv)) {
        jsonChannel->Cancel(rv);
        return rv;
    }

    nsresult status;
    jsonChannel->GetStatus(&status);
    uint64_t offset = 0;
    while (NS_SUCCEEDED(status)) {
        uint64_t available;
        rv = aStream->Available(&available);
        if (rv == NS_BASE_STREAM_CLOSED) {
            rv = NS_OK;
            break;
        }
        if (NS_FAILED(rv)) {
            jsonChannel->Cancel(rv);
            break;
        }
        if (!available)
            break; // blocking input stream has none available when done

        if (available > UINT32_MAX)
            available = UINT32_MAX;

        rv = jsonListener->OnDataAvailable(jsonChannel, nullptr,
                                           aStream,
                                           offset,
                                           (uint32_t)available);
        if (NS_FAILED(rv)) {
            jsonChannel->Cancel(rv);
            break;
        }

        offset += available;
        jsonChannel->GetStatus(&status);
    }
    NS_ENSURE_SUCCESS(rv, rv);

    rv = jsonListener->OnStopRequest(jsonChannel, nullptr, status);
    NS_ENSURE_SUCCESS(rv, rv);

    return NS_OK;
}
Esempio n. 6
0
nsresult
nsJSON::DecodeInternal(JSContext* cx,
                       nsIInputStream *aStream,
                       int32_t aContentLength,
                       bool aNeedsConverter,
                       JS::MutableHandle<JS::Value> aRetval)
{
  // Consume the stream
  nsCOMPtr<nsIChannel> jsonChannel;
  if (!mURI) {
    NS_NewURI(getter_AddRefs(mURI), NS_LITERAL_CSTRING("about:blank"), 0, 0 );
    if (!mURI)
      return NS_ERROR_OUT_OF_MEMORY;
  }

  nsresult rv;
  nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();

  // The ::Decode function is deprecated [Bug 675797] and the following
  // channel is never openend, so it does not matter what securityFlags
  // we pass to NS_NewInputStreamChannel here.
  rv = NS_NewInputStreamChannel(getter_AddRefs(jsonChannel),
                                mURI,
                                aStream,
                                nullPrincipal,
                                nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
                                nsIContentPolicy::TYPE_OTHER,
                                NS_LITERAL_CSTRING("application/json"));

  if (!jsonChannel || NS_FAILED(rv))
    return NS_ERROR_FAILURE;

  RefPtr<nsJSONListener> jsonListener =
    new nsJSONListener(cx, aRetval.address(), aNeedsConverter);

  //XXX this stream pattern should be consolidated in netwerk
  rv = jsonListener->OnStartRequest(jsonChannel, nullptr);
  if (NS_FAILED(rv)) {
    jsonChannel->Cancel(rv);
    return rv;
  }

  nsresult status;
  jsonChannel->GetStatus(&status);
  uint64_t offset = 0;
  while (NS_SUCCEEDED(status)) {
    uint64_t available;
    rv = aStream->Available(&available);
    if (rv == NS_BASE_STREAM_CLOSED) {
      rv = NS_OK;
      break;
    }
    if (NS_FAILED(rv)) {
      jsonChannel->Cancel(rv);
      break;
    }
    if (!available)
      break; // blocking input stream has none available when done

    if (available > UINT32_MAX)
      available = UINT32_MAX;

    rv = jsonListener->OnDataAvailable(jsonChannel, nullptr,
                                       aStream,
                                       offset,
                                       (uint32_t)available);
    if (NS_FAILED(rv)) {
      jsonChannel->Cancel(rv);
      break;
    }

    offset += available;
    jsonChannel->GetStatus(&status);
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = jsonListener->OnStopRequest(jsonChannel, nullptr, status);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
NS_IMETHODIMP
MobileMessageManager::Send(JS::Handle<JS::Value> aNumber,
                           const nsAString& aMessage,
                           JS::Handle<JS::Value> aSendParams,
                           JSContext* aCx,
                           uint8_t aArgc,
                           JS::MutableHandle<JS::Value> aReturn)
{
  if (!aNumber.isString() &&
      !(aNumber.isObject() && JS_IsArrayObject(aCx, &aNumber.toObject()))) {
    return NS_ERROR_INVALID_ARG;
  }

  nsresult rv;
  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_STATE(sc);

  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));

  mozilla::Maybe<JSAutoCompartment> ac;
  if (!global) {
    global = sc->GetWindowProxy();
    ac.construct(aCx, global);
  }

  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
  NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);

  // Use the default one unless |aSendParams.serviceId| is available.
  uint32_t serviceId;
  rv = smsService->GetSmsDefaultServiceId(&serviceId);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aArgc == 3) {
    JS::Rooted<JS::Value> param(aCx, aSendParams);
    RootedDictionary<SmsSendParameters> sendParams(aCx);
    if (!sendParams.Init(aCx, param)) {
      return NS_ERROR_TYPE_ERR;
    }
    if (sendParams.mServiceId.WasPassed()) {
      serviceId = sendParams.mServiceId.Value();
    }
  }

  if (aNumber.isString()) {
    JS::Rooted<JSString*> str(aCx, aNumber.toString());
    return Send(aCx, global, serviceId, str, aMessage, aReturn.address());
  }

  // Must be an array then.
  JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());

  uint32_t size;
  if (!JS_GetArrayLength(aCx, numbers, &size)) {
    return NS_ERROR_FAILURE;
  }

  JS::AutoValueVector requests(aCx);
  if (!requests.resize(size)) {
    return NS_ERROR_FAILURE;
  }

  JS::Rooted<JS::Value> number(aCx);
  JS::Rooted<JSString*> str(aCx);
  for (uint32_t i = 0; i < size; ++i) {
    if (!JS_GetElement(aCx, numbers, i, &number)) {
      return NS_ERROR_INVALID_ARG;
    }

    str = JS::ToString(aCx, number);
    if (!str) {
      return NS_ERROR_FAILURE;
    }

    nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  JS::Rooted<JSObject*> obj(aCx);
  obj = JS_NewArrayObject(aCx, requests.length(), requests.begin());
  if (!obj) {
    return NS_ERROR_FAILURE;
  }

  aReturn.setObject(*obj);
  return NS_OK;
}