Beispiel #1
0
NS_IMETHODIMP
nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength, JS::Handle<JS::Value> aBuffer, JSContext* cx)
{
    if (!aBuffer.isObject()) {
        return NS_ERROR_FAILURE;
    }
    JS::RootedObject buffer(cx, &aBuffer.toObject());
    if (!JS_IsArrayBufferObject(buffer) ||
        JS_GetArrayBufferByteLength(buffer) < aLength) {
        return NS_ERROR_FAILURE;
    }
    uint8_t* data = JS_GetArrayBufferData(&aBuffer.toObject());
    if (!data) {
        return NS_ERROR_FAILURE;
    }

    uint32_t bytesRead;
    nsresult rv = Read(reinterpret_cast<char*>(data), aLength, &bytesRead);
    if (NS_WARN_IF(NS_FAILED(rv)))
        return rv;
    if (bytesRead != aLength) {
        return NS_ERROR_FAILURE;
    }
    return NS_OK;
}
NS_IMETHODIMP
ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
                                uint32_t aByteOffset,
                                uint32_t aLength,
                                JSContext* aCx)
{
  if (!aBuffer.isObject()) {
    return NS_ERROR_FAILURE;
  }
  JS::RootedObject arrayBuffer(aCx, &aBuffer.toObject());
  if (!JS_IsArrayBufferObject(arrayBuffer)) {
    return NS_ERROR_FAILURE;
  }

  mArrayBuffer.construct(aCx, aBuffer);

  uint32_t buflen = JS_GetArrayBufferByteLength(arrayBuffer);
  mOffset = std::min(buflen, aByteOffset);
  mBufferLength = std::min(buflen - mOffset, aLength);
  mBuffer = JS_GetStableArrayBufferData(aCx, arrayBuffer);
  if (!mBuffer) {
      return NS_ERROR_FAILURE;
  }
  return NS_OK;
}
bool
FieldSetterImpl(JSContext *cx, JS::CallArgs args)
{
  JS::Handle<JS::Value> thisv = args.thisv();
  MOZ_ASSERT(ValueHasISupportsPrivate(thisv));

  JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());

  // We should be in the compartment of |this|. If we got here via nativeCall,
  // |this| is not same-compartment with |callee|, and it's possible via
  // asymmetric security semantics that |args.calleev()| is actually a security
  // wrapper. In this case, we know we want to do an unsafe unwrap, and
  // InstallXBLField knows how to handle cross-compartment pointers.
  bool installed = false;
  JS::Rooted<JSObject*> callee(cx, js::UncheckedUnwrap(&args.calleev().toObject()));
  JS::Rooted<jsid> id(cx);
  if (!InstallXBLField(cx, callee, thisObj, &id, &installed)) {
    return false;
  }

  if (installed) {
    if (!::JS_SetPropertyById(cx, thisObj, id, args.get(0))) {
      return false;
    }
  }
  args.rval().setUndefined();
  return true;
}
Beispiel #4
0
// static
nsresult
IDBKeyRange::FromJSVal(JSContext* aCx,
                       JS::Handle<JS::Value> aVal,
                       IDBKeyRange** aKeyRange)
{
  nsRefPtr<IDBKeyRange> keyRange;

  if (aVal.isNullOrUndefined()) {
    // undefined and null returns no IDBKeyRange.
    keyRange.forget(aKeyRange);
    return NS_OK;
  }

  JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
  if (aVal.isPrimitive() || JS_IsArrayObject(aCx, obj) ||
      JS_ObjectIsDate(aCx, obj)) {
    // A valid key returns an 'only' IDBKeyRange.
    keyRange = new IDBKeyRange(nullptr, false, false, true);

    nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
    if (NS_FAILED(rv)) {
      return rv;
    }
  }
  else {
    MOZ_ASSERT(aVal.isObject());
    // An object is not permitted unless it's another IDBKeyRange.
    if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
    }
  }

  keyRange.forget(aKeyRange);
  return NS_OK;
}
Beispiel #5
0
NS_IMETHODIMP
TCPSocketParent::InitJS(JS::Handle<JS::Value> aIntermediary, JSContext* aCx)
{
  MOZ_ASSERT(aIntermediary.isObject());
  mIntermediaryObj = &aIntermediary.toObject();
  return NS_OK;
}
// PromiseNativeHandler
void
PresentationResponderInfo::ResolvedCallback(JSContext* aCx,
                                            JS::Handle<JS::Value> aValue)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (NS_WARN_IF(!aValue.isObject())) {
    ReplyError(NS_ERROR_NOT_AVAILABLE);
    return;
  }

  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
  if (NS_WARN_IF(!obj)) {
    ReplyError(NS_ERROR_NOT_AVAILABLE);
    return;
  }

  // Start to listen to document state change event |STATE_TRANSFERRING|.
  HTMLIFrameElement* frame = nullptr;
  nsresult rv = UNWRAP_OBJECT(HTMLIFrameElement, obj, frame);
  if (NS_WARN_IF(!frame)) {
    ReplyError(NS_ERROR_NOT_AVAILABLE);
    return;
  }

  nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface((nsIFrameLoaderOwner*) frame);
  if (NS_WARN_IF(!owner)) {
    ReplyError(NS_ERROR_NOT_AVAILABLE);
    return;
  }

  nsCOMPtr<nsIFrameLoader> frameLoader;
  rv = owner->GetFrameLoader(getter_AddRefs(frameLoader));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    ReplyError(rv);
    return;
  }

  nsRefPtr<TabParent> tabParent = TabParent::GetFrom(frameLoader);
  if (tabParent) {
    // OOP frame
    nsCOMPtr<nsIContentParent> cp = tabParent->Manager();
    NS_WARN_IF(!static_cast<ContentParent*>(cp.get())->SendNotifyPresentationReceiverLaunched(tabParent, mSessionId));
  } else {
    // In-process frame
    nsCOMPtr<nsIDocShell> docShell;
    rv = frameLoader->GetDocShell(getter_AddRefs(docShell));
    if (NS_WARN_IF(NS_FAILED(rv))) {
      ReplyError(rv);
      return;
    }

    mLoadingCallback = new PresentationResponderLoadingCallback(mSessionId);
    rv = mLoadingCallback->Init(docShell);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      ReplyError(rv);
      return;
    }
  }
}
NS_IMETHODIMP
MobileConnectionRequestParent::NotifyGetCallForwardingSuccess(JS::Handle<JS::Value> aResults)
{
  uint32_t length;
  AutoSafeJSContext cx;
  JS::Rooted<JSObject*> object(cx, &aResults.toObject());
  nsTArray<IPC::MozCallForwardingOptions> results;

  if (!JS_IsArrayObject(cx, object) ||
      !JS_GetArrayLength(cx, object, &length)) {
    return NS_ERROR_TYPE_ERR;
  }

  for (uint32_t i = 0; i < length; i++) {
    JS::Rooted<JS::Value> entry(cx);
    IPC::MozCallForwardingOptions info;

    if (!JS_GetElement(cx, object, i, &entry) || !info.Init(cx, entry)) {
      return NS_ERROR_TYPE_ERR;
    }

    results.AppendElement(info);
  }

  return SendReply(MobileConnectionReplySuccessCallForwarding(results));
}
NS_IMETHODIMP
nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength,
                                     JS::Handle<JS::Value> aBuffer,
                                     JSContext* aCx, uint32_t* aReadLength)
{
  if (!aBuffer.isObject()) {
    return NS_ERROR_FAILURE;
  }
  JS::RootedObject buffer(aCx, &aBuffer.toObject());
  if (!JS_IsArrayBufferObject(buffer)) {
    return NS_ERROR_FAILURE;
  }

  uint32_t bufferLength = JS_GetArrayBufferByteLength(buffer);
  if (bufferLength < aLength) {
    return NS_ERROR_FAILURE;
  }

  uint32_t bufSize = std::min<uint32_t>(aLength, 4096);
  UniquePtr<char[]> buf = MakeUnique<char[]>(bufSize);

  uint32_t pos = 0;
  *aReadLength = 0;
  do {
    // Read data into temporary buffer.
    uint32_t bytesRead;
    uint32_t amount = std::min(aLength - pos, bufSize);
    nsresult rv = Read(buf.get(), amount, &bytesRead);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
    MOZ_ASSERT(bytesRead <= amount);

    if (bytesRead == 0) {
      break;
    }

    // Copy data into actual buffer.

    JS::AutoCheckCannotGC nogc;
    bool isShared;
    if (bufferLength != JS_GetArrayBufferByteLength(buffer)) {
      return NS_ERROR_FAILURE;
    }

    char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(buffer, &isShared, nogc));
    MOZ_ASSERT(!isShared);      // Implied by JS_GetArrayBufferData()
    if (!data) {
      return NS_ERROR_FAILURE;
    }

    *aReadLength += bytesRead;
    PodCopy(data + pos, buf.get(), bytesRead);

    pos += bytesRead;
  } while (pos < aLength);

  return NS_OK;
}
bool
ValueHasISupportsPrivate(JS::Handle<JS::Value> v)
{
  if (!v.isObject()) {
    return false;
  }

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

  const 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;
}
Beispiel #10
0
NS_IMETHODIMP
nsSpeechTask::SendAudio(JS::Handle<JS::Value> aData, JS::Handle<JS::Value> aLandmarks,
                        JSContext* aCx)
{
  MOZ_ASSERT(XRE_IsParentProcess());

  if(NS_WARN_IF(!(mStream))) {
    return NS_ERROR_NOT_AVAILABLE;
  }
  if(NS_WARN_IF(mStream->IsDestroyed())) {
    return NS_ERROR_NOT_AVAILABLE;
  }
  if(NS_WARN_IF(!(mChannels))) {
    return NS_ERROR_FAILURE;
  }
  if(NS_WARN_IF(!(aData.isObject()))) {
    return NS_ERROR_INVALID_ARG;
  }

  if (mIndirectAudio) {
    NS_WARNING("Can't call SendAudio from an indirect audio speech service.");
    return NS_ERROR_FAILURE;
  }

  JS::Rooted<JSObject*> darray(aCx, &aData.toObject());
  JSAutoCompartment ac(aCx, darray);

  JS::Rooted<JSObject*> tsrc(aCx, nullptr);

  // Allow either Int16Array or plain JS Array
  if (JS_IsInt16Array(darray)) {
    tsrc = darray;
  } else {
    bool isArray;
    if (!JS_IsArrayObject(aCx, darray, &isArray)) {
      return NS_ERROR_UNEXPECTED;
    }
    if (isArray) {
      tsrc = JS_NewInt16ArrayFromArray(aCx, darray);
    }
  }

  if (!tsrc) {
    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
  }

  uint32_t dataLen = JS_GetTypedArrayLength(tsrc);
  RefPtr<mozilla::SharedBuffer> samples;
  {
    JS::AutoCheckCannotGC nogc;
    samples = makeSamples(JS_GetInt16ArrayData(tsrc, nogc), dataLen);
  }
  SendAudioImpl(samples, dataLen);

  return NS_OK;
}
static already_AddRefed<EventListener>
ToEventListener(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
  if (NS_WARN_IF(!aValue.isObject())) {
    return nullptr;
  }

  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
  RefPtr<EventListener> listener =
    new EventListener(aCx, obj, GetIncumbentGlobal());
  return listener.forget();
}
nsresult
TelephonyDialCallback::NotifyDialMMISuccess(JSContext* aCx,
                                            const nsAString& aStatusMessage,
                                            JS::Handle<JS::Value> aInfo)
{
  RootedDictionary<MozMMIResult> result(aCx);

  result.mServiceCode.Assign(mServiceCode);
  result.mStatusMessage.Assign(aStatusMessage);
  result.mAdditionalInformation.Construct().SetAsObject() = &aInfo.toObject();

  return NotifyDialMMISuccess(aCx, result);
}
NS_IMETHODIMP
WebVTTListener::OnRegion(JS::Handle<JS::Value> aRegion, JSContext* aCx)
{
  if (!aRegion.isObject()) {
    return NS_ERROR_FAILURE;
  }

  TextTrackRegion* region;
  nsresult rv = UNWRAP_OBJECT(VTTRegion, &aRegion.toObject(), region);
  NS_ENSURE_SUCCESS(rv, rv);

  mElement->mTrack->AddRegion(*region);

  return NS_OK;
}
NS_IMETHODIMP
WebVTTListener::OnCue(JS::Handle<JS::Value> aCue, JSContext* aCx)
{
  if (!aCue.isObject()) {
    return NS_ERROR_FAILURE;
  }

  TextTrackCue* cue = nullptr;
  nsresult rv = UNWRAP_OBJECT(VTTCue, &aCue.toObject(), cue);
  NS_ENSURE_SUCCESS(rv, rv);

  cue->SetTrackElement(mElement);
  mElement->mTrack->AddCue(*cue);

  return NS_OK;
}
Beispiel #15
0
void
GetEntryHelper::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
  if(NS_WARN_IF(!aValue.isObject())) {
    return;
  }

  JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());

  // This is not the last part of the path.
  if (!mParts.IsEmpty()) {
    ContinueRunning(obj);
    return;
  }

  CompleteOperation(obj);
}
// static
nsresult
IDBKeyRange::FromJSVal(JSContext* aCx,
                       JS::Handle<JS::Value> aVal,
                       IDBKeyRange** aKeyRange)
{
  MOZ_ASSERT_IF(!aCx, aVal.isUndefined());

  RefPtr<IDBKeyRange> keyRange;

  if (aVal.isNullOrUndefined()) {
    // undefined and null returns no IDBKeyRange.
    keyRange.forget(aKeyRange);
    return NS_OK;
  }

  JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
  bool isValidKey = aVal.isPrimitive();
  if (!isValidKey) {
    js::ESClass cls;
    if (!js::GetBuiltinClass(aCx, obj, &cls)) {
      return NS_ERROR_UNEXPECTED;
    }
    isValidKey = cls == js::ESClass::Array || cls == js::ESClass::Date;
  }
  if (isValidKey) {
    // A valid key returns an 'only' IDBKeyRange.
    keyRange = new IDBKeyRange(nullptr, false, false, true);

    nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
    if (NS_FAILED(rv)) {
      return rv;
    }
  }
  else {
    MOZ_ASSERT(aVal.isObject());
    // An object is not permitted unless it's another IDBKeyRange.
    if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
    }
  }

  keyRange.forget(aKeyRange);
  return NS_OK;
}
Beispiel #17
0
NS_IMETHODIMP
SmsFilter::SetNumbers(JSContext* aCx, JS::Handle<JS::Value> aNumbers)
{
  if (aNumbers.isNull()) {
    mData.numbers().Clear();
    return NS_OK;
  }

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

  JS::Rooted<JSObject*> obj(aCx, &aNumbers.toObject());
  if (!JS_IsArrayObject(aCx, obj)) {
    return NS_ERROR_INVALID_ARG;
  }

  uint32_t size;
  JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, obj, &size));

  nsTArray<nsString> numbers;

  for (uint32_t i=0; i<size; ++i) {
    JS::Rooted<JS::Value> jsNumber(aCx);
    if (!JS_GetElement(aCx, obj, i, &jsNumber)) {
      return NS_ERROR_INVALID_ARG;
    }

    if (!jsNumber.isString()) {
      return NS_ERROR_INVALID_ARG;
    }

    nsDependentJSString number;
    number.init(aCx, jsNumber.toString());

    numbers.AppendElement(number);
  }

  mData.numbers().Clear();
  mData.numbers().AppendElements(numbers);

  return NS_OK;
}
Beispiel #18
0
/* static */ void
ThreadSafeChromeUtils::NondeterministicGetWeakSetKeys(GlobalObject& aGlobal,
                                                      JS::Handle<JS::Value> aSet,
                                                      JS::MutableHandle<JS::Value> aRetval,
                                                      ErrorResult& aRv)
{
  if (!aSet.isObject()) {
    aRetval.setUndefined();
  } else {
    JSContext* cx = aGlobal.Context();
    JS::Rooted<JSObject*> objRet(cx);
    JS::Rooted<JSObject*> setObj(cx, &aSet.toObject());
    if (!JS_NondeterministicGetWeakSetKeys(cx, setObj, &objRet)) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    } else {
      aRetval.set(objRet ? JS::ObjectValue(*objRet) : JS::UndefinedValue());
    }
  }
}
void
RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
  AutoCancel autoCancel(this);

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

  nsRefPtr<Response> response;
  nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response);
  if (NS_FAILED(rv)) {
    return;
  }

  nsCOMPtr<nsIInputStream> body;
  response->GetBody(getter_AddRefs(body));
  if (NS_WARN_IF(!body) || NS_WARN_IF(response->BodyUsed())) {
    return;
  }
  response->SetBodyUsed();

  nsCOMPtr<nsIOutputStream> responseBody;
  rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel));

  nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
  if (NS_WARN_IF(!stsThread)) {
    return;
  }
  rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
                    RespondWithCopyComplete, closure.forget());
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  autoCancel.Reset();
}
Beispiel #20
0
bool
CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aException)
{
  if (mExceptionHandling == eRethrowExceptions) {
    if (!mCompartment) {
      // Caller didn't ask us to filter for only exceptions we subsume.
      return true;
    }

    // On workers, we don't have nsIPrincipals to work with.  But we also only
    // have one compartment, so check whether mCompartment is the same as the
    // current compartment of mCx.
    if (mCompartment == js::GetContextCompartment(mCx)) {
      return true;
    }

    MOZ_ASSERT(NS_IsMainThread());

    // At this point mCx is in the compartment of our unwrapped callback, so
    // just check whether the principal of mCompartment subsumes that of the
    // current compartment/global of mCx.
    nsIPrincipal* callerPrincipal =
      nsJSPrincipals::get(JS_GetCompartmentPrincipals(mCompartment));
    nsIPrincipal* calleePrincipal = nsContentUtils::SubjectPrincipal();
    if (callerPrincipal->SubsumesConsideringDomain(calleePrincipal)) {
      return true;
    }
  }

  MOZ_ASSERT(mCompartment);

  // Now we only want to throw an exception to the caller if the object that was
  // thrown is in the caller compartment (which we stored in mCompartment).

  if (!aException.isObject()) {
    return false;
  }

  JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
  obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
  return js::GetObjectCompartment(obj) == mCompartment;
}
nsresult
SystemWorkerManager::RegisterNfcWorker(JS::Handle<JS::Value> aWorker,
                                       JSContext* aCx)
{
#ifndef MOZ_NFC
  return NS_ERROR_NOT_IMPLEMENTED;
#else
  NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED);

  JSAutoCompartment ac(aCx, &aWorker.toObject());

  WorkerCrossThreadDispatcher* wctd =
    GetWorkerCrossThreadDispatcher(aCx, aWorker);
  if (!wctd) {
    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for nfc");
    return NS_ERROR_FAILURE;
  }

  return NfcConsumer::Register(wctd);
