Esempio n. 1
0
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                       mozilla::net::LoadInfoArgs* aLoadInfoArgs)
{
  nsresult rv = NS_OK;

  if (aLoadInfo) {
    rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(),
                                  &aLoadInfoArgs->requestingPrincipalInfo());
    NS_ENSURE_SUCCESS(rv, rv);
    rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
                                  &aLoadInfoArgs->triggeringPrincipalInfo());
    NS_ENSURE_SUCCESS(rv, rv);
    aLoadInfoArgs->securityFlags() = aLoadInfo->GetSecurityFlags();
    aLoadInfoArgs->contentPolicyType() = aLoadInfo->GetContentPolicyType();
    aLoadInfoArgs->innerWindowID() = aLoadInfo->GetInnerWindowID();
    aLoadInfoArgs->outerWindowID() = aLoadInfo->GetOuterWindowID();
    aLoadInfoArgs->parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID();
    return NS_OK;
  }

  // use default values if no loadInfo is provided
  rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(),
                                &aLoadInfoArgs->requestingPrincipalInfo());
  NS_ENSURE_SUCCESS(rv, rv);
  rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(),
                                &aLoadInfoArgs->triggeringPrincipalInfo());
  NS_ENSURE_SUCCESS(rv, rv);
  aLoadInfoArgs->securityFlags() = nsILoadInfo::SEC_NORMAL;
  aLoadInfoArgs->contentPolicyType() = nsIContentPolicy::TYPE_OTHER;
  aLoadInfoArgs->innerWindowID() = 0;
  aLoadInfoArgs->outerWindowID() = 0;
  aLoadInfoArgs->parentOuterWindowID() = 0;
  return NS_OK;
}
Esempio n. 2
0
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                       OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
{
  if (!aLoadInfo) {
    // if there is no loadInfo, then there is nothing to serialize
    *aOptionalLoadInfoArgs = void_t();
    return NS_OK;
  }

  nsresult rv = NS_OK;
  PrincipalInfo requestingPrincipalInfo;
  rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(),
                                &requestingPrincipalInfo);
  NS_ENSURE_SUCCESS(rv, rv);

  PrincipalInfo triggeringPrincipalInfo;
  rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
                                &triggeringPrincipalInfo);

  *aOptionalLoadInfoArgs =
    LoadInfoArgs(
      requestingPrincipalInfo,
      triggeringPrincipalInfo,
      aLoadInfo->GetSecurityFlags(),
      aLoadInfo->GetContentPolicyType(),
      aLoadInfo->GetUpgradeInsecureRequests(),
      aLoadInfo->GetInnerWindowID(),
      aLoadInfo->GetOuterWindowID(),
      aLoadInfo->GetParentOuterWindowID());

  return NS_OK;
}
Esempio n. 3
0
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                       OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
{
  if (!aLoadInfo) {
    // if there is no loadInfo, then there is nothing to serialize
    *aOptionalLoadInfoArgs = void_t();
    return NS_OK;
  }

  nsresult rv = NS_OK;
  PrincipalInfo requestingPrincipalInfo;
  rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(),
                                &requestingPrincipalInfo);
  NS_ENSURE_SUCCESS(rv, rv);

  PrincipalInfo triggeringPrincipalInfo;
  rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
                                &triggeringPrincipalInfo);

  nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects;
  for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) {
    rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsTArray<PrincipalInfo> redirectChain;
  for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) {
    rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  *aOptionalLoadInfoArgs =
    LoadInfoArgs(
      requestingPrincipalInfo,
      triggeringPrincipalInfo,
      aLoadInfo->GetSecurityFlags(),
      aLoadInfo->InternalContentPolicyType(),
      aLoadInfo->GetUpgradeInsecureRequests(),
      aLoadInfo->GetUpgradeInsecurePreloads(),
      aLoadInfo->GetInnerWindowID(),
      aLoadInfo->GetOuterWindowID(),
      aLoadInfo->GetParentOuterWindowID(),
      aLoadInfo->GetEnforceSecurity(),
      aLoadInfo->GetInitialSecurityCheckDone(),
      aLoadInfo->GetIsInThirdPartyContext(),
      aLoadInfo->GetOriginAttributes(),
      redirectChainIncludingInternalRedirects,
      redirectChain);

  return NS_OK;
}
Esempio n. 4
0
// static
nsresult
IDBFactory::CreateForMainThreadJS(JSContext* aCx,
                                  JS::Handle<JSObject*> aOwningObject,
                                  IDBFactory** aFactory)
{
    MOZ_ASSERT(NS_IsMainThread());

    nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo());
    nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aOwningObject);
    MOZ_ASSERT(principal);
    bool isSystem;
    if (!AllowedForPrincipal(principal, &isSystem)) {
        return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
    }

    nsresult rv = PrincipalToPrincipalInfo(principal, principalInfo);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
    }

    rv = CreateForMainThreadJSInternal(aCx, aOwningObject, principalInfo, aFactory);
    if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
    }

    MOZ_ASSERT(!principalInfo);

    return NS_OK;
}
Esempio n. 5
0
  bool MainThreadRun() override
  {
    MOZ_ASSERT(NS_IsMainThread());

    nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
    if (!principal) {
      mRv.Throw(NS_ERROR_FAILURE);
      return true;
    }

    bool isNullPrincipal;
    mRv = principal->GetIsNullPrincipal(&isNullPrincipal);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    if (NS_WARN_IF(isNullPrincipal)) {
      mRv.Throw(NS_ERROR_FAILURE);
      return true;
    }

    mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    mRv = principal->GetOrigin(mOrigin);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    // Walk up to our containing page
    WorkerPrivate* wp = mWorkerPrivate;
    while (wp->GetParent()) {
      wp = wp->GetParent();
    }

    // Window doesn't exist for some kind of workers (eg: SharedWorkers)
    nsPIDOMWindow* window = wp->GetWindow();
    if (!window) {
      return true;
    }

    nsIDocument* doc = window->GetExtantDoc();
    if (doc) {
      mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);

      // No bfcache when BroadcastChannel is used.
      doc->DisallowBFCaching();
    }

    return true;
  }
