void
    WriteNetworkBufferToNewCache()
    {
        AssertIsOnMainThread();
        MOZ_ASSERT(mCN);
        MOZ_ASSERT(mCacheStorage);
        MOZ_ASSERT(mNewCacheName.IsEmpty());

        ErrorResult result;
        result = serviceWorkerScriptCache::GenerateCacheName(mNewCacheName);
        if (NS_WARN_IF(result.Failed())) {
            MOZ_ASSERT(!result.IsErrorWithMessage());
            Fail(result.StealNSResult());
            return;
        }

        RefPtr<Promise> cacheOpenPromise = mCacheStorage->Open(mNewCacheName, result);
        if (NS_WARN_IF(result.Failed())) {
            MOZ_ASSERT(!result.IsErrorWithMessage());
            Fail(result.StealNSResult());
            return;
        }

        cacheOpenPromise->AppendNativeHandler(this);
    }
Example #2
0
  virtual bool
  MainThreadRun() override
  {
    AssertIsOnMainThread();

    // Initialise an AutoJSAPI with the target window.
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(mBackingStore->GetParentObject()))) {
      mResult = NS_ERROR_UNEXPECTED;
      return true;
    }
    JSContext* cx = jsapi.cx();

    ErrorResult rv;
    JS::Rooted<JS::Value> value(cx);
    Read(mBackingStore->GetParentObject(), cx, &value, rv);
    if (NS_WARN_IF(rv.Failed())) {
      rv.SuppressException();
      mResult = NS_ERROR_DOM_DATA_CLONE_ERR;
      return true;
    }

    RefPtr<Promise> promise = mBackingStore->Add(cx, value, mId,
                                                 mRevisionId, rv);
    if (NS_WARN_IF(rv.Failed())) {
      rv.SuppressException();
      mResult = NS_ERROR_FAILURE;
      return true;
    }

    promise->AppendNativeHandler(mPromiseWorkerProxy);
    return true;
  }
Example #3
0
already_AddRefed<Promise>
Cache::AddAll(const GlobalObject& aGlobal,
              nsTArray<RefPtr<Request>>&& aRequestList,
              CallerType aCallerType, ErrorResult& aRv)
{
  MOZ_DIAGNOSTIC_ASSERT(mActor);

  // If there is no work to do, then resolve immediately
  if (aRequestList.IsEmpty()) {
    RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
    if (NS_WARN_IF(!promise)) {
      return nullptr;
    }

    promise->MaybeResolveWithUndefined();
    return promise.forget();
  }

  AutoTArray<RefPtr<Promise>, 256> fetchList;
  fetchList.SetCapacity(aRequestList.Length());

  // Begin fetching each request in parallel.  For now, if an error occurs just
  // abandon our previous fetch calls.  In theory we could cancel them in the
  // future once fetch supports it.

  for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
    RequestOrUSVString requestOrString;
    requestOrString.SetAsRequest() = aRequestList[i];
    RefPtr<Promise> fetch = FetchRequest(mGlobal, requestOrString,
                                         RequestInit(), aCallerType, aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    fetchList.AppendElement(std::move(fetch));
  }

  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  RefPtr<FetchHandler> handler =
    new FetchHandler(mActor->GetWorkerHolder(), this,
                     std::move(aRequestList), promise);

  RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }
  fetchPromise->AppendNativeHandler(handler);

  return promise.forget();
}
Example #4
0
  virtual bool
  MainThreadRun() override
  {
    AssertIsOnMainThread();

    ErrorResult rv;
    RefPtr<Promise> promise = mBackingStore->GetLength(rv);
    promise->AppendNativeHandler(mPromiseWorkerProxy);
    if (NS_WARN_IF(rv.Failed())) {
      rv.SuppressException();
      mFailed = true;
    }

    return true;
  }
