示例#1
0
// static
already_AddRefed<IDBLocaleAwareKeyRange>
IDBLocaleAwareKeyRange::Bound(const GlobalObject& aGlobal,
                              JS::Handle<JS::Value> aLower,
                              JS::Handle<JS::Value> aUpper,
                              bool aLowerOpen,
                              bool aUpperOpen,
                              ErrorResult& aRv)
{
  RefPtr<IDBLocaleAwareKeyRange> keyRange =
    new IDBLocaleAwareKeyRange(aGlobal.GetAsSupports(), aLowerOpen, aUpperOpen, false);

  aRv = GetKeyFromJSVal(aGlobal.Context(), aLower, keyRange->Lower());
  if (aRv.Failed()) {
    return nullptr;
  }

  aRv = GetKeyFromJSVal(aGlobal.Context(), aUpper, keyRange->Upper());
  if (aRv.Failed()) {
    return nullptr;
  }

  if (keyRange->Lower() == keyRange->Upper() && (aLowerOpen || aUpperOpen)) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
    return nullptr;
  }

  return keyRange.forget();
}
示例#2
0
already_AddRefed<CustomEvent>
CustomEvent::Constructor(const GlobalObject& aGlobal,
                         const nsAString& aType,
                         const CustomEventInit& aParam,
                         ErrorResult& aRv)
{
    nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
    nsRefPtr<CustomEvent> e = new CustomEvent(t, nullptr, nullptr);
    bool trusted = e->Init(t);
    JS::Rooted<JS::Value> detail(aGlobal.Context(), aParam.mDetail);
    e->InitCustomEvent(aGlobal.Context(), aType, aParam.mBubbles, aParam.mCancelable, detail, aRv);
    e->SetTrusted(trusted);
    return e.forget();
}
/* static */ already_AddRefed<KeyframeEffectType>
KeyframeEffectReadOnly::ConstructKeyframeEffect(
    const GlobalObject& aGlobal,
    const Nullable<ElementOrCSSPseudoElement>& aTarget,
    JS::Handle<JSObject*> aKeyframes,
    const OptionsType& aOptions,
    ErrorResult& aRv)
{
  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
  if (!doc) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  TimingParams timingParams =
    TimingParams::FromOptionsUnion(aOptions, doc, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  nsAutoString invalidPacedProperty;
  KeyframeEffectParams effectOptions =
    KeyframeEffectParamsFromUnion(aOptions, invalidPacedProperty, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  if (!invalidPacedProperty.IsEmpty()) {
    const char16_t* params[] = { invalidPacedProperty.get() };
    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                    NS_LITERAL_CSTRING("Animation"),
                                    doc,
                                    nsContentUtils::eDOM_PROPERTIES,
                                    "UnanimatablePacedProperty",
                                    params, ArrayLength(params));
  }

  Maybe<OwningAnimationTarget> target = ConvertTarget(aTarget);
  RefPtr<KeyframeEffectType> effect =
    new KeyframeEffectType(doc, target, timingParams, effectOptions);

  effect->SetKeyframes(aGlobal.Context(), aKeyframes, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  return effect.forget();
}
示例#4
0
already_AddRefed<BluetoothLeDeviceEvent>
BluetoothLeDeviceEvent::Constructor(
  const GlobalObject& aGlobal,
  const nsAString& aType,
  const BluetoothLeDeviceEventInit& aEventInitDict,
  ErrorResult& aRv)
{
  nsCOMPtr<mozilla::dom::EventTarget> owner =
    do_QueryInterface(aGlobal.GetAsSupports());

  RefPtr<BluetoothLeDeviceEvent> e = new BluetoothLeDeviceEvent(owner);
  bool trusted = e->Init(owner);
  e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
  e->mDevice = aEventInitDict.mDevice;
  e->mRssi = aEventInitDict.mRssi;

  if (!aEventInitDict.mScanRecord.IsNull()) {
    const auto& scanRecord = aEventInitDict.mScanRecord.Value();
    scanRecord.ComputeLengthAndData();
    e->mScanRecord = ArrayBuffer::Create(aGlobal.Context(),
                                         scanRecord.Length(),
                                         scanRecord.Data());
    if (!e->mScanRecord) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
      return nullptr;
    }
  }

  e->SetTrusted(trusted);
  return e.forget();
}
示例#5
0
/* static */ already_AddRefed<Blob>
Blob::Constructor(const GlobalObject& aGlobal,
                  const Optional<Sequence<BlobPart>>& aData,
                  const BlobPropertyBag& aBag,
                  ErrorResult& aRv)
{
  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();

  if (aData.WasPassed()) {
    nsAutoString type(aBag.mType);
    MakeValidBlobType(type);
    impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
                         aBag.mEndings == EndingTypes::Native, aRv);
  } else {
    impl->InitializeBlob(aRv);
  }

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

  MOZ_ASSERT(!impl->IsFile());

  RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
  return blob.forget();
}
// static
already_AddRefed<PerformanceObserver>
PerformanceObserver::Constructor(const GlobalObject& aGlobal,
                                 PerformanceObserverCallback& aCb,
                                 ErrorResult& aRv)
{
  if (NS_IsMainThread()) {
    nsCOMPtr<nsPIDOMWindow> ownerWindow =
      do_QueryInterface(aGlobal.GetAsSupports());
    if (!ownerWindow) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }
    MOZ_ASSERT(ownerWindow->IsInnerWindow());

    RefPtr<PerformanceObserver> observer =
      new PerformanceObserver(ownerWindow, aCb);
    return observer.forget();
  }

  JSContext* cx = aGlobal.Context();
  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
  MOZ_ASSERT(workerPrivate);

  RefPtr<PerformanceObserver> observer =
    new PerformanceObserver(workerPrivate, aCb);
  return observer.forget();
}
/* static */ already_AddRefed<KeyframeEffectType>
KeyframeEffectReadOnly::ConstructKeyframeEffect(const GlobalObject& aGlobal,
                                                KeyframeEffectReadOnly& aSource,
                                                ErrorResult& aRv)
{
  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
  if (!doc) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  // Create a new KeyframeEffectReadOnly object with aSource's target,
  // iteration composite operation, composite operation, and spacing mode.
  // The constructor creates a new AnimationEffect(ReadOnly) object by
  // aSource's TimingParams.
  // Note: we don't need to re-throw exceptions since the value specified on
  //       aSource's timing object can be assumed valid.
  RefPtr<KeyframeEffectType> effect =
    new KeyframeEffectType(doc,
                           aSource.mTarget,
                           aSource.SpecifiedTiming(),
                           aSource.mEffectOptions);
  // Copy cumulative change hint. mCumulativeChangeHint should be the same as
  // the source one because both of targets are the same.
  effect->mCumulativeChangeHint = aSource.mCumulativeChangeHint;

  // Copy aSource's keyframes and animation properties.
  // Note: We don't call SetKeyframes directly, which might revise the
  //       computed offsets and rebuild the animation properties.
  // FIXME: Bug 1314537: We have to make sure SharedKeyframeList is handled
  //        properly.
  effect->mKeyframes = aSource.mKeyframes;
  effect->mProperties = aSource.mProperties;
  return effect.forget();
}
示例#8
0
// ---------------------------------------------------------------------------
//
// Animation interface:
//
// ---------------------------------------------------------------------------
/* static */ already_AddRefed<Animation>
Animation::Constructor(const GlobalObject& aGlobal,
                       KeyframeEffectReadOnly* aEffect,
                       const Optional<AnimationTimeline*>& aTimeline,
                       ErrorResult& aRv)
{
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
  RefPtr<Animation> animation = new Animation(global);

  if (!aEffect) {
    // Bug 1049975: We do not support null effect yet.
    aRv.Throw(NS_ERROR_DOM_ANIM_NO_EFFECT_ERR);
    return nullptr;
  }

  AnimationTimeline* timeline;
  if (aTimeline.WasPassed()) {
    timeline = aTimeline.Value();
  } else {
    nsIDocument* document =
      AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
    if (!document) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }
    timeline = document->Timeline();
  }

  animation->SetTimelineNoUpdate(timeline);
  animation->SetEffect(aEffect);

  return animation.forget();
}
示例#9
0
already_AddRefed<MediaEncryptedEvent>
MediaEncryptedEvent::Constructor(const GlobalObject& aGlobal,
                                 const nsAString& aType,
                                 const MediaKeyNeededEventInit& aEventInitDict,
                                 ErrorResult& aRv)
{
  nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
  RefPtr<MediaEncryptedEvent> e = new MediaEncryptedEvent(owner);
  bool trusted = e->Init(owner);
  e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
  e->mInitDataType = aEventInitDict.mInitDataType;
  if (!aEventInitDict.mInitData.IsNull()) {
    const auto& a = aEventInitDict.mInitData.Value();
    a.ComputeLengthAndData();
    e->mInitData = ArrayBuffer::Create(aGlobal.Context(),
                                       a.Length(),
                                       a.Data());
    if (!e->mInitData) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
      return nullptr;
    }
  }
  e->SetTrusted(trusted);
  return e.forget();
}
示例#10
0
/* static */ already_AddRefed<File>
File::Constructor(const GlobalObject& aGlobal,
                  const Sequence<BlobPart>& aData,
                  const nsAString& aName,
                  const FilePropertyBag& aBag,
                  ErrorResult& aRv)
{
  // Normalizing the filename
  nsString name(aName);
  name.ReplaceChar('/', ':');

  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(name);

  nsAutoString type(aBag.mType);
  MakeValidBlobType(type);
  impl->InitializeBlob(aGlobal.Context(), aData, type, false, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }
  MOZ_ASSERT(impl->IsFile());

  if (aBag.mLastModified.WasPassed()) {
    impl->SetLastModified(aBag.mLastModified.Value());
  }

  RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
  return file.forget();
}
示例#11
0
/* static */ void
ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
                                       const nsACString& aString,
                                       const Base64URLDecodeOptions& aOptions,
                                       JS::MutableHandle<JSObject*> aRetval,
                                       ErrorResult& aRv)
{
  Base64URLDecodePaddingPolicy paddingPolicy;
  switch (aOptions.mPadding) {
    case Base64URLDecodePadding::Require:
      paddingPolicy = Base64URLDecodePaddingPolicy::Require;
      break;

    case Base64URLDecodePadding::Ignore:
      paddingPolicy = Base64URLDecodePaddingPolicy::Ignore;
      break;

    case Base64URLDecodePadding::Reject:
      paddingPolicy = Base64URLDecodePaddingPolicy::Reject;
      break;

    default:
      aRv.Throw(NS_ERROR_INVALID_ARG);
      return;
  }
  FallibleTArray<uint8_t> data;
  nsresult rv = mozilla::Base64URLDecode(aString, paddingPolicy, data);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv.Throw(rv);
    return;
  }

  JS::Rooted<JSObject*> buffer(aGlobal.Context(),
                               ArrayBuffer::Create(aGlobal.Context(),
                                                   data.Length(),
                                                   data.Elements()));
  if (NS_WARN_IF(!buffer)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }
  aRetval.set(buffer);
}
示例#12
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();
}
示例#13
0
/* static */ void
ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
                                       const nsACString& aString,
                                       const Base64URLDecodeOptions& aOptions,
                                       JS::MutableHandle<JSObject*> aRetval,
                                       ErrorResult& aRv)
{
  FallibleTArray<uint8_t> data;
  nsresult rv = mozilla::Base64URLDecode(aString, aOptions, data);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv.Throw(rv);
    return;
  }

  JS::Rooted<JSObject*> buffer(aGlobal.Context(),
                               ArrayBuffer::Create(aGlobal.Context(),
                                                   data.Length(),
                                                   data.Elements()));
  if (NS_WARN_IF(!buffer)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }
  aRetval.set(buffer);
}
示例#14
0
// static
already_AddRefed<IDBKeyRange>
IDBKeyRange::Only(const GlobalObject& aGlobal,
                  JS::Handle<JS::Value> aValue,
                  ErrorResult& aRv)
{
  RefPtr<IDBKeyRange> keyRange =
    new IDBKeyRange(aGlobal.GetAsSupports(), false, false, true);

  aRv = GetKeyFromJSVal(aGlobal.Context(), aValue, keyRange->Lower());
  if (aRv.Failed()) {
    return nullptr;
  }

  return keyRange.forget();
}
示例#15
0
/* static */ already_AddRefed<FileReader>
FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
    nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
    WorkerPrivate* workerPrivate = nullptr;

    if (!NS_IsMainThread()) {
        JSContext* cx = aGlobal.Context();
        workerPrivate = GetWorkerPrivateFromContext(cx);
        MOZ_ASSERT(workerPrivate);
    }

    RefPtr<FileReader> fileReader = new FileReader(global, workerPrivate);

    return fileReader.forget();
}
示例#16
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());
    }
  }
}
示例#17
0
/* static */ already_AddRefed<Blob>
Blob::Constructor(
        const GlobalObject& aGlobal,
        const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
        const BlobPropertyBag& aBag,
        ErrorResult& aRv)
{
  nsRefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();

  impl->InitializeBlob(aGlobal.Context(), aData, aBag.mType,
                       aBag.mEndings == EndingTypes::Native, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }
  MOZ_ASSERT(!impl->IsFile());

  nsRefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
  return blob.forget();
}
示例#18
0
// static
already_AddRefed<PushManager>
PushManager::Constructor(GlobalObject& aGlobal,
                         const nsAString& aScope,
                         ErrorResult& aRv)
{
  if (!NS_IsMainThread()) {
    RefPtr<PushManager> ret = new PushManager(aScope);
    return ret.forget();
  }

  RefPtr<PushManagerImpl> impl = PushManagerImpl::Constructor(aGlobal,
                                                              aGlobal.Context(),
                                                              aScope, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
  RefPtr<PushManager> ret = new PushManager(global, impl);

  return ret.forget();
}
示例#19
0
/* static */ already_AddRefed<ChromeWorker>
ChromeWorker::Constructor(const GlobalObject& aGlobal,
                          const nsAString& aScriptURL,
                          ErrorResult& aRv)
{
  JSContext* cx = aGlobal.Context();

  RefPtr<WorkerPrivate> workerPrivate =
    WorkerPrivate::Constructor(cx, aScriptURL, true /* aIsChromeWorker */,
                               WorkerTypeDedicated, EmptyString(),
                               VoidCString(), nullptr /*aLoadInfo */, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  nsCOMPtr<nsIGlobalObject> globalObject =
    do_QueryInterface(aGlobal.GetAsSupports());

  RefPtr<ChromeWorker> worker =
    new ChromeWorker(globalObject, workerPrivate.forget());
  return worker.forget();
}
示例#20
0
/* static */ already_AddRefed<File>
File::Constructor(
        const GlobalObject& aGlobal,
        const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData,
        const nsAString& aName,
        const FilePropertyBag& aBag,
        ErrorResult& aRv)
{
  nsRefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(aName);

  impl->InitializeBlob(aGlobal.Context(), aData, aBag.mType, false, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }
  MOZ_ASSERT(impl->IsFile());

  if (aBag.mLastModified.WasPassed()) {
    impl->SetLastModified(aBag.mLastModified.Value());
  }

  nsRefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
  return file.forget();
}
示例#21
0
// static
already_AddRefed<Promise>
Promise::All(const GlobalObject& aGlobal,
             const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
{
  nsCOMPtr<nsIGlobalObject> global;
  global = do_QueryInterface(aGlobal.GetAsSupports());
  if (!global) {
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return nullptr;
  }

  JSContext* cx = aGlobal.Context();

  JS::AutoObjectVector promises(cx);
  if (!promises.reserve(aPromiseList.Length())) {
    aRv.NoteJSContextException(cx);
    return nullptr;
  }

  for (auto& promise : aPromiseList) {
    JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj());
    // Just in case, make sure these are all in the context compartment.
    if (!JS_WrapObject(cx, &promiseObj)) {
      aRv.NoteJSContextException(cx);
      return nullptr;
    }
    promises.infallibleAppend(promiseObj);
  }

  JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises));
  if (!result) {
    aRv.NoteJSContextException(cx);
    return nullptr;
  }

  return CreateFromExisting(global, result);
}
示例#22
0
/* static */ already_AddRefed<FileReader>
FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
  // The owner can be null when this object is used by chrome code.
  nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
  WorkerPrivate* workerPrivate = nullptr;

  if (!NS_IsMainThread()) {
    JSContext* cx = aGlobal.Context();
    workerPrivate = GetWorkerPrivateFromContext(cx);
    MOZ_ASSERT(workerPrivate);
  }

  RefPtr<FileReader> fileReader = new FileReader(owner, workerPrivate);

  if (!owner && nsContentUtils::ThreadsafeIsCallerChrome()) {
    // Instead of grabbing some random global from the context stack,
    // let's use the default one (junk scope) for now.
    // We should move away from this Init...
    fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
  }

  return fileReader.forget();
}
示例#23
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 (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);

  // 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) {
      nsIDocument* doc = window->GetExtantDoc();
      MOZ_ASSERT(doc);
      info.InitFromDocument(doc);
    } else {
      info.InitFromChromeGlobal(global);
    }
    internalResponse->InitChannelInfo(info);
  } else {
    WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
    MOZ_ASSERT(worker);
    internalResponse->InitChannelInfo(worker->GetChannelInfo());
  }

  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.
        void* 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();
}
/* 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();
}
示例#25
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();
}
示例#26
0
already_AddRefed<WebSocket>
WebSocket::Constructor(const GlobalObject& aGlobal,
                       const nsAString& aUrl,
                       const Sequence<nsString>& aProtocols,
                       ErrorResult& aRv)
{
  if (!PrefEnabled()) {
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    return nullptr;
  }

  nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
    do_QueryInterface(aGlobal.GetAsSupports());
  if (!scriptPrincipal) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
  if (!principal) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
  if (!sgo) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal.GetAsSupports());
  if (!ownerWindow) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsTArray<nsString> protocolArray;

  for (uint32_t index = 0, len = aProtocols.Length(); index < len; ++index) {

    const nsString& protocolElement = aProtocols[index];

    if (protocolElement.IsEmpty()) {
      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
      return nullptr;
    }
    if (protocolArray.Contains(protocolElement)) {
      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
      return nullptr;
    }
    if (protocolElement.FindChar(',') != -1)  /* interferes w/list */ {
      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
      return nullptr;
    }

    protocolArray.AppendElement(protocolElement);
  }

  nsRefPtr<WebSocket> webSocket = new WebSocket(ownerWindow);
  nsresult rv = webSocket->Init(aGlobal.Context(), principal,
                                aUrl, protocolArray);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return nullptr;
  }

  return webSocket.forget();
}
示例#27
0
/* static */
void PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID,
                         const PrioParams& aPrioParams,
                         RootedDictionary<PrioEncodedData>& aData,
                         ErrorResult& aRv) {
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
  if (!global) {
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return;
  }

  SECStatus prio_rv = SECSuccess;

  if (!sSingleton) {
    nsresult rv;

    nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyA;
    rv = Preferences::GetCString("prio.publicKeyA", prioKeyA);
    if (NS_FAILED(rv)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyB;
    rv = Preferences::GetCString("prio.publicKeyB", prioKeyB);
    if (NS_FAILED(rv)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    // Check that both public keys are of the right length
    // and contain only hex digits 0-9a-fA-f
    if (!PrioEncoder::IsValidHexPublicKey(prioKeyA) ||
        !PrioEncoder::IsValidHexPublicKey(prioKeyB)) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    prio_rv = Prio_init();

    if (prio_rv != SECSuccess) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    prio_rv = PublicKey_import_hex(
        &sPublicKeyA,
        reinterpret_cast<const unsigned char*>(prioKeyA.BeginReading()),
        CURVE25519_KEY_LEN_HEX);
    if (prio_rv != SECSuccess) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    prio_rv = PublicKey_import_hex(
        &sPublicKeyB,
        reinterpret_cast<const unsigned char*>(prioKeyB.BeginReading()),
        CURVE25519_KEY_LEN_HEX);
    if (prio_rv != SECSuccess) {
      aRv.Throw(NS_ERROR_UNEXPECTED);
      return;
    }

    sSingleton = new PrioEncoder();
    ClearOnShutdown(&sSingleton);
  }

  nsTArray<bool> dataItems = aPrioParams.mBooleans;
  if (dataItems.Length() > gNumBooleans) {
    aRv.ThrowRangeError<MSG_VALUE_OUT_OF_RANGE>(
        NS_LITERAL_STRING("Maximum boolean value exceeded"));
    return;
  }

  PrioConfig prioConfig = PrioConfig_new(
      dataItems.Length(), sPublicKeyA, sPublicKeyB,
      reinterpret_cast<const unsigned char*>(aBatchID.BeginReading()),
      aBatchID.Length());

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

  auto configGuard = MakeScopeExit([&] { PrioConfig_clear(prioConfig); });

  unsigned char* forServerA = nullptr;
  unsigned int lenA = 0;
  unsigned char* forServerB = nullptr;
  unsigned int lenB = 0;

  prio_rv = PrioClient_encode(prioConfig, dataItems.Elements(), &forServerA,
                              &lenA, &forServerB, &lenB);

  nsTArray<uint8_t> arrayForServerA;
  nsTArray<uint8_t> arrayForServerB;

  if (!arrayForServerA.AppendElements(reinterpret_cast<uint8_t*>(forServerA),
                                      lenA, fallible)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  free(forServerA);

  if (!arrayForServerB.AppendElements(reinterpret_cast<uint8_t*>(forServerB),
                                      lenB, fallible)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  free(forServerB);

  if (prio_rv != SECSuccess) {
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }

  JS::Rooted<JS::Value> valueA(aGlobal.Context());
  if (!ToJSValue(aGlobal.Context(),
                 TypedArrayCreator<Uint8Array>(arrayForServerA), &valueA)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  aData.mA.Construct().Init(&valueA.toObject());

  JS::Rooted<JS::Value> valueB(aGlobal.Context());
  if (!ToJSValue(aGlobal.Context(),
                 TypedArrayCreator<Uint8Array>(arrayForServerB), &valueB)) {
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  aData.mB.Construct().Init(&valueB.toObject());
}
/* 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();
}