Esempio n. 6
0
nsresult
FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver)
{
  AssertIsOnMainThread();
#ifdef DEBUG
  MOZ_ASSERT(!mFetchCalled);
  mFetchCalled = true;
#endif

  mObserver = aObserver;

  Telemetry::Accumulate(Telemetry::SERVICE_WORKER_REQUEST_PASSTHROUGH,
                        mRequest->WasCreatedByFetchEvent());

  // FIXME(nsm): Deal with HSTS.

  MOZ_RELEASE_ASSERT(!mRequest->IsSynchronous(),
                     "Synchronous fetch not supported");


  UniquePtr<mozilla::ipc::PrincipalInfo> principalInfo(new mozilla::ipc::PrincipalInfo());
  nsresult rv = PrincipalToPrincipalInfo(mPrincipal, principalInfo.get());
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  mRequest->SetPrincipalInfo(std::move(principalInfo));

  // If the signal is aborted, it's time to inform the observer and terminate
  // the operation.
  if (aSignal) {
    if (aSignal->Aborted()) {
      Abort();
      return NS_OK;
    }

    Follow(aSignal);
  }

  rv = HttpFetch(mRequest->GetPreferredAlternativeDataType());
  if (NS_FAILED(rv)) {
    FailWithNetworkError(rv);
  }

  // Any failure is handled by FailWithNetworkError notifying the aObserver.
  return NS_OK;
}
Esempio n. 7
0
  bool MainThreadRun() override
  {
    MOZ_ASSERT(NS_IsMainThread());

    nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
    if (!principal) {
      mRv.Throw(NS_ERROR_FAILURE);
      return true;
    }

    bool isNullPrincipal;
    mRv = principal->GetIsNullPrincipal(&isNullPrincipal);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    if (NS_WARN_IF(isNullPrincipal)) {
      mRv.Throw(NS_ERROR_FAILURE);
      return true;
    }

    mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    mRv = principal->GetOrigin(mOrigin);
    if (NS_WARN_IF(mRv.Failed())) {
      return true;
    }

    // Walk up to our containing page
    WorkerPrivate* wp = mWorkerPrivate;
    while (wp->GetParent()) {
      wp = wp->GetParent();
    }

    // Window doesn't exist for some kind of workers (eg: SharedWorkers)
    nsPIDOMWindowInner* window = wp->GetWindow();
    if (!window) {
      return true;
    }

    return true;
  }
Esempio n. 8
0
nsresult CheckedPrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
                                         PrincipalInfo& aPrincipalInfo) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aPrincipal);

  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (NS_WARN_IF(!QuotaManager::IsPrincipalInfoValid(aPrincipalInfo))) {
    return NS_ERROR_FAILURE;
  }

  if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
      aPrincipalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}