Example #5
0
void
GetEntryHelper::Run()
{
  MOZ_ASSERT(!mParts.IsEmpty());

  ErrorResult rv;
  RefPtr<Promise> promise = mDirectory->Get(mParts[0], rv);
  if (NS_WARN_IF(rv.Failed())) {
    rv.SuppressException();
    Error(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  mParts.RemoveElementAt(0);
  promise->AppendNativeHandler(this);
}
Example #6
0
void JSWindowActor::ReceiveMessageOrQuery(
    JSContext* aCx, const JSWindowActorMessageMeta& aMetadata,
    JS::Handle<JS::Value> aData, ErrorResult& aRv) {
  // The argument which we want to pass to IPC.
  RootedDictionary<ReceiveMessageArgument> argument(aCx);
  argument.mObjects = JS_NewPlainObject(aCx);
  argument.mTarget = this;
  argument.mName = aMetadata.messageName();
  argument.mData = aData;
  argument.mJson = aData;
  argument.mSync = false;

  JS::Rooted<JSObject*> self(aCx, GetWrapper());
  JS::Rooted<JSObject*> global(aCx, JS::GetNonCCWObjectGlobal(self));

  // We only need to create a promise if we're dealing with a query here. It
  // will be resolved or rejected once the listener has been called. Our
  // listener on this promise will then send the reply.
  RefPtr<Promise> promise;
  if (aMetadata.kind() == JSWindowActorMessageKind::Query) {
    promise = Promise::Create(xpc::NativeGlobal(global), aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return;
    }

    RefPtr<QueryHandler> handler = new QueryHandler(this, aMetadata);
    promise->AppendNativeHandler(handler);
  }

  // Invoke the actual callback.
  JS::Rooted<JS::Value> retval(aCx);
  RefPtr<MessageListener> messageListener =
      new MessageListener(self, global, nullptr, nullptr);
  messageListener->ReceiveMessage(argument, &retval, aRv,
                                  "JSWindowActor receive message");

  // If we have a promise, resolve or reject it respectively.
  if (promise) {
    if (aRv.Failed()) {
      promise->MaybeReject(aRv);
    } else {
      promise->MaybeResolve(aCx, retval);
    }
  }
}
  void
  WriteToCache(Cache* aCache)
  {
    AssertIsOnMainThread();
    MOZ_ASSERT(aCache);
    MOZ_ASSERT(mState == WaitingForOpen);

    ErrorResult result;
    nsCOMPtr<nsIInputStream> body;
    result = NS_NewCStringInputStream(getter_AddRefs(body),
                                      NS_ConvertUTF16toUTF8(mCN->Buffer()));
    if (NS_WARN_IF(result.Failed())) {
      MOZ_ASSERT(!result.IsErrorWithMessage());
      Fail(result.StealNSResult());
      return;
    }

    RefPtr<InternalResponse> ir =
      new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
    ir->SetBody(body, mCN->Buffer().Length());

    ir->InitChannelInfo(mChannelInfo);
    if (mPrincipalInfo) {
      ir->SetPrincipalInfo(Move(mPrincipalInfo));
    }

    RefPtr<Response> response = new Response(aCache->GetGlobalObject(), ir);

    RequestOrUSVString request;
    request.SetAsUSVString().Rebind(URL().Data(), URL().Length());

    // For now we have to wait until the Put Promise is fulfilled before we can
    // continue since Cache does not yet support starting a read that is being
    // written to.
    RefPtr<Promise> cachePromise = aCache->Put(request, *response, result);
    if (NS_WARN_IF(result.Failed())) {
      MOZ_ASSERT(!result.IsErrorWithMessage());
      Fail(result.StealNSResult());
      return;
    }

    mState = WaitingForPut;
    cachePromise->AppendNativeHandler(this);
  }
nsresult
CompareCache::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL,
                         const nsAString& aCacheName)
{
    MOZ_ASSERT(aPrincipal);
    AssertIsOnMainThread();

    mURL = aURL;

    ErrorResult rv;

    RefPtr<Promise> promise = mManager->CacheStorage_()->Open(aCacheName, rv);
    if (NS_WARN_IF(rv.Failed())) {
        MOZ_ASSERT(!rv.IsErrorWithMessage());
        return rv.StealNSResult();
    }

    promise->AppendNativeHandler(this);
    return NS_OK;
}
Example #9
0
NS_IMETHODIMP
FetchStreamReader::OnOutputStreamReady(nsIAsyncOutputStream* aStream)
{
  NS_ASSERT_OWNINGTHREAD(FetchStreamReader);
  MOZ_ASSERT(aStream == mPipeOut);
  MOZ_ASSERT(mReader);

  if (mStreamClosed) {
    return NS_OK;
  }

  if (mBuffer) {
    return WriteBuffer();
  }

  // TODO: We need to verify this is the correct global per the spec.
  //       See bug 1385890.
  AutoEntryScript aes(mGlobal, "ReadableStreamReader.read", !mWorkerHolder);

  JS::Rooted<JSObject*> reader(aes.cx(), mReader);
  JS::Rooted<JSObject*> promise(aes.cx(),
                                JS::ReadableStreamDefaultReaderRead(aes.cx(),
                                                                    reader));
  if (NS_WARN_IF(!promise)) {
    // Let's close the stream.
    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
    return NS_ERROR_FAILURE;
  }

  RefPtr<Promise> domPromise = Promise::CreateFromExisting(mGlobal, promise);
  if (NS_WARN_IF(!domPromise)) {
    // Let's close the stream.
    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
    return NS_ERROR_FAILURE;
  }

  // Let's wait.
  domPromise->AppendNativeHandler(this);
  return NS_OK;
}
Example #10
0
NS_IMETHODIMP
FetchStreamReader::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
  NS_ASSERT_OWNINGTHREAD(FetchStreamReader);
  MOZ_ASSERT(aStream == mPipeOut);
  MOZ_ASSERT(mReader);

  if (mStreamClosed) {
    return NS_OK;
  }

  if (mBuffer) {
    return WriteBuffer();
  }

  // Here we can retrieve data from the reader using any global we want because
  // it is not observable. We want to use the reader's global, which is also the
  // Response's one.
  AutoEntryScript aes(mGlobal, "ReadableStreamReader.read", !mWorkerRef);

  JS::Rooted<JSObject*> reader(aes.cx(), mReader);
  JS::Rooted<JSObject*> promise(
      aes.cx(), JS::ReadableStreamDefaultReaderRead(aes.cx(), reader));
  if (NS_WARN_IF(!promise)) {
    // Let's close the stream.
    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
    return NS_ERROR_FAILURE;
  }

  RefPtr<Promise> domPromise = Promise::CreateFromExisting(mGlobal, promise);
  if (NS_WARN_IF(!domPromise)) {
    // Let's close the stream.
    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
    return NS_ERROR_FAILURE;
  }

  // Let's wait.
  domPromise->AppendNativeHandler(this);
  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;
}
Example #12
0
  virtual bool
  MainThreadRun() override
  {
    AssertIsOnMainThread();

    // Walk up to the containing window.
    WorkerPrivate* wp = mWorkerPrivate;
    while (wp->GetParent()) {
      wp = wp->GetParent();
    }
    nsPIDOMWindowInner* window = wp->GetWindow();

    // TODO SharedWorker has null window. Don't need to worry about at this
    // point, though.
    if (!window) {
      mRv.Throw(NS_ERROR_FAILURE);
      return false;
    }

    RefPtr<Promise> promise =
      Navigator::GetDataStores(window, mName, mOwner, mRv);
    promise->AppendNativeHandler(mPromiseWorkerProxy);
    return true;
  }