#endif // MOZ_NFC
}
Beispiel #22
0
nsresult
SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
                                       JS::Handle<JS::Value> aWorker,
                                       JSContext *aCx)
{
#ifndef MOZ_B2G_RIL
  return NS_ERROR_NOT_IMPLEMENTED;
#else
  NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED);

  JSAutoCompartment ac(aCx, &aWorker.toObject());

  WorkerCrossThreadDispatcher *wctd =
    GetWorkerCrossThreadDispatcher(aCx, aWorker);
  if (!wctd) {
    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for ril");
    return NS_ERROR_FAILURE;
  }

  return RilWorker::Register(aClientId, wctd);
#endif // MOZ_B2G_RIL
}
Beispiel #23
0
NS_IMETHODIMP
nsSpeechTask::SendAudio(JS::Handle<JS::Value> aData, JS::Handle<JS::Value> aLandmarks,
                        JSContext* aCx)
{
  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);

  NS_ENSURE_TRUE(mStream, NS_ERROR_NOT_AVAILABLE);
  NS_ENSURE_FALSE(mStream->IsDestroyed(), NS_ERROR_NOT_AVAILABLE);
  NS_ENSURE_TRUE(mChannels, NS_ERROR_FAILURE);
  NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_INVALID_ARG);

  if (mIndirectAudio) {
    NS_WARNING("Can't call SendAudio from an indirect audio speech service.");
    return NS_ERROR_FAILURE;
  }

  JS::Rooted<JSObject*> darray(aCx, &aData.toObject());
  JSAutoCompartment ac(aCx, darray);

  JS::Rooted<JSObject*> tsrc(aCx, nullptr);

  // Allow either Int16Array or plain JS Array
  if (JS_IsInt16Array(darray)) {
    tsrc = darray;
  } else if (JS_IsArrayObject(aCx, darray)) {
    tsrc = JS_NewInt16ArrayFromArray(aCx, darray);
  }

  if (!tsrc) {
    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
  }

  SendAudioImpl(JS_GetInt16ArrayData(tsrc),
                JS_GetTypedArrayLength(tsrc));

  return NS_OK;
}
void
CompareCache::ManageCacheResult(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
    AssertIsOnMainThread();

    if (NS_WARN_IF(!aValue.isObject())) {
        mManager->CacheFinished(NS_ERROR_FAILURE, false);
        return;
    }

    JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
    if (NS_WARN_IF(!obj)) {
        mManager->CacheFinished(NS_ERROR_FAILURE, false);
        return;
    }

    Cache* cache = nullptr;
    nsresult rv = UNWRAP_OBJECT(Cache, obj, cache);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        mManager->CacheFinished(rv, false);
        return;
    }

    RequestOrUSVString request;
    request.SetAsUSVString().Rebind(mURL.Data(), mURL.Length());
    ErrorResult error;
    CacheQueryOptions params;
    RefPtr<Promise> promise = cache->Match(request, params, error);
    if (NS_WARN_IF(error.Failed())) {
        mManager->CacheFinished(error.StealNSResult(), false);
        return;
    }

    promise->AppendNativeHandler(this);
    mState = WaitingForValue;
}
    // This class manages 2 promises: 1 is to retrieve Cache object, and 2 is to
    // Put the value in the cache. For this reason we have mState to know what
    // callback we are handling.
    void
    ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
    {
        AssertIsOnMainThread();
        MOZ_ASSERT(mCallback);

        if (mState == WaitingForOpen) {
            if (NS_WARN_IF(!aValue.isObject())) {
                Fail(NS_ERROR_FAILURE);
                return;
            }

            JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
            if (NS_WARN_IF(!obj)) {
                Fail(NS_ERROR_FAILURE);
                return;
            }

            Cache* cache = nullptr;
            nsresult rv = UNWRAP_OBJECT(Cache, obj, cache);
            if (NS_WARN_IF(NS_FAILED(rv))) {
                Fail(rv);
                return;
            }

            // Just to be safe.
            RefPtr<Cache> kungfuDeathGrip = cache;
            WriteToCache(cache);
            return;
        }

        MOZ_ASSERT(mState == WaitingForPut);
        mCallback->ComparisonResult(NS_OK, false /* aIsEqual */,
                                    mNewCacheName, mMaxScope);
        Cleanup();
    }