Esempio n. 9
0
/* static */ already_AddRefed<BroadcastChannel>
BroadcastChannel::Constructor(const GlobalObject& aGlobal,
                              const nsAString& aChannel,
                              ErrorResult& aRv)
{
  nsCOMPtr<nsPIDOMWindowInner> window =
    do_QueryInterface(aGlobal.GetAsSupports());
  // Window is null in workers.

  RefPtr<BroadcastChannel> bc = new BroadcastChannel(window, aChannel);

  nsAutoCString origin;
  PrincipalInfo principalInfo;

  if (NS_IsMainThread()) {
    nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();

    if (!incumbent) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    nsIPrincipal* principal = incumbent->PrincipalOrNull();
    if (!principal) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    aRv = principal->GetOrigin(origin);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }
  } else {
    JSContext* cx = aGlobal.Context();

    WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
    MOZ_ASSERT(workerPrivate);

    RefPtr<StrongWorkerRef> workerRef =
      StrongWorkerRef::Create(workerPrivate, "BroadcastChannel",
                              [bc] () { bc->Shutdown(); });
    // We are already shutting down the worker. Let's return a non-active
    // object.
    if (NS_WARN_IF(!workerRef)) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    RefPtr<ThreadSafeWorkerRef> tsr = new ThreadSafeWorkerRef(workerRef);

    RefPtr<InitializeRunnable> runnable =
      new InitializeRunnable(tsr, origin, principalInfo, aRv);
    runnable->Dispatch(Canceling, aRv);
    if (aRv.Failed()) {
      return nullptr;
    }

    bc->mWorkerRef = Move(workerRef);
  }

  // Register this component to PBackground.
  PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
  if (NS_WARN_IF(!actorChild)) {
    // Firefox is probably shutting down. Let's return a 'generic' error.
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  PBroadcastChannelChild* actor =
    actorChild->SendPBroadcastChannelConstructor(principalInfo, origin,
                                                 nsString(aChannel));

  bc->mActor = static_cast<BroadcastChannelChild*>(actor);
  MOZ_ASSERT(bc->mActor);

  bc->mActor->SetParent(bc);

  return bc.forget();
}
Esempio n. 10
0
already_AddRefed<IDBOpenDBRequest>
IDBFactory::OpenInternal(JSContext* aCx,
                         nsIPrincipal* aPrincipal,
                         const nsAString& aName,
                         const Optional<uint64_t>& aVersion,
                         const Optional<StorageType>& aStorageType,
                         bool aDeleting,
                         ErrorResult& aRv)
{
    MOZ_ASSERT(mWindow || mOwningObject);
    MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode);

    CommonFactoryRequestParams commonParams;
    commonParams.privateBrowsingMode() = mPrivateBrowsingMode;

    PrincipalInfo& principalInfo = commonParams.principalInfo();

    if (aPrincipal) {
        if (!NS_IsMainThread()) {
            MOZ_CRASH("Figure out security checks for workers!");
        }
        MOZ_ASSERT(nsContentUtils::IsCallerChrome());

        if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal,
                                 &principalInfo)))) {
            IDB_REPORT_INTERNAL_ERR();
            aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
            return nullptr;
        }

        if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
                principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
            IDB_REPORT_INTERNAL_ERR();
            aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
            return nullptr;
        }
    } else {
        principalInfo = *mPrincipalInfo;
    }

    uint64_t version = 0;
    if (!aDeleting && aVersion.WasPassed()) {
        if (aVersion.Value() < 1) {
            aRv.ThrowTypeError<MSG_INVALID_VERSION>();
            return nullptr;
        }
        version = aVersion.Value();
    }

    // Nothing can be done here if we have previously failed to create a
    // background actor.
    if (mBackgroundActorFailed) {
        IDB_REPORT_INTERNAL_ERR();
        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        return nullptr;
    }

    PersistenceType persistenceType;

    if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
        // Chrome privilege always gets persistent storage.
        persistenceType = PERSISTENCE_TYPE_PERSISTENT;
    } else {
        persistenceType = PersistenceTypeFromStorage(aStorageType);
    }

    DatabaseMetadata& metadata = commonParams.metadata();
    metadata.name() = aName;
    metadata.persistenceType() = persistenceType;

    FactoryRequestParams params;
    if (aDeleting) {
        metadata.version() = 0;
        params = DeleteDatabaseRequestParams(commonParams);
    } else {
        metadata.version() = version;
        params = OpenDatabaseRequestParams(commonParams);
    }

    if (!mBackgroundActor && mPendingRequests.IsEmpty()) {
        BackgroundChildImpl::ThreadLocal* threadLocal =
            BackgroundChildImpl::GetThreadLocalForCurrentThread();

        nsAutoPtr<ThreadLocal> newIDBThreadLocal;
        ThreadLocal* idbThreadLocal;

        if (threadLocal && threadLocal->mIndexedDBThreadLocal) {
            idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
        } else {
            nsCOMPtr<nsIUUIDGenerator> uuidGen =
                do_GetService("@mozilla.org/uuid-generator;1");
            MOZ_ASSERT(uuidGen);

            nsID id;
            MOZ_ALWAYS_SUCCEEDS(uuidGen->GenerateUUIDInPlace(&id));

            newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id);
        }

        if (PBackgroundChild* actor = BackgroundChild::GetForCurrentThread()) {
            BackgroundActorCreated(actor, idbThreadLocal->GetLoggingInfo());
        } else {
            // We need to start the sequence to create a background actor for this
            // thread.
            RefPtr<BackgroundCreateCallback> cb =
                new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo());
            if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) {
                IDB_REPORT_INTERNAL_ERR();
                aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
                return nullptr;
            }
        }

        if (newIDBThreadLocal) {
            if (!threadLocal) {
                threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread();
            }
            MOZ_ASSERT(threadLocal);
            MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal);

            threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
        }
    }

    RefPtr<IDBOpenDBRequest> request;

    if (mWindow) {
        JS::Rooted<JSObject*> scriptOwner(aCx,
                                          nsGlobalWindow::Cast(mWindow.get())->FastGetGlobalJSObject());
        MOZ_ASSERT(scriptOwner);

        request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner);
    } else {
        JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject);

        request = IDBOpenDBRequest::CreateForJS(aCx, this, scriptOwner);
        if (!request) {
            MOZ_ASSERT(!NS_IsMainThread());
            aRv.ThrowUncatchableException();
            return nullptr;
        }
    }

    MOZ_ASSERT(request);

    if (aDeleting) {
        IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
                     "indexedDB.deleteDatabase(\"%s\")",
                     "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()",
                     IDB_LOG_ID_STRING(),
                     request->LoggingSerialNumber(),
                     NS_ConvertUTF16toUTF8(aName).get());
    } else {
        IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
                     "indexedDB.open(\"%s\", %s)",
                     "IndexedDB %s: C R[%llu]: IDBFactory.open()",
                     IDB_LOG_ID_STRING(),
                     request->LoggingSerialNumber(),
                     NS_ConvertUTF16toUTF8(aName).get(),
                     IDB_LOG_STRINGIFY(aVersion));
    }

    // If we already have a background actor then we can start this request now.
    if (mBackgroundActor) {
        nsresult rv = InitiateRequest(request, params);
        if (NS_WARN_IF(NS_FAILED(rv))) {
            IDB_REPORT_INTERNAL_ERR();
            aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
            return nullptr;
        }
    } else {
        mPendingRequests.AppendElement(new PendingRequestInfo(request, params));
    }

    return request.forget();
}
Esempio n. 11
0
/*static*/
already_AddRefed<Response> Response::Constructor(
    const GlobalObject& aGlobal,
    const Optional<Nullable<fetch::ResponseBodyInit>>& aBody,
    const ResponseInit& aInit, ErrorResult& aRv) {
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());

  if (NS_WARN_IF(!global)) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return nullptr;
  }

  if (aInit.mStatus < 200 || aInit.mStatus > 599) {
    aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>();
    return nullptr;
  }

  // Check if the status text contains illegal characters
  nsACString::const_iterator start, end;
  aInit.mStatusText.BeginReading(start);
  aInit.mStatusText.EndReading(end);
  if (FindCharInReadable('\r', start, end)) {
    aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>();
    return nullptr;
  }
  // Reset iterator since FindCharInReadable advances it.
  aInit.mStatusText.BeginReading(start);
  if (FindCharInReadable('\n', start, end)) {
    aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>();
    return nullptr;
  }

  RefPtr<InternalResponse> internalResponse =
      new InternalResponse(aInit.mStatus, aInit.mStatusText);

  UniquePtr<mozilla::ipc::PrincipalInfo> principalInfo;

  // Grab a valid channel info from the global so this response is 'valid' for
  // interception.
  if (NS_IsMainThread()) {
    ChannelInfo info;
    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
    if (window) {
      Document* doc = window->GetExtantDoc();
      MOZ_ASSERT(doc);
      info.InitFromDocument(doc);

      principalInfo.reset(new mozilla::ipc::PrincipalInfo());
      nsresult rv =
          PrincipalToPrincipalInfo(doc->NodePrincipal(), principalInfo.get());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
        return nullptr;
      }

      internalResponse->InitChannelInfo(info);
    } else if (nsContentUtils::IsSystemPrincipal(global->PrincipalOrNull())) {
      info.InitFromChromeGlobal(global);

      internalResponse->InitChannelInfo(info);
    }

    /**
     * The channel info is left uninitialized if neither the above `if` nor
     * `else if` statements are executed; this could be because we're in a
     * WebExtensions content script, where the global (i.e. `global`) is a
     * wrapper, and the principal is an expanded principal. In this case,
     * as far as I can tell, there's no way to get the security info, but we'd
     * like the `Response` to be successfully constructed.
     */
  } else {
    WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
    MOZ_ASSERT(worker);
    internalResponse->InitChannelInfo(worker->GetChannelInfo());
    principalInfo =
        MakeUnique<mozilla::ipc::PrincipalInfo>(worker->GetPrincipalInfo());
  }

  internalResponse->SetPrincipalInfo(std::move(principalInfo));

  RefPtr<Response> r = new Response(global, internalResponse, nullptr);

  if (aInit.mHeaders.WasPassed()) {
    internalResponse->Headers()->Clear();

    // Instead of using Fill, create an object to allow the constructor to
    // unwrap the HeadersInit.
    RefPtr<Headers> headers =
        Headers::Create(global, aInit.mHeaders.Value(), aRv);
    if (aRv.Failed()) {
      return nullptr;
    }

    internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }
  }

  if (aBody.WasPassed() && !aBody.Value().IsNull()) {
    if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) {
      aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>();
      return nullptr;
    }

    nsCString contentTypeWithCharset;
    nsCOMPtr<nsIInputStream> bodyStream;
    int64_t bodySize = InternalResponse::UNKNOWN_BODY_SIZE;

    const fetch::ResponseBodyInit& body = aBody.Value().Value();
    if (body.IsReadableStream()) {
      aRv.MightThrowJSException();

      JSContext* cx = aGlobal.Context();
      const ReadableStream& readableStream = body.GetAsReadableStream();

      JS::Rooted<JSObject*> readableStreamObj(cx, readableStream.Obj());

      bool disturbed;
      bool locked;
      if (!JS::ReadableStreamIsDisturbed(cx, readableStreamObj, &disturbed) ||
          !JS::ReadableStreamIsLocked(cx, readableStreamObj, &locked)) {
        aRv.StealExceptionFromJSContext(cx);
        return nullptr;
      }
      if (disturbed || locked) {
        aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
        return nullptr;
      }

      r->SetReadableStreamBody(cx, readableStreamObj);

      JS::ReadableStreamMode streamMode;
      if (!JS::ReadableStreamGetMode(cx, readableStreamObj, &streamMode)) {
        aRv.StealExceptionFromJSContext(cx);
        return nullptr;
      }
      if (streamMode == JS::ReadableStreamMode::ExternalSource) {
        // If this is a DOM generated ReadableStream, we can extract the
        // inputStream directly.
        JS::ReadableStreamUnderlyingSource* underlyingSource = nullptr;
        if (!JS::ReadableStreamGetExternalUnderlyingSource(
                cx, readableStreamObj, &underlyingSource)) {
          aRv.StealExceptionFromJSContext(cx);
          return nullptr;
        }

        MOZ_ASSERT(underlyingSource);

        aRv = FetchStream::RetrieveInputStream(underlyingSource,
                                               getter_AddRefs(bodyStream));

        // The releasing of the external source is needed in order to avoid an
        // extra stream lock.
        if (!JS::ReadableStreamReleaseExternalUnderlyingSource(
                cx, readableStreamObj)) {
          aRv.StealExceptionFromJSContext(cx);
          return nullptr;
        }
        if (NS_WARN_IF(aRv.Failed())) {
          return nullptr;
        }
      } else {
        // If this is a JS-created ReadableStream, let's create a
        // FetchStreamReader.
        aRv = FetchStreamReader::Create(aGlobal.Context(), global,
                                        getter_AddRefs(r->mFetchStreamReader),
                                        getter_AddRefs(bodyStream));
        if (NS_WARN_IF(aRv.Failed())) {
          return nullptr;
        }
      }
    } else {
      uint64_t size = 0;
      aRv = ExtractByteStreamFromBody(body, getter_AddRefs(bodyStream),
                                      contentTypeWithCharset, size);
      if (NS_WARN_IF(aRv.Failed())) {
        return nullptr;
      }

      bodySize = size;
    }

    internalResponse->SetBody(bodyStream, bodySize);

    if (!contentTypeWithCharset.IsVoid() &&
        !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"),
                                          aRv)) {
      // Ignore Append() failing here.
      ErrorResult error;
      internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"),
                                          contentTypeWithCharset, error);
      error.SuppressException();
    }

    if (aRv.Failed()) {
      return nullptr;
    }
  }

  r->SetMimeType();
  return r.forget();
}
Esempio n. 12
0
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
                       OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
{
  if (!aLoadInfo) {
    // if there is no loadInfo, then there is nothing to serialize
    *aOptionalLoadInfoArgs = void_t();
    return NS_OK;
  }

  nsresult rv = NS_OK;
  OptionalPrincipalInfo loadingPrincipalInfo = mozilla::void_t();
  if (aLoadInfo->LoadingPrincipal()) {
    PrincipalInfo loadingPrincipalInfoTemp;
    rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(),
                                  &loadingPrincipalInfoTemp);
    NS_ENSURE_SUCCESS(rv, rv);
    loadingPrincipalInfo = loadingPrincipalInfoTemp;
  }

  PrincipalInfo triggeringPrincipalInfo;
  rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
                                &triggeringPrincipalInfo);

  nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects;
  for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) {
    rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsTArray<PrincipalInfo> redirectChain;
  for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) {
    rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  *aOptionalLoadInfoArgs =
    LoadInfoArgs(
      loadingPrincipalInfo,
      triggeringPrincipalInfo,
      aLoadInfo->GetSecurityFlags(),
      aLoadInfo->InternalContentPolicyType(),
      static_cast<uint32_t>(aLoadInfo->GetTainting()),
      aLoadInfo->GetUpgradeInsecureRequests(),
      aLoadInfo->GetVerifySignedContent(),
      aLoadInfo->GetEnforceSRI(),
      aLoadInfo->GetForceInheritPrincipalDropped(),
      aLoadInfo->GetInnerWindowID(),
      aLoadInfo->GetOuterWindowID(),
      aLoadInfo->GetParentOuterWindowID(),
      aLoadInfo->GetFrameOuterWindowID(),
      aLoadInfo->GetEnforceSecurity(),
      aLoadInfo->GetInitialSecurityCheckDone(),
      aLoadInfo->GetIsInThirdPartyContext(),
      aLoadInfo->GetOriginAttributes(),
      redirectChainIncludingInternalRedirects,
      redirectChain,
      aLoadInfo->CorsUnsafeHeaders(),
      aLoadInfo->GetForcePreflight(),
      aLoadInfo->GetIsPreflight());

  return NS_OK;
}
Esempio n. 13
0
nsresult
PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
                         PrincipalInfo* aPrincipalInfo)
{
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aPrincipal);
  MOZ_ASSERT(aPrincipalInfo);

  bool isNullPrin;
  nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrin);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (isNullPrin) {
    *aPrincipalInfo = NullPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef());
    return NS_OK;
  }

  nsCOMPtr<nsIScriptSecurityManager> secMan =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  bool isSystemPrincipal;
  rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (isSystemPrincipal) {
    *aPrincipalInfo = SystemPrincipalInfo();
    return NS_OK;
  }

  // might be an expanded principal
  nsCOMPtr<nsIExpandedPrincipal> expanded =
    do_QueryInterface(aPrincipal);

  if (expanded) {
    nsTArray<PrincipalInfo> whitelistInfo;
    PrincipalInfo info;

    nsTArray< nsCOMPtr<nsIPrincipal> >* whitelist;
    MOZ_ALWAYS_SUCCEEDS(expanded->GetWhiteList(&whitelist));

    for (uint32_t i = 0; i < whitelist->Length(); i++) {
      rv = PrincipalToPrincipalInfo((*whitelist)[i], &info);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }
      // append that spec to the whitelist
      whitelistInfo.AppendElement(info);
    }

    *aPrincipalInfo =
      ExpandedPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(),
                            Move(whitelistInfo));
    return NS_OK;
  }

  // must be a content principal

  nsCOMPtr<nsIURI> uri;
  rv = aPrincipal->GetURI(getter_AddRefs(uri));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (NS_WARN_IF(!uri)) {
    return NS_ERROR_FAILURE;
  }

  nsCString spec;
  rv = uri->GetSpec(spec);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  *aPrincipalInfo = ContentPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(),
                                         spec);
  return NS_OK;
}
Esempio n. 14
0
already_AddRefed<IDBOpenDBRequest>
IDBFactory::OpenInternal(JSContext* aCx,
                         nsIPrincipal* aPrincipal,
                         const nsAString& aName,
                         const Optional<uint64_t>& aVersion,
                         const Optional<StorageType>& aStorageType,
                         bool aDeleting,
                         CallerType aCallerType,
                         ErrorResult& aRv)
{
  MOZ_ASSERT(mWindow || mOwningObject);
  MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode);

  CommonFactoryRequestParams commonParams;

  PrincipalInfo& principalInfo = commonParams.principalInfo();

  if (aPrincipal) {
    if (!NS_IsMainThread()) {
      MOZ_CRASH("Figure out security checks for workers!  What's this "
                "aPrincipal we have on a worker thread?");
    }
    MOZ_ASSERT(aCallerType == CallerType::System);
    MOZ_DIAGNOSTIC_ASSERT(mPrivateBrowsingMode == (aPrincipal->GetPrivateBrowsingId() > 0));

    if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal,
                                                      &principalInfo)))) {
      IDB_REPORT_INTERNAL_ERR();
      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
      return nullptr;
    }

    if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
        principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
      IDB_REPORT_INTERNAL_ERR();
      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
      return nullptr;
    }
  } else {
    principalInfo = *mPrincipalInfo;
  }

  uint64_t version = 0;
  if (!aDeleting && aVersion.WasPassed()) {
    if (aVersion.Value() < 1) {
      aRv.ThrowTypeError<MSG_INVALID_VERSION>();
      return nullptr;
    }
    version = aVersion.Value();
  }

  // Nothing can be done here if we have previously failed to create a
  // background actor.
  if (mBackgroundActorFailed) {
    IDB_REPORT_INTERNAL_ERR();
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    return nullptr;
  }

  PersistenceType persistenceType;

  bool isInternal = principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo;
  if (!isInternal && principalInfo.type() == PrincipalInfo::TContentPrincipalInfo) {
    nsCString origin = principalInfo.get_ContentPrincipalInfo().originNoSuffix();
    isInternal = QuotaManager::IsOriginInternal(origin);
  }

  // Allow storage attributes for add-ons independent of the pref.
  // This works in the main thread only, workers don't have the principal.
  bool isAddon = false;
  if (NS_IsMainThread()) {
    // aPrincipal is passed inconsistently, so even when we are already on
    // the main thread, we may have been passed a null aPrincipal.
    nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(principalInfo);
    if (principal) {
      nsAutoString addonId;
      Unused << NS_WARN_IF(NS_FAILED(principal->GetAddonId(addonId)));
      isAddon = !addonId.IsEmpty();
    }
  }

  if (isInternal) {
    // Chrome privilege and internal origins always get persistent storage.
    persistenceType = PERSISTENCE_TYPE_PERSISTENT;
  } else if (isAddon || DOMPrefs::IndexedDBStorageOptionsEnabled()) {
    persistenceType = PersistenceTypeFromStorage(aStorageType);
  } else {
    persistenceType = PERSISTENCE_TYPE_DEFAULT;
  }

  DatabaseMetadata& metadata = commonParams.metadata();
  metadata.name() = aName;
  metadata.persistenceType() = persistenceType;

  FactoryRequestParams params;
  if (aDeleting) {
    metadata.version() = 0;
    params = DeleteDatabaseRequestParams(commonParams);
  } else {
    metadata.version() = version;
    params = OpenDatabaseRequestParams(commonParams);
  }

  if (!mBackgroundActor) {
    BackgroundChildImpl::ThreadLocal* threadLocal =
      BackgroundChildImpl::GetThreadLocalForCurrentThread();

    nsAutoPtr<ThreadLocal> newIDBThreadLocal;
    ThreadLocal* idbThreadLocal;

    if (threadLocal && threadLocal->mIndexedDBThreadLocal) {
      idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
    } else {
      nsCOMPtr<nsIUUIDGenerator> uuidGen =
        do_GetService("@mozilla.org/uuid-generator;1");
      MOZ_ASSERT(uuidGen);

      nsID id;
      MOZ_ALWAYS_SUCCEEDS(uuidGen->GenerateUUIDInPlace(&id));

      newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id);
    }

    PBackgroundChild* backgroundActor =
      BackgroundChild::GetOrCreateForCurrentThread();
    if (NS_WARN_IF(!backgroundActor)) {
      IDB_REPORT_INTERNAL_ERR();
      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
      return nullptr;
    }

    {
      BackgroundFactoryChild* actor = new BackgroundFactoryChild(this);

      // Set EventTarget for the top-level actor.
      // All child actors created later inherit the same event target.
      backgroundActor->SetEventTargetForActor(actor, EventTarget());
      MOZ_ASSERT(actor->GetActorEventTarget());
      mBackgroundActor =
        static_cast<BackgroundFactoryChild*>(
          backgroundActor->SendPBackgroundIDBFactoryConstructor(actor,
                                                                idbThreadLocal->GetLoggingInfo()));

      if (NS_WARN_IF(!mBackgroundActor)) {
        mBackgroundActorFailed = true;
        IDB_REPORT_INTERNAL_ERR();
        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        return nullptr;
      }
    }

    if (newIDBThreadLocal) {
      if (!threadLocal) {
        threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread();
      }
      MOZ_ASSERT(threadLocal);
      MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal);

      threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
    }
  }

  RefPtr<IDBOpenDBRequest> request;

  if (mWindow) {
    JS::Rooted<JSObject*> scriptOwner(aCx,
                                      nsGlobalWindowInner::Cast(mWindow.get())->FastGetGlobalJSObject());
    MOZ_ASSERT(scriptOwner);

    request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner);
  } else {
    JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject);

    request = IDBOpenDBRequest::CreateForJS(aCx, this, scriptOwner);
    if (!request) {
      MOZ_ASSERT(!NS_IsMainThread());
      aRv.ThrowUncatchableException();
      return nullptr;
    }
  }

  MOZ_ASSERT(request);

  if (aDeleting) {
    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
                   "indexedDB.deleteDatabase(\"%s\")",
                 "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()",
                 IDB_LOG_ID_STRING(),
                 request->LoggingSerialNumber(),
                 NS_ConvertUTF16toUTF8(aName).get());
  } else {
    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
                   "indexedDB.open(\"%s\", %s)",
                 "IndexedDB %s: C R[%llu]: IDBFactory.open()",
                 IDB_LOG_ID_STRING(),
                 request->LoggingSerialNumber(),
                 NS_ConvertUTF16toUTF8(aName).get(),
                 IDB_LOG_STRINGIFY(aVersion));
  }

  nsresult rv = InitiateRequest(request, params);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    IDB_REPORT_INTERNAL_ERR();
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    return nullptr;
  }

  return request.forget();
}
Esempio n. 15
0
nsresult
PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
                         PrincipalInfo* aPrincipalInfo)
{
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aPrincipal);
  MOZ_ASSERT(aPrincipalInfo);

  bool isNullPointer;
  nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPointer);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (isNullPointer) {
    *aPrincipalInfo = NullPrincipalInfo();
    return NS_OK;
  }

  nsCOMPtr<nsIScriptSecurityManager> secMan =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  bool isSystemPrincipal;
  rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (isSystemPrincipal) {
    *aPrincipalInfo = SystemPrincipalInfo();
    return NS_OK;
  }

  // might be an expanded principal
  nsCOMPtr<nsIExpandedPrincipal> expanded =
    do_QueryInterface(aPrincipal);

  if (expanded) {
    nsTArray<PrincipalInfo> whitelistInfo;
    PrincipalInfo info;

    nsTArray< nsCOMPtr<nsIPrincipal> >* whitelist;
    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(expanded->GetWhiteList(&whitelist)));

    for (uint32_t i = 0; i < whitelist->Length(); i++) {
      rv = PrincipalToPrincipalInfo((*whitelist)[i], &info);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }
      // append that spec to the whitelist
      whitelistInfo.AppendElement(info);
    }

    *aPrincipalInfo = ExpandedPrincipalInfo(Move(whitelistInfo));
    return NS_OK;
  }

  // must be a content principal

  nsCOMPtr<nsIURI> uri;
  rv = aPrincipal->GetURI(getter_AddRefs(uri));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (NS_WARN_IF(!uri)) {
    return NS_ERROR_FAILURE;
  }

  nsCString spec;
  rv = uri->GetSpec(spec);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  bool isUnknownAppId;
  rv = aPrincipal->GetUnknownAppId(&isUnknownAppId);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  uint32_t appId;
  if (isUnknownAppId) {
    appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
  } else {
    rv = aPrincipal->GetAppId(&appId);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  bool isInBrowserElement;
  rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  *aPrincipalInfo = ContentPrincipalInfo(appId, isInBrowserElement, spec);
  return NS_OK;
}
Esempio n. 16
0
/* static */ already_AddRefed<BroadcastChannel>
BroadcastChannel::Constructor(const GlobalObject& aGlobal,
                              const nsAString& aChannel,
                              ErrorResult& aRv)
{
  nsCOMPtr<nsPIDOMWindowInner> window =
    do_QueryInterface(aGlobal.GetAsSupports());
  // Window is null in workers.

  nsAutoCString origin;
  PrincipalInfo principalInfo;
  WorkerPrivate* workerPrivate = nullptr;

  if (NS_IsMainThread()) {
    nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();

    if (!incumbent) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    nsIPrincipal* principal = incumbent->PrincipalOrNull();
    if (!principal) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    aRv = principal->GetOrigin(origin);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }
  } else {
    JSContext* cx = aGlobal.Context();
    workerPrivate = GetWorkerPrivateFromContext(cx);
    MOZ_ASSERT(workerPrivate);

    RefPtr<InitializeRunnable> runnable =
      new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
    runnable->Dispatch(Closing, aRv);
  }

  if (aRv.Failed()) {
    return nullptr;
  }

  RefPtr<BroadcastChannel> bc =
    new BroadcastChannel(window, principalInfo, origin, aChannel);

  // Register this component to PBackground.
  PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
  if (actor) {
    bc->ActorCreated(actor);
  } else {
    BackgroundChild::GetOrCreateForCurrentThread(bc);
  }

  if (!workerPrivate) {
    MOZ_ASSERT(window);
    MOZ_ASSERT(window->IsInnerWindow());
    bc->mInnerID = window->WindowID();

    // Register as observer for inner-window-destroyed.
    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    if (obs) {
      obs->AddObserver(bc, "inner-window-destroyed", false);
    }
  } else {
    bc->mWorkerHolder = new BroadcastChannelWorkerHolder(bc);
    if (NS_WARN_IF(!bc->mWorkerHolder->HoldWorker(workerPrivate, Closing))) {
      bc->mWorkerHolder = nullptr;
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }
  }

  return bc.forget();
}
Esempio n. 17
0
/* static */ already_AddRefed<BroadcastChannel>
BroadcastChannel::Constructor(const GlobalObject& aGlobal,
                              const nsAString& aChannel,
                              ErrorResult& aRv)
{
  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
  // Window is null in workers.

  nsAutoString origin;
  PrincipalInfo principalInfo;
  bool privateBrowsing = false;
  WorkerPrivate* workerPrivate = nullptr;

  if (NS_IsMainThread()) {
    nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();

    if (!incumbent) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    nsIPrincipal* principal = incumbent->PrincipalOrNull();
    if (!principal) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return nullptr;
    }

    bool isNullPrincipal;
    aRv = principal->GetIsNullPrincipal(&isNullPrincipal);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    if (NS_WARN_IF(isNullPrincipal)) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    GetOrigin(principal, origin, aRv);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
    if (NS_WARN_IF(aRv.Failed())) {
      return nullptr;
    }

    nsIDocument* doc = window->GetExtantDoc();
    if (doc) {
      privateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);

      // No bfcache when BroadcastChannel is used.
      doc->DisallowBFCaching();
    }
  } else {
    JSContext* cx = aGlobal.Context();
    workerPrivate = GetWorkerPrivateFromContext(cx);
    MOZ_ASSERT(workerPrivate);

    nsRefPtr<InitializeRunnable> runnable =
      new InitializeRunnable(workerPrivate, origin, principalInfo,
                             privateBrowsing, aRv);
    runnable->Dispatch(cx);
  }

  if (aRv.Failed()) {
    return nullptr;
  }

  nsRefPtr<BroadcastChannel> bc =
    new BroadcastChannel(window, principalInfo, origin, aChannel,
                         privateBrowsing);

  // Register this component to PBackground.
  PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
  if (actor) {
    bc->ActorCreated(actor);
  } else {
    BackgroundChild::GetOrCreateForCurrentThread(bc);
  }

  if (!workerPrivate) {
    MOZ_ASSERT(window);
    MOZ_ASSERT(window->IsInnerWindow());
    bc->mInnerID = window->WindowID();

    // Register as observer for inner-window-destroyed.
    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    if (obs) {
      obs->AddObserver(bc, "inner-window-destroyed", false);
    }
  } else {
    bc->mWorkerFeature = new BroadcastChannelFeature(bc);
    JSContext* cx = workerPrivate->GetJSContext();
    if (NS_WARN_IF(!workerPrivate->AddFeature(cx, bc->mWorkerFeature))) {
      NS_WARNING("Failed to register the BroadcastChannel worker feature.");
      bc->mWorkerFeature = nullptr;
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }
  }

  return bc.forget();
}