void
RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
  AutoCancel autoCancel(this, mRequestURL);

  if (!aValue.isObject()) {
    NS_WARNING("FetchEvent::RespondWith was passed a promise resolved to a non-Object value");

    nsCString sourceSpec;
    uint32_t line = 0;
    uint32_t column = 0;
    nsString valueString;
    ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString);

    autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column,
                                           NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"),
                                           mRequestURL, valueString);
    return;
  }

  RefPtr<Response> response;
  nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response);
  if (NS_FAILED(rv)) {
    nsCString sourceSpec;
    uint32_t line = 0;
    uint32_t column = 0;
    nsString valueString;
    ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString);

    autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column,
                                           NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"),
                                           mRequestURL, valueString);
    return;
  }

  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  MOZ_ASSERT(worker);
  worker->AssertIsOnWorkerThread();

  // Section "HTTP Fetch", step 3.3:
  //  If one of the following conditions is true, return a network error:
  //    * response's type is "error".
  //    * request's mode is not "no-cors" and response's type is "opaque".
  //    * request's redirect mode is not "manual" and response's type is
  //      "opaqueredirect".
  //    * request's redirect mode is not "follow" and response's url list
  //      has more than one item.

  if (response->Type() == ResponseType::Error) {
    autoCancel.SetCancelMessage(
      NS_LITERAL_CSTRING("InterceptedErrorResponseWithURL"), mRequestURL);
    return;
  }

  MOZ_ASSERT_IF(mIsClientRequest, mRequestMode == RequestMode::Same_origin ||
                                  mRequestMode == RequestMode::Navigate);

  if (response->Type() == ResponseType::Opaque && mRequestMode != RequestMode::No_cors) {
    uint32_t mode = static_cast<uint32_t>(mRequestMode);
    NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[mode].value,
                                      RequestModeValues::strings[mode].length);

    autoCancel.SetCancelMessage(
      NS_LITERAL_CSTRING("BadOpaqueInterceptionRequestModeWithURL"),
      mRequestURL, modeString);
    return;
  }

  if (mRequestRedirectMode != RequestRedirect::Manual &&
      response->Type() == ResponseType::Opaqueredirect) {
    autoCancel.SetCancelMessage(
      NS_LITERAL_CSTRING("BadOpaqueRedirectInterceptionWithURL"), mRequestURL);
    return;
  }

  if (mRequestRedirectMode != RequestRedirect::Follow && response->Redirected()) {
    autoCancel.SetCancelMessage(
      NS_LITERAL_CSTRING("BadRedirectModeInterceptionWithURL"), mRequestURL);
    return;
  }

  if (NS_WARN_IF(response->BodyUsed())) {
    autoCancel.SetCancelMessage(
      NS_LITERAL_CSTRING("InterceptedUsedResponseWithURL"), mRequestURL);
    return;
  }

  RefPtr<InternalResponse> ir = response->GetInternalResponse();
  if (NS_WARN_IF(!ir)) {
    return;
  }
  // When an opaque response is encountered, we need the original channel's principal
  // to reflect the final URL. Non-opaque responses are either same-origin or CORS-enabled
  // cross-origin responses, which are treated as same-origin by consumers.
  nsCString responseURL;
  if (response->Type() == ResponseType::Opaque) {
    responseURL = ir->GetUnfilteredURL();
    if (NS_WARN_IF(responseURL.IsEmpty())) {
      return;
    }
  }
  nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel,
                                                               mRegistration, ir,
                                                               worker->GetChannelInfo(),
                                                               mScriptSpec,
                                                               responseURL,
                                                               mRequestURL,
                                                               mRespondWithScriptSpec,
                                                               mRespondWithLineNumber,
                                                               mRespondWithColumnNumber));
  nsCOMPtr<nsIInputStream> body;
  ir->GetUnfilteredBody(getter_AddRefs(body));
  // Errors and redirects may not have a body.
  if (body) {
    response->SetBodyUsed();

    nsCOMPtr<nsIOutputStream> responseBody;
    rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return;
    }

    const uint32_t kCopySegmentSize = 4096;

    // Depending on how the Response passed to .respondWith() was created, we may
    // get a non-buffered input stream.  In addition, in some configurations the
    // destination channel's output stream can be unbuffered.  We wrap the output
    // stream side here so that NS_AsyncCopy() works.  Wrapping the output side
    // provides the most consistent operation since there are fewer stream types
    // we are writing to.  The input stream can be a wide variety of concrete
    // objects which may or many not play well with NS_InputStreamIsBuffered().
    if (!NS_OutputStreamIsBuffered(responseBody)) {
      nsCOMPtr<nsIOutputStream> buffered;
      rv = NS_NewBufferedOutputStream(getter_AddRefs(buffered), responseBody,
           kCopySegmentSize);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return;
      }
      responseBody = buffered;
    }

    nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
    if (NS_WARN_IF(!stsThread)) {
      return;
    }

    // XXXnsm, Fix for Bug 1141332 means that if we decide to make this
    // streaming at some point, we'll need a different solution to that bug.
    rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_WRITESEGMENTS,
                      kCopySegmentSize, RespondWithCopyComplete, closure.forget());
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return;
    }
  } else {
    RespondWithCopyComplete(closure.forget(), NS_OK);
  }

  MOZ_ASSERT(!closure);
  autoCancel.Reset();
  mRequestWasHandled = true;
}
void
CompareCache::ManageValueResult(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
    AssertIsOnMainThread();

    // The cache returns undefined if the object is not stored.
    if (aValue.isUndefined()) {
        mManager->CacheFinished(NS_OK, false);
        return;
    }

    MOZ_ASSERT(aValue.isObject());

    JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
    if (NS_WARN_IF(!obj)) {
        mManager->CacheFinished(NS_ERROR_FAILURE, false);
        return;
    }

    Response* response = nullptr;
    nsresult rv = UNWRAP_OBJECT(Response, obj, response);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        mManager->CacheFinished(rv, false);
        return;
    }

    MOZ_ASSERT(response->Ok());

    nsCOMPtr<nsIInputStream> inputStream;
    response->GetBody(getter_AddRefs(inputStream));
    MOZ_ASSERT(inputStream);

    MOZ_ASSERT(!mPump);
    rv = NS_NewInputStreamPump(getter_AddRefs(mPump), inputStream);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        mManager->CacheFinished(rv, false);
        return;
    }

    nsCOMPtr<nsIStreamLoader> loader;
    rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        mManager->CacheFinished(rv, false);
        return;
    }

    rv = mPump->AsyncRead(loader, nullptr);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        mPump = nullptr;
        mManager->CacheFinished(rv, false);
        return;
    }

    nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(mPump);
    if (rr) {
        nsCOMPtr<nsIEventTarget> sts =
            do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
        rv = rr->RetargetDeliveryTo(sts);
        if (NS_WARN_IF(NS_FAILED(rv))) {
            mPump = nullptr;
            mManager->CacheFinished(rv, false);
            return;
        }
    }
}
Beispiel #28
0
NS_IMETHODIMP
TCPSocketParent::SendEvent(const nsAString& aType, JS::Handle<JS::Value> aDataVal,
                           const nsAString& aReadyState, JSContext* aCx)
{
  if (!mIPCOpen) {
    NS_WARNING("Dropping callback due to no IPC connection");
    return NS_OK;
  }

  CallbackData data;
  if (aDataVal.isString()) {
    JSString* jsstr = aDataVal.toString();
    nsAutoJSString str;
    if (!str.init(aCx, jsstr)) {
      FireInteralError(this, __LINE__);
      return NS_ERROR_OUT_OF_MEMORY;
    }
    data = SendableData(str);

  } else if (aDataVal.isUndefined() || aDataVal.isNull()) {
    data = mozilla::void_t();

  } else if (aDataVal.isObject()) {
    JS::Rooted<JSObject *> obj(aCx, &aDataVal.toObject());
    if (JS_IsArrayBufferObject(obj)) {
      FallibleTArray<uint8_t> fallibleArr;
      uint32_t errLine = 0;
      do {
          JS::AutoCheckCannotGC nogc;
          uint32_t nbytes = JS_GetArrayBufferByteLength(obj);
          uint8_t* buffer = JS_GetArrayBufferData(obj, nogc);
          if (!buffer) {
              errLine = __LINE__;
              break;
          }
          if (!fallibleArr.InsertElementsAt(0, buffer, nbytes, fallible)) {
              errLine = __LINE__;
              break;
          }
      } while (false);

      if (errLine) {
          FireInteralError(this, errLine);
          return NS_ERROR_OUT_OF_MEMORY;
      }

      InfallibleTArray<uint8_t> arr;
      arr.SwapElements(fallibleArr);
      data = SendableData(arr);

    } else {
      nsAutoJSString name;

      JS::Rooted<JS::Value> val(aCx);
      if (!JS_GetProperty(aCx, obj, "name", &val)) {
        NS_ERROR("No name property on supposed error object");
      } else if (val.isString()) {
        if (!name.init(aCx, val.toString())) {
          NS_WARNING("couldn't initialize string");
        }
      }

      data = TCPError(name);
    }
  } else {
    NS_ERROR("Unexpected JS value encountered");
    FireInteralError(this, __LINE__);
    return NS_ERROR_FAILURE;
  }
  mozilla::unused <<
      PTCPSocketParent::SendCallback(nsString(aType), data,
                                     nsString(aReadyState));
  return NS_OK;
}
void
RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
{
  AutoCancel autoCancel(this);

  if (!aValue.isObject()) {
    NS_WARNING("FetchEvent::RespondWith was passed a promise resolved to a non-Object value");
    return;
  }

  RefPtr<Response> response;
  nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response);
  if (NS_FAILED(rv)) {
    return;
  }

  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  MOZ_ASSERT(worker);
  worker->AssertIsOnWorkerThread();

  // Allow opaque response interception to be disabled until we can ensure the
  // security implications are not a complete disaster.
  if (response->Type() == ResponseType::Opaque &&
      !worker->OpaqueInterceptionEnabled()) {
    autoCancel.SetCancelStatus(NS_ERROR_OPAQUE_INTERCEPTION_DISABLED);
    return;
  }

  // Section "HTTP Fetch", step 2.2:
  //  If one of the following conditions is true, return a network error:
  //    * response's type is "error".
  //    * request's mode is not "no-cors" and response's type is "opaque".
  //    * request is not a navigation request and response's type is
  //      "opaqueredirect".

  if (response->Type() == ResponseType::Error) {
    autoCancel.SetCancelStatus(NS_ERROR_INTERCEPTED_ERROR_RESPONSE);
    return;
  }

  MOZ_ASSERT_IF(mIsClientRequest, mRequestMode == RequestMode::Same_origin);

  if (response->Type() == ResponseType::Opaque && mRequestMode != RequestMode::No_cors) {
    autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE);
    return;
  }

  if (!mIsNavigationRequest && response->Type() == ResponseType::Opaqueredirect) {
    autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_REDIRECT_INTERCEPTION);
    return;
  }

  if (NS_WARN_IF(response->BodyUsed())) {
    autoCancel.SetCancelStatus(NS_ERROR_INTERCEPTED_USED_RESPONSE);
    return;
  }

  RefPtr<InternalResponse> ir = response->GetInternalResponse();
  if (NS_WARN_IF(!ir)) {
    return;
  }

  nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel, ir,
                                                               worker->GetChannelInfo(),
                                                               mScriptSpec));
  nsCOMPtr<nsIInputStream> body;
  ir->GetUnfilteredBody(getter_AddRefs(body));
  // Errors and redirects may not have a body.
  if (body) {
    response->SetBodyUsed();

    nsCOMPtr<nsIOutputStream> responseBody;
    rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return;
    }

    nsCOMPtr<nsIEventTarget> stsThread = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
    if (NS_WARN_IF(!stsThread)) {
      return;
    }

    // XXXnsm, Fix for Bug 1141332 means that if we decide to make this
    // streaming at some point, we'll need a different solution to that bug.
    rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
                      RespondWithCopyComplete, closure.forget());
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return;
    }
  } else {
    RespondWithCopyComplete(closure.forget(), NS_OK);
  }

  MOZ_ASSERT(!closure);
  autoCancel.Reset();
  mRequestWasHandled = true;
}
bool IsWitness(JS::Handle<JS::Value> v)
{
  return v.isObject() && JS_GetClass(&v.toObject()) == &sWitnessClass;
}