Exemple #1
0
void
Crypto::DisableRightClick(ErrorResult& aRv)
{
  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
Exemple #2
0
NS_IMETHODIMP
FetchDriver::OnStartRequest(nsIRequest* aRequest,
                            nsISupports* aContext)
{
  AssertIsOnMainThread();

  // Note, this can be called multiple times if we are doing an opaqueredirect.
  // In that case we will get a simulated OnStartRequest() and then the real
  // channel will call in with an errored OnStartRequest().

  if (!mChannel) {
    MOZ_ASSERT(!mObserver);
    return NS_BINDING_ABORTED;
  }

  nsresult rv;
  aRequest->GetStatus(&rv);
  if (NS_FAILED(rv)) {
    FailWithNetworkError(rv);
    return rv;
  }

  // We should only get to the following code once.
  MOZ_ASSERT(!mPipeOutputStream);
  MOZ_ASSERT(mObserver);

  mNeedToObserveOnDataAvailable = mObserver->NeedOnDataAvailable();

  RefPtr<InternalResponse> response;
  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);

  // On a successful redirect we perform the following substeps of HTTP Fetch,
  // step 5, "redirect status", step 11.

  bool foundOpaqueRedirect = false;

  int64_t contentLength = InternalResponse::UNKNOWN_BODY_SIZE;
  rv = channel->GetContentLength(&contentLength);
  MOZ_ASSERT_IF(NS_FAILED(rv), contentLength == InternalResponse::UNKNOWN_BODY_SIZE);

  if (httpChannel) {
    uint32_t responseStatus;
    rv = httpChannel->GetResponseStatus(&responseStatus);
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    if (mozilla::net::nsHttpChannel::IsRedirectStatus(responseStatus)) {
      if (mRequest->GetRedirectMode() == RequestRedirect::Error) {
        FailWithNetworkError(NS_BINDING_ABORTED);
        return NS_BINDING_FAILED;
      }
      if (mRequest->GetRedirectMode() == RequestRedirect::Manual) {
        foundOpaqueRedirect = true;
      }
    }

    nsAutoCString statusText;
    rv = httpChannel->GetResponseStatusText(statusText);
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    response = new InternalResponse(responseStatus, statusText);

    response->Headers()->FillResponseHeaders(httpChannel);

    // If Content-Encoding or Transfer-Encoding headers are set, then the actual
    // Content-Length (which refer to the decoded data) is obscured behind the encodings.
    ErrorResult result;
    if (response->Headers()->Has(NS_LITERAL_CSTRING("content-encoding"), result) ||
        response->Headers()->Has(NS_LITERAL_CSTRING("transfer-encoding"), result)) {
      // We cannot trust the content-length when content-encoding or
      // transfer-encoding are set.  There are many servers which just
      // get this wrong.
      contentLength = InternalResponse::UNKNOWN_BODY_SIZE;
    }
    MOZ_ASSERT(!result.Failed());
  } else {
    response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));

    ErrorResult result;
    nsAutoCString contentType;
    rv = channel->GetContentType(contentType);
    if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) {
      nsAutoCString contentCharset;
      channel->GetContentCharset(contentCharset);
      if (NS_SUCCEEDED(rv) && !contentCharset.IsEmpty()) {
        contentType += NS_LITERAL_CSTRING(";charset=") + contentCharset;
      }

      response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"),
                                  contentType,
                                  result);
      MOZ_ASSERT(!result.Failed());
    }

    if (contentLength > 0) {
      nsAutoCString contentLenStr;
      contentLenStr.AppendInt(contentLength);
      response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"),
                                  contentLenStr,
                                  result);
      MOZ_ASSERT(!result.Failed());
    }
  }

  nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(aRequest);
  if (cic && mAltDataListener) {
    // Skip the case that mAltDataListener->Status() equals to FALLBACK, that means
    // the opened channel for alternative data loading is reused for loading the
    // main data.
    if (mAltDataListener->Status() != AlternativeDataStreamListener::FALLBACK) {
      // Verify the cache ID is the same with from alternative data cache.
      // If the cache ID is different, droping the alternative data loading,
      // otherwise setup the response's alternative body and cacheInfoChannel.
      uint64_t cacheEntryId = 0;
      if (NS_SUCCEEDED(cic->GetCacheEntryId(&cacheEntryId)) &&
          cacheEntryId != mAltDataListener->GetAlternativeDataCacheEntryId()) {
        mAltDataListener->Cancel();
      } else {
        // AlternativeDataStreamListener::OnStartRequest had already been called,
        // the alternative data input stream and cacheInfo channel must be created.
        nsCOMPtr<nsICacheInfoChannel> cacheInfo = mAltDataListener->GetCacheInfoChannel();
        nsCOMPtr<nsIInputStream> altInputStream = mAltDataListener->GetAlternativeInputStream();
        MOZ_ASSERT(altInputStream && cacheInfo);
        response->SetAlternativeBody(altInputStream);
        nsMainThreadPtrHandle<nsICacheInfoChannel> handle(
          new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel",
                                                         cacheInfo,
                                                         false));
        response->SetCacheInfoChannel(handle);
      }
    } else if (!mAltDataListener->GetAlternativeDataType().IsEmpty()) {
      // If the status is FALLBACK and the mAltDataListener::mAlternativeDataType
      // is not empty, that means the data need to be saved into cache, setup the
      // response's nsICacheInfoChannel for caching the data after loading.
      nsMainThreadPtrHandle<nsICacheInfoChannel> handle(
        new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel",
                                                       cic,
                                                       false));
      response->SetCacheInfoChannel(handle);
    }
  }

  // We open a pipe so that we can immediately set the pipe's read end as the
  // response's body. Setting the segment size to UINT32_MAX means that the
  // pipe has infinite space. The nsIChannel will continue to buffer data in
  // xpcom events even if we block on a fixed size pipe.  It might be possible
  // to suspend the channel and then resume when there is space available, but
  // for now use an infinite pipe to avoid blocking.
  nsCOMPtr<nsIInputStream> pipeInputStream;
  rv = NS_NewPipe(getter_AddRefs(pipeInputStream),
                  getter_AddRefs(mPipeOutputStream),
                  0, /* default segment size */
                  UINT32_MAX /* infinite pipe */,
                  true /* non-blocking input, otherwise you deadlock */,
                  false /* blocking output, since the pipe is 'in'finite */ );
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError(rv);
    // Cancel request.
    return rv;
  }
  response->SetBody(pipeInputStream, contentLength);

  response->InitChannelInfo(channel);

  nsCOMPtr<nsIURI> channelURI;
  rv = channel->GetURI(getter_AddRefs(channelURI));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError(rv);
    // Cancel request.
    return rv;
  }

  nsCOMPtr<nsILoadInfo> loadInfo;
  rv = channel->GetLoadInfo(getter_AddRefs(loadInfo));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError(rv);
    return rv;
  }

  // Propagate any tainting from the channel back to our response here.  This
  // step is not reflected in the spec because the spec is written such that
  // FetchEvent.respondWith() just passes the already-tainted Response back to
  // the outer fetch().  In gecko, however, we serialize the Response through
  // the channel and must regenerate the tainting from the channel in the
  // interception case.
  mRequest->MaybeIncreaseResponseTainting(loadInfo->GetTainting());

  // Resolves fetch() promise which may trigger code running in a worker.  Make
  // sure the Response is fully initialized before calling this.
  mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect);
  if (NS_WARN_IF(!mResponse)) {
    // Fail to generate a paddingInfo for opaque response.
    MOZ_DIAGNOSTIC_ASSERT(mResponse->Type() == ResponseType::Opaque);
    FailWithNetworkError(NS_ERROR_UNEXPECTED);
    return rv;
  }

  // From "Main Fetch" step 19: SRI-part1.
  if (ShouldCheckSRI(mRequest, mResponse) && mSRIMetadata.IsEmpty()) {
    nsIConsoleReportCollector* reporter = nullptr;
    if (mObserver) {
      reporter = mObserver->GetReporter();
    }

    nsAutoCString sourceUri;
    if (mDocument && mDocument->GetDocumentURI()) {
      mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
    } else if (!mWorkerScript.IsEmpty()) {
      sourceUri.Assign(mWorkerScript);
    }
    SRICheck::IntegrityMetadata(mRequest->GetIntegrity(), sourceUri,
                                reporter, &mSRIMetadata);
    mSRIDataVerifier = new SRICheckDataVerifier(mSRIMetadata, sourceUri,
                                                reporter);

    // Do not retarget off main thread when using SRI API.
    return NS_OK;
  }

  nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError(rv);
    // Cancel request.
    return rv;
  }

  // Try to retarget off main thread.
  if (nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(aRequest)) {
    Unused << NS_WARN_IF(NS_FAILED(rr->RetargetDeliveryTo(sts)));
  }
  return NS_OK;
}
already_AddRefed<Promise>
MobileMessageManager::SetSmscAddress(const SmscAddress& aSmscAddress,
                                     const Optional<uint32_t>& aServiceId,
                                     ErrorResult& aRv)
{
  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
  if (!smsService) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  // Use the default one unless |serviceId| is available.
  uint32_t serviceId;
  nsresult rv;
  if (aServiceId.WasPassed()) {
    serviceId = aServiceId.Value();
  } else {
    rv = smsService->GetSmsDefaultServiceId(&serviceId);
    if (NS_FAILED(rv)) {
      aRv.Throw(rv);
      return nullptr;
    }
  }

  nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
  if (!window) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
  if (!global) {
    aRv.Throw(NS_ERROR_UNEXPECTED);
    return nullptr;
  }

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

  if (!aSmscAddress.mAddress.WasPassed()) {
    NS_WARNING("SmscAddress.address is a mandatory field and can not be omitted.");
    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    return promise.forget();
  }

  nsString address = aSmscAddress.mAddress.Value();
  TypeOfNumber ton = aSmscAddress.mTypeOfAddress.mTypeOfNumber;
  NumberPlanIdentification npi =
    aSmscAddress.mTypeOfAddress.mNumberPlanIdentification;

  // If the address begins with +, set TON to international no matter what has
  // passed in.
  if (!address.IsEmpty() && address[0] == '+') {
    ton = TypeOfNumber::International;
  }

  nsCOMPtr<nsIMobileMessageCallback> msgCallback =
    new MobileMessageCallback(promise);

  rv = smsService->SetSmscAddress(serviceId, address,
    static_cast<uint32_t>(ton), static_cast<uint32_t>(npi), msgCallback);
  if (NS_FAILED(rv)) {
    promise->MaybeReject(rv);
    return promise.forget();
  }

  return promise.forget();
}
already_AddRefed<IDBRequest>
IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
                  ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  if (!mTransaction->IsOpen()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
    return nullptr;
  }

  if (!mTransaction->IsWriteAllowed()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
    return nullptr;
  }

  if (mTransaction->GetMode() == IDBTransaction::CLEANUP ||
      IsSourceDeleted() ||
      !mHaveValue ||
      mType == Type_ObjectStoreKey ||
      mType == Type_IndexKey ||
      mContinueCalled) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
    return nullptr;
  }

  MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
  MOZ_ASSERT(!mKey.IsUnset());
  MOZ_ASSERT_IF(mType == Type_Index, !mPrimaryKey.IsUnset());

  IDBObjectStore* objectStore;
  if (mType == Type_ObjectStore) {
    objectStore = mSourceObjectStore;
  } else {
    objectStore = mSourceIndex->ObjectStore();
  }

  MOZ_ASSERT(objectStore);

  const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;

  RefPtr<IDBRequest> request;

  if (objectStore->HasValidKeyPath()) {
    // Make sure the object given has the correct keyPath value set on it.
    const KeyPath& keyPath = objectStore->GetKeyPath();
    Key key;

    aRv = keyPath.ExtractKey(aCx, aValue, key);
    if (aRv.Failed()) {
      return nullptr;
    }

    if (key != primaryKey) {
      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
      return nullptr;
    }

    request = objectStore->AddOrPut(aCx,
                                    aValue,
                                    /* aKey */ JS::UndefinedHandleValue,
                                    /* aOverwrite */ true,
                                    /* aFromCursor */ true,
                                    aRv);
    if (aRv.Failed()) {
      return nullptr;
    }
  }
  else {
    JS::Rooted<JS::Value> keyVal(aCx);
    aRv = primaryKey.ToJSVal(aCx, &keyVal);
    if (aRv.Failed()) {
      return nullptr;
    }

    request = objectStore->AddOrPut(aCx,
                                    aValue,
                                    keyVal,
                                    /* aOverwrite */ true,
                                    /* aFromCursor */ true,
                                    aRv);
    if (aRv.Failed()) {
      return nullptr;
    }
  }

  request->SetSource(this);

  if (mType == Type_ObjectStore) {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s)."
                   "cursor(%s).update(%s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
                 IDB_LOG_ID_STRING(),
                 mTransaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(mTransaction->Database()),
                 IDB_LOG_STRINGIFY(mTransaction),
                 IDB_LOG_STRINGIFY(objectStore),
                 IDB_LOG_STRINGIFY(mDirection),
                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
  } else {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s)."
                   "index(%s).cursor(%s).update(%s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
                 IDB_LOG_ID_STRING(),
                 mTransaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(mTransaction->Database()),
                 IDB_LOG_STRINGIFY(mTransaction),
                 IDB_LOG_STRINGIFY(objectStore),
                 IDB_LOG_STRINGIFY(mSourceIndex),
                 IDB_LOG_STRINGIFY(mDirection),
                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
  }

  return request.forget();
}
nsresult
DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent)
{
  MOZ_ASSERT(NS_IsMainThread());

  // This DB has been just created and we have to inform the callback about
  // this.
  mCreatedSchema = true;

#ifdef DEBUG
  nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent);
  MOZ_ASSERT(event);

  Nullable<uint64_t> version = event->GetNewVersion();
  MOZ_ASSERT(!version.IsNull());
  MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION);
#endif

  ErrorResult error;
  JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
  mRequest->GetResult(&result, error);
  if (NS_WARN_IF(error.Failed())) {
    return error.StealNSResult();
  }

  MOZ_ASSERT(result.isObject());

  IDBDatabase* database = nullptr;
  nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
  if (NS_FAILED(rv)) {
    NS_WARNING("Didn't get the object we expected!");
    return rv;
  }

  {
    IDBObjectStoreParameters params;
    params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }"));
    RefPtr<IDBObjectStore> store =
      database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_NAME),
                                  params, error);
    if (NS_WARN_IF(error.Failed())) {
      return error.StealNSResult();
    }
  }

  RefPtr<IDBObjectStore> store;

  {
    IDBObjectStoreParameters params;
    params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }"));

    store =
      database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION),
                                  params, error);
    if (NS_WARN_IF(error.Failed())) {
      return error.StealNSResult();
    }
  }

  {
    IDBIndexParameters params;
    params.Init(NS_LITERAL_STRING("{ \"unique\": true }"));
    RefPtr<IDBIndex> index =
      store->CreateIndex(NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX),
                         NS_LITERAL_STRING("revisionId"), params, error);
    if (NS_WARN_IF(error.Failed())) {
      return error.StealNSResult();
    }
  }

  return NS_OK;
}
void
HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
                                  uint32_t aStart, uint32_t aEnd,
                                  const SelectionMode& aSelectMode,
                                  ErrorResult& aRv, int32_t aSelectionStart,
                                  int32_t aSelectionEnd)
{
  if (aStart > aEnd) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  nsAutoString value;
  GetValueInternal(value, false);
  uint32_t inputValueLength = value.Length();

  if (aStart > inputValueLength) {
    aStart = inputValueLength;
  }

  if (aEnd > inputValueLength) {
    aEnd = inputValueLength;
  }

  if (aSelectionStart == -1 && aSelectionEnd == -1) {
    aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
    if (aRv.Failed()) {
      if (mState.IsSelectionCached()) {
        aSelectionStart = mState.GetSelectionProperties().mStart;
        aSelectionEnd = mState.GetSelectionProperties().mEnd;
        aRv = NS_OK;
      }
    }
  }

  if (aStart <= aEnd) {
    value.Replace(aStart, aEnd - aStart, aReplacement);
    nsresult rv =
      SetValueInternal(value, nsTextEditorState::eSetValue_ByContent);
    if (NS_FAILED(rv)) {
      aRv.Throw(rv);
      return;
    }
  }

  uint32_t newEnd = aStart + aReplacement.Length();
  int32_t delta =  aReplacement.Length() - (aEnd - aStart);

  switch (aSelectMode) {
    case mozilla::dom::SelectionMode::Select:
    {
      aSelectionStart = aStart;
      aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Start:
    {
      aSelectionStart = aSelectionEnd = aStart;
    }
    break;
    case mozilla::dom::SelectionMode::End:
    {
      aSelectionStart = aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Preserve:
    {
      if ((uint32_t)aSelectionStart > aEnd) {
        aSelectionStart += delta;
      } else if ((uint32_t)aSelectionStart > aStart) {
        aSelectionStart = aStart;
      }

      if ((uint32_t)aSelectionEnd > aEnd) {
        aSelectionEnd += delta;
      } else if ((uint32_t)aSelectionEnd > aStart) {
        aSelectionEnd = newEnd;
      }
    }
    break;
    default:
      MOZ_CRASH("Unknown mode!");
  }

  Optional<nsAString> direction;
  SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
}
void
FileReaderSync::ReadAsText(JS::Handle<JSObject*> aBlob,
                           const Optional<nsAString>& aEncoding,
                           nsAString& aResult,
                           ErrorResult& aRv)
{
  nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob);
  if (!blob) {
    aRv.Throw(NS_ERROR_INVALID_ARG);
    return;
  }

  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return;
  }

  nsAutoCString encoding;
  unsigned char sniffBuf[3] = { 0, 0, 0 };
  uint32_t numRead;
  rv = stream->Read(reinterpret_cast<char*>(sniffBuf),
                    sizeof(sniffBuf), &numRead);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return;
  }

  // The BOM sniffing is baked into the "decode" part of the Encoding
  // Standard, which the File API references.
  if (!nsContentUtils::CheckForBOM(sniffBuf, numRead, encoding)) {
    // BOM sniffing failed. Try the API argument.
    if (!aEncoding.WasPassed() ||
        !EncodingUtils::FindEncodingForLabel(aEncoding.Value(),
                                             encoding)) {
      // API argument failed. Try the type property of the blob.
      nsAutoString type16;
      blob->GetType(type16);
      NS_ConvertUTF16toUTF8 type(type16);
      nsAutoCString specifiedCharset;
      bool haveCharset;
      int32_t charsetStart, charsetEnd;
      NS_ExtractCharsetFromContentType(type,
                                       specifiedCharset,
                                       &haveCharset,
                                       &charsetStart,
                                       &charsetEnd);
      if (!EncodingUtils::FindEncodingForLabel(specifiedCharset, encoding)) {
        // Type property failed. Use UTF-8.
        encoding.AssignLiteral("UTF-8");
      }
    }
  }

  nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(stream);
  if (!seekable) {
    aRv.Throw(NS_ERROR_FAILURE);
    return;
  }

  // Seek to 0 because to undo the BOM sniffing advance. UTF-8 and UTF-16
  // decoders will swallow the BOM.
  rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return;
  }

  rv = ConvertStream(stream, encoding.get(), aResult);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return;
  }
}
already_AddRefed<Promise>
ServiceWorkerRegistrationMainThread::Unregister(ErrorResult& aRv)
{
  AssertIsOnMainThread();
  nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(GetOwner());
  if (!go) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  // Although the spec says that the same-origin checks should also be done
  // asynchronously, we do them in sync because the Promise created by the
  // WebIDL infrastructure due to a returned error will be resolved
  // asynchronously. We aren't making any internal state changes in these
  // checks, so ordering of multiple calls is not affected.
  nsCOMPtr<nsIDocument> document = GetOwner()->GetExtantDoc();
  if (!document) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsCOMPtr<nsIURI> scopeURI;
  nsCOMPtr<nsIURI> baseURI = document->GetBaseURI();
  // "If the origin of scope is not client's origin..."
  nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), mScope, nullptr, baseURI);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    return nullptr;
  }

  nsCOMPtr<nsIPrincipal> documentPrincipal = document->NodePrincipal();
  rv = documentPrincipal->CheckMayLoad(scopeURI, true /* report */,
                                       false /* allowIfInheritsPrinciple */);
  if (NS_FAILED(rv)) {
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    return nullptr;
  }

  nsAutoCString uriSpec;
  aRv = scopeURI->GetSpecIgnoringRef(uriSpec);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  nsCOMPtr<nsIServiceWorkerManager> swm =
    mozilla::services::GetServiceWorkerManager();

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

  RefPtr<UnregisterCallback> cb = new UnregisterCallback(promise);

  NS_ConvertUTF8toUTF16 scope(uriSpec);
  aRv = swm->Unregister(documentPrincipal, cb, scope);
  if (aRv.Failed()) {
    return nullptr;
  }

  return promise.forget();
}
/* 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();
}
Exemple #10
0
mozilla::ipc::IPCResult CacheOpChild::Recv__delete__(
    const ErrorResult& aRv, const CacheOpResult& aResult) {
  NS_ASSERT_OWNINGTHREAD(CacheOpChild);

  if (NS_WARN_IF(aRv.Failed())) {
    MOZ_DIAGNOSTIC_ASSERT(aResult.type() == CacheOpResult::Tvoid_t);
    // TODO: Remove this const_cast (bug 1152078).
    // It is safe for now since this ErrorResult is handed off to us by IPDL
    // and is thrown into the trash afterwards.
    mPromise->MaybeReject(const_cast<ErrorResult&>(aRv));
    mPromise = nullptr;
    return IPC_OK();
  }

  switch (aResult.type()) {
    case CacheOpResult::TCacheMatchResult: {
      HandleResponse(aResult.get_CacheMatchResult().maybeResponse());
      break;
    }
    case CacheOpResult::TCacheMatchAllResult: {
      HandleResponseList(aResult.get_CacheMatchAllResult().responseList());
      break;
    }
    case CacheOpResult::TCachePutAllResult: {
      mPromise->MaybeResolveWithUndefined();
      break;
    }
    case CacheOpResult::TCacheDeleteResult: {
      mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success());
      break;
    }
    case CacheOpResult::TCacheKeysResult: {
      HandleRequestList(aResult.get_CacheKeysResult().requestList());
      break;
    }
    case CacheOpResult::TStorageMatchResult: {
      HandleResponse(aResult.get_StorageMatchResult().maybeResponse());
      break;
    }
    case CacheOpResult::TStorageHasResult: {
      mPromise->MaybeResolve(aResult.get_StorageHasResult().success());
      break;
    }
    case CacheOpResult::TStorageOpenResult: {
      auto result = aResult.get_StorageOpenResult();
      auto actor = static_cast<CacheChild*>(result.actorChild());

      // If we have a success status then we should have an actor.  Gracefully
      // reject instead of crashing, though, if we get a nullptr here.
      MOZ_DIAGNOSTIC_ASSERT(actor);
      if (!actor) {
        ErrorResult status;
        status.ThrowTypeError<MSG_CACHE_OPEN_FAILED>();
        mPromise->MaybeReject(status);
        break;
      }

      RefPtr<CacheWorkerHolder> workerHolder =
          CacheWorkerHolder::PreferBehavior(
              GetWorkerHolder(), CacheWorkerHolder::AllowIdleShutdownStart);

      actor->SetWorkerHolder(workerHolder);
      RefPtr<Cache> cache = new Cache(mGlobal, actor, result.ns());
      mPromise->MaybeResolve(cache);
      break;
    }
    case CacheOpResult::TStorageDeleteResult: {
      mPromise->MaybeResolve(aResult.get_StorageDeleteResult().success());
      break;
    }
    case CacheOpResult::TStorageKeysResult: {
      mPromise->MaybeResolve(aResult.get_StorageKeysResult().keyList());
      break;
    }
    default:
      MOZ_CRASH("Unknown Cache op result type!");
  }

  mPromise = nullptr;

  return IPC_OK();
}
Exemple #11
0
already_AddRefed<DetailedPromise>
MediaKeys::Init(ErrorResult& aRv)
{
  RefPtr<DetailedPromise> promise(MakePromise(aRv,
    NS_LITERAL_CSTRING("MediaKeys::Init()")));
  if (aRv.Failed()) {
    return nullptr;
  }

  mProxy = new CDMProxy(this, mKeySystem);

  // Determine principal (at creation time) of the MediaKeys object.
  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject());
  if (!sop) {
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get script principal in MediaKeys::Init"));
    return promise.forget();
  }
  mPrincipal = sop->GetPrincipal();

  // Determine principal of the "top-level" window; the principal of the
  // page that will display in the URL bar.
  nsCOMPtr<nsPIDOMWindowInner> window = GetParentObject();
  if (!window) {
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get top-level window in MediaKeys::Init"));
    return promise.forget();
  }
  nsCOMPtr<nsPIDOMWindowOuter> top = window->GetOuterWindow()->GetTop();
  if (!top || !top->GetExtantDoc()) {
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get document in MediaKeys::Init"));
    return promise.forget();
  }

  mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal();

  if (!mPrincipal || !mTopLevelPrincipal) {
    NS_WARNING("Failed to get principals when creating MediaKeys");
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get principal(s) in MediaKeys::Init"));
    return promise.forget();
  }

  nsAutoString origin;
  nsresult rv = nsContentUtils::GetUTFOrigin(mPrincipal, origin);
  if (NS_FAILED(rv)) {
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get principal origin string in MediaKeys::Init"));
    return promise.forget();
  }
  nsAutoString topLevelOrigin;
  rv = nsContentUtils::GetUTFOrigin(mTopLevelPrincipal, topLevelOrigin);
  if (NS_FAILED(rv)) {
    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                         NS_LITERAL_CSTRING("Couldn't get top-level principal origin string in MediaKeys::Init"));
    return promise.forget();
  }

  nsIDocument* doc = window->GetExtantDoc();
  const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);

  EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s",
          this,
          NS_ConvertUTF16toUTF8(origin).get(),
          NS_ConvertUTF16toUTF8(topLevelOrigin).get(),
          (inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));

  // The CDMProxy's initialization is asynchronous. The MediaKeys is
  // refcounted, and its instance is returned to JS by promise once
  // it's been initialized. No external refs exist to the MediaKeys while
  // we're waiting for the promise to be resolved, so we must hold a
  // reference to the new MediaKeys object until it's been created,
  // or its creation has failed. Store the id of the promise returned
  // here, and hold a self-reference until that promise is resolved or
  // rejected.
  MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!");
  mCreatePromiseId = StorePromise(promise);
  AddRef();
  mProxy->Init(mCreatePromiseId,
               origin,
               topLevelOrigin,
               KeySystemToGMPName(mKeySystem),
               inPrivateBrowsing,
               new MediaKeysGMPCrashHelper(this));

  return promise.forget();
}
void
HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
                                  uint32_t aStart, uint32_t aEnd,
                                  const SelectionMode& aSelectMode,
                                  ErrorResult& aRv, int32_t aSelectionStart,
                                  int32_t aSelectionEnd)
{
  if (aStart > aEnd) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  nsAutoString value;
  GetValueInternal(value, false);
  uint32_t inputValueLength = value.Length();

  if (aStart > inputValueLength) {
    aStart = inputValueLength;
  }

  if (aEnd > inputValueLength) {
    aEnd = inputValueLength;
  }

  if (aSelectionStart == -1 && aSelectionEnd == -1) {
    aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
    if (aRv.Failed()) {
      if (mState.IsSelectionCached()) {
        aSelectionStart = mState.GetSelectionProperties().mStart;
        aSelectionEnd = mState.GetSelectionProperties().mEnd;
        aRv = NS_OK;
      }
    }
  }

  if (aStart <= aEnd) {
    value.Replace(aStart, aEnd - aStart, aReplacement);
    SetValueInternal(value, false);
  }

  uint32_t newEnd = aStart + aReplacement.Length();
  int32_t delta =  aReplacement.Length() - (aEnd - aStart);

  switch (aSelectMode) {
    case mozilla::dom::SelectionMode::Select:
    {
      aSelectionStart = aStart;
      aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Start:
    {
      aSelectionStart = aSelectionEnd = aStart;
    }
    break;
    case mozilla::dom::SelectionMode::End:
    {
      aSelectionStart = aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Preserve:
    {
      if ((uint32_t)aSelectionStart > aEnd) {
        aSelectionStart += delta;
      } else if ((uint32_t)aSelectionStart > aStart) {
        aSelectionStart = aStart;
      }

      if ((uint32_t)aSelectionEnd > aEnd) {
        aSelectionEnd += delta;
      } else if ((uint32_t)aSelectionEnd > aStart) {
        aSelectionEnd = newEnd;
      }
    }
    break;
  }

  Optional<nsAString> direction;
  SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
  if (!aRv.Failed()) {
    nsRefPtr<nsAsyncDOMEvent> event =
      new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false);
    event->PostDOMEvent();
  }
}
void
DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue)
{
  // When the number of items in our internal counterpart changes, we MUST stay
  // in sync. Everything in the scary comment in
  // DOMSVGLengthList::InternalBaseValListWillChangeTo applies here just as
  // much, but we have the additional issue that failing to stay in sync would
  // mean that - assuming we aren't reading bad memory - we would likely end up
  // decoding command types from argument floats when looking in our
  // SVGPathData's data array! Either way, we'll likely then go down
  // NS_NOTREACHED code paths, or end up reading/setting more bad memory!!

  // The only time that our other DOM list type implementations remove items is
  // if those items become surplus items due to an attribute change or SMIL
  // animation sample shortening the list. In general though, they try to keep
  // their existing DOM items, even when things change. To be consistent, we'd
  // really like to do the same thing. However, because different types of path
  // segment correspond to different DOMSVGPathSeg subclasses, the type of
  // items in our list are generally not the same, which makes this harder for
  // us. We have to remove DOM segments if their type is not the same as the
  // type of the new internal segment at their index.
  //
  // We also need to sync up mInternalDataIndex, but since we need to loop over
  // all the items in the new list checking types anyway, that's almost
  // insignificant in terms of overhead.
  //
  // Note that this method is called on every single SMIL animation resample
  // and we have no way to short circuit the overhead since we don't have a
  // way to tell if the call is due to a new animation, or a resample of an
  // existing animation (when the number and type of items would be the same).
  // (Note that a new animation could start overriding an existing animation at
  // any time, so checking IsAnimating() wouldn't work.) Because we get called
  // on every sample, it would not be acceptable alternative to throw away all
  // our items and let them be recreated lazily, since that would break what
  // script sees!

  uint32_t length = mItems.Length();
  uint32_t index = 0;

  uint32_t dataLength = aNewValue.mData.Length();
  uint32_t dataIndex = 0; // index into aNewValue's raw data array

  uint32_t newSegType;

  nsRefPtr<DOMSVGPathSegList> kungFuDeathGrip;
  if (length) {
    // RemovingFromList() might clear last reference to |this|.
    // Retain a temporary reference to keep from dying before returning.
    //
    // NOTE: For path-seg lists (unlike other list types), we have to do this
    // *whenever our list is nonempty* (even if we're growing in length).
    // That's because the path-seg-type of any segment could differ between old
    // list vs. new list, which will make us destroy & recreate that segment,
    // which could remove the last reference to us.
    //
    // (We explicitly *don't* want to create a kungFuDeathGrip in the length=0
    // case, though, because we do hit this code inside our constructor before
    // any other owning references have been added, and at that point, the
    // deathgrip-removal would make us die before we exit our constructor.)
    kungFuDeathGrip = this;
  }

  while (index < length && dataIndex < dataLength) {
    newSegType = SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]);
    if (ItemAt(index) && ItemAt(index)->Type() != newSegType) {
      ItemAt(index)->RemovingFromList();
      ItemAt(index) = nullptr;
    }
    // Only after the RemovingFromList() can we touch mInternalDataIndex!
    mItems[index].mInternalDataIndex = dataIndex;
    ++index;
    dataIndex += 1 + SVGPathSegUtils::ArgCountForType(newSegType);
  }

  NS_ABORT_IF_FALSE((index == length && dataIndex <= dataLength) ||
                    (index <= length && dataIndex == dataLength),
                    "very bad - list corruption?");

  if (index < length) {
    // aNewValue has fewer items than our previous internal counterpart

    uint32_t newLength = index;

    // Remove excess items from the list:
    for (; index < length; ++index) {
      if (ItemAt(index)) {
        ItemAt(index)->RemovingFromList();
        ItemAt(index) = nullptr;
      }
    }

    // Only now may we truncate mItems
    mItems.SetLength(newLength);

  } else if (dataIndex < dataLength) {
    // aNewValue has more items than our previous internal counterpart

    // Sync mItems:
    while (dataIndex < dataLength) {
      if (mItems.Length() &&
          mItems.Length() - 1 > DOMSVGPathSeg::MaxListIndex()) {
        // It's safe to get out of sync with our internal list as long as we
        // have FEWER items than it does.
        return;
      }
      if (!mItems.AppendElement(ItemProxy(nullptr, dataIndex))) {
        // OOM
        ErrorResult rv;
        Clear(rv);
        MOZ_ASSERT(!rv.Failed());
        return;
      }
      dataIndex += 1 + SVGPathSegUtils::ArgCountForType(SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]));
    }
  }

  NS_ABORT_IF_FALSE(dataIndex == dataLength, "Serious processing error");
  NS_ABORT_IF_FALSE(index == length, "Serious counting error");
}
already_AddRefed<DOMSVGPathSeg>
DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem,
                               uint32_t aIndex,
                               ErrorResult& aError)
{
  if (IsAnimValList()) {
    aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    return nullptr;
  }

  if (aIndex >= LengthNoFlush()) {
    aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return nullptr;
  }

  nsRefPtr<DOMSVGPathSeg> domItem = &aNewItem;
  if (domItem->HasOwner()) {
    domItem = domItem->Clone(); // must do this before changing anything!
  }

  nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList();
  if (ItemAt(aIndex)) {
    // Notify any existing DOM item of removal *before* modifying the lists so
    // that the DOM item can copy the *old* value at its index:
    ItemAt(aIndex)->RemovingFromList();
  }

  uint32_t internalIndex = mItems[aIndex].mInternalDataIndex;
  // We use InternalList() to get oldArgCount since we may not have a DOM
  // wrapper at the index being replaced.
  uint32_t oldType = SVGPathSegUtils::DecodeType(InternalList().mData[internalIndex]);

  // NOTE: ArgCountForType returns a (small) unsigned value, but we're
  // intentionally putting it in a signed variable, because we're going to
  // subtract these values and might produce something negative.
  int32_t oldArgCount = SVGPathSegUtils::ArgCountForType(oldType);
  int32_t newArgCount = SVGPathSegUtils::ArgCountForType(domItem->Type());

  float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
  domItem->ToSVGPathSegEncodedData(segAsRaw);

  bool ok = !!InternalList().mData.ReplaceElementsAt(
                  internalIndex, 1 + oldArgCount,
                  segAsRaw, 1 + newArgCount);
  if (!ok) {
    aError.Throw(NS_ERROR_OUT_OF_MEMORY);
    return nullptr;
  }
  ItemAt(aIndex) = domItem;

  // This MUST come after the ToSVGPathSegEncodedData call, otherwise that call
  // would end up reading bad data from InternalList()!
  domItem->InsertingIntoList(this, aIndex, IsAnimValList());

  int32_t delta = newArgCount - oldArgCount;
  if (delta != 0) {
    for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
      mItems[i].mInternalDataIndex += delta;
    }
  }

  Element()->DidChangePathSegList(emptyOrOldValue);
  if (AttrIsAnimating()) {
    Element()->AnimationNeedsResample();
  }
  return domItem.forget();
}
NS_IMETHODIMP
nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
{
  nsAutoString tmpStr;
  aCssText.Truncate();
  nsresult result = NS_OK;

  switch (mType) {
    case CSS_PX :
      {
        float val = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
        nsStyleUtil::AppendCSSNumber(val, tmpStr);
        tmpStr.AppendLiteral("px");
        break;
      }
    case CSS_IDENT :
      {
        AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword),
                          tmpStr);
        break;
      }
    case CSS_STRING :
    case CSS_COUNTER : /* FIXME: COUNTER should use an object */
      {
        tmpStr.Append(mValue.mString);
        break;
      }
    case CSS_URI :
      {
        if (mValue.mURI) {
          nsAutoCString specUTF8;
          mValue.mURI->GetSpec(specUTF8);

          tmpStr.AssignLiteral("url(");
          nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8),
                                              tmpStr);
          tmpStr.AppendLiteral(")");
        } else {
          // http://dev.w3.org/csswg/css3-values/#attr defines
          // 'about:invalid' as the default value for url attributes,
          // so let's also use it here as the default computed value
          // for invalid URLs.
          tmpStr.Assign(NS_LITERAL_STRING("url(about:invalid)"));
        }
        break;
      }
    case CSS_ATTR :
      {
        tmpStr.AppendLiteral("attr(");
        tmpStr.Append(mValue.mString);
        tmpStr.Append(char16_t(')'));
        break;
      }
    case CSS_PERCENTAGE :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat * 100, tmpStr);
        tmpStr.Append(char16_t('%'));
        break;
      }
    case CSS_NUMBER :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        break;
      }
    case CSS_DEG :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        tmpStr.AppendLiteral("deg");
        break;
      }
    case CSS_GRAD :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        tmpStr.AppendLiteral("grad");
        break;
      }
    case CSS_RAD :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        tmpStr.AppendLiteral("rad");
        break;
      }
    case CSS_TURN :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        tmpStr.AppendLiteral("turn");
        break;
      }
    case CSS_RECT :
      {
        NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
        NS_NAMED_LITERAL_STRING(comma, ", ");
        nsCOMPtr<nsIDOMCSSPrimitiveValue> sideCSSValue;
        nsAutoString sideValue;
        tmpStr.AssignLiteral("rect(");
        // get the top
        result = mValue.mRect->GetTop(getter_AddRefs(sideCSSValue));
        if (NS_FAILED(result))
          break;
        result = sideCSSValue->GetCssText(sideValue);
        if (NS_FAILED(result))
          break;
        tmpStr.Append(sideValue + comma);
        // get the right
        result = mValue.mRect->GetRight(getter_AddRefs(sideCSSValue));
        if (NS_FAILED(result))
          break;
        result = sideCSSValue->GetCssText(sideValue);
        if (NS_FAILED(result))
          break;
        tmpStr.Append(sideValue + comma);
        // get the bottom
        result = mValue.mRect->GetBottom(getter_AddRefs(sideCSSValue));
        if (NS_FAILED(result))
          break;
        result = sideCSSValue->GetCssText(sideValue);
        if (NS_FAILED(result))
          break;
        tmpStr.Append(sideValue + comma);
        // get the left
        result = mValue.mRect->GetLeft(getter_AddRefs(sideCSSValue));
        if (NS_FAILED(result))
          break;
        result = sideCSSValue->GetCssText(sideValue);
        if (NS_FAILED(result))
          break;
        tmpStr.Append(sideValue + NS_LITERAL_STRING(")"));
        break;
      }
    case CSS_RGBCOLOR :
      {
        NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
        ErrorResult error;
        NS_NAMED_LITERAL_STRING(comma, ", ");
        nsAutoString colorValue;
        if (mValue.mColor->HasAlpha())
          tmpStr.AssignLiteral("rgba(");
        else
          tmpStr.AssignLiteral("rgb(");

        // get the red component
        mValue.mColor->Red()->GetCssText(colorValue, error);
        if (error.Failed())
          break;
        tmpStr.Append(colorValue + comma);

        // get the green component
        mValue.mColor->Green()->GetCssText(colorValue, error);
        if (error.Failed())
          break;
        tmpStr.Append(colorValue + comma);

        // get the blue component
        mValue.mColor->Blue()->GetCssText(colorValue, error);
        if (error.Failed())
          break;
        tmpStr.Append(colorValue);

        if (mValue.mColor->HasAlpha()) {
          // get the alpha component
          mValue.mColor->Alpha()->GetCssText(colorValue, error);
          if (error.Failed())
            break;
          tmpStr.Append(comma + colorValue);
        }

        tmpStr.Append(NS_LITERAL_STRING(")"));

        break;
      }
    case CSS_S :
      {
        nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
        tmpStr.AppendLiteral("s");
        break;
      }
    case CSS_CM :
    case CSS_MM :
    case CSS_IN :
    case CSS_PT :
    case CSS_PC :
    case CSS_UNKNOWN :
    case CSS_EMS :
    case CSS_EXS :
    case CSS_MS :
    case CSS_HZ :
    case CSS_KHZ :
    case CSS_DIMENSION :
      NS_ERROR("We have a bogus value set.  This should not happen");
      return NS_ERROR_DOM_INVALID_ACCESS_ERR;
  }

  if (NS_SUCCEEDED(result)) {
    aCssText.Assign(tmpStr);
  }

  return NS_OK;
}
NS_IMETHODIMP
FetchDriver::OnStartRequest(nsIRequest* aRequest,
                            nsISupports* aContext)
{
  workers::AssertIsOnMainThread();

  // Note, this can be called multiple times if we are doing an opaqueredirect.
  // In that case we will get a simulated OnStartRequest() and then the real
  // channel will call in with an errored OnStartRequest().

  nsresult rv;
  aRequest->GetStatus(&rv);
  if (NS_FAILED(rv)) {
    FailWithNetworkError();
    return rv;
  }

  // We should only get to the following code once.
  MOZ_ASSERT(!mPipeOutputStream);
  MOZ_ASSERT(mObserver);

  RefPtr<InternalResponse> response;
  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);

  // On a successful redirect we perform the following substeps of HTTP Fetch,
  // step 5, "redirect status", step 11.

  bool foundOpaqueRedirect = false;

  if (httpChannel) {
    uint32_t responseStatus;
    httpChannel->GetResponseStatus(&responseStatus);

    if (mozilla::net::nsHttpChannel::IsRedirectStatus(responseStatus)) {
      if (mRequest->GetRedirectMode() == RequestRedirect::Error) {
        FailWithNetworkError();
        return NS_BINDING_FAILED;
      }
      if (mRequest->GetRedirectMode() == RequestRedirect::Manual) {
        foundOpaqueRedirect = true;
      }
    }

    nsAutoCString statusText;
    httpChannel->GetResponseStatusText(statusText);

    response = new InternalResponse(responseStatus, statusText);

    RefPtr<FillResponseHeaders> visitor = new FillResponseHeaders(response);
    rv = httpChannel->VisitResponseHeaders(visitor);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      NS_WARNING("Failed to visit all headers.");
    }
  } else {
    response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));

    ErrorResult result;
    nsAutoCString contentType;
    rv = channel->GetContentType(contentType);
    if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) {
      nsAutoCString contentCharset;
      channel->GetContentCharset(contentCharset);
      if (NS_SUCCEEDED(rv) && !contentCharset.IsEmpty()) {
        contentType += NS_LITERAL_CSTRING(";charset=") + contentCharset;
      }

      response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"),
                                  contentType,
                                  result);
      MOZ_ASSERT(!result.Failed());
    }

    int64_t contentLength;
    rv = channel->GetContentLength(&contentLength);
    if (NS_SUCCEEDED(rv) && contentLength) {
      nsAutoCString contentLenStr;
      contentLenStr.AppendInt(contentLength);
      response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"),
                                  contentLenStr,
                                  result);
      MOZ_ASSERT(!result.Failed());
    }
  }

  // We open a pipe so that we can immediately set the pipe's read end as the
  // response's body. Setting the segment size to UINT32_MAX means that the
  // pipe has infinite space. The nsIChannel will continue to buffer data in
  // xpcom events even if we block on a fixed size pipe.  It might be possible
  // to suspend the channel and then resume when there is space available, but
  // for now use an infinite pipe to avoid blocking.
  nsCOMPtr<nsIInputStream> pipeInputStream;
  rv = NS_NewPipe(getter_AddRefs(pipeInputStream),
                  getter_AddRefs(mPipeOutputStream),
                  0, /* default segment size */
                  UINT32_MAX /* infinite pipe */,
                  true /* non-blocking input, otherwise you deadlock */,
                  false /* blocking output, since the pipe is 'in'finite */ );
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    // Cancel request.
    return rv;
  }
  response->SetBody(pipeInputStream);

  response->InitChannelInfo(channel);

  nsCOMPtr<nsIURI> channelURI;
  rv = channel->GetURI(getter_AddRefs(channelURI));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    // Cancel request.
    return rv;
  }

  nsCOMPtr<nsILoadInfo> loadInfo;
  rv = channel->GetLoadInfo(getter_AddRefs(loadInfo));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    return rv;
  }

  // Propagate any tainting from the channel back to our response here.  This
  // step is not reflected in the spec because the spec is written such that
  // FetchEvent.respondWith() just passes the already-tainted Response back to
  // the outer fetch().  In gecko, however, we serialize the Response through
  // the channel and must regenerate the tainting from the channel in the
  // interception case.
  mRequest->MaybeIncreaseResponseTainting(loadInfo->GetTainting());

  // Resolves fetch() promise which may trigger code running in a worker.  Make
  // sure the Response is fully initialized before calling this.
  mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect);

  nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    FailWithNetworkError();
    // Cancel request.
    return rv;
  }

  // Try to retarget off main thread.
  if (nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(aRequest)) {
    NS_WARN_IF(NS_FAILED(rr->RetargetDeliveryTo(sts)));
  }
  return NS_OK;
}
void
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                         const Optional<Sequence<JS::Value>>& aTransferable,
                         ErrorResult& aRv)
{
  // We *must* clone the data here, or the JS::Value could be modified
  // by script

  JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
  if (aTransferable.WasPassed()) {
    const Sequence<JS::Value>& realTransferable = aTransferable.Value();

    // Here we want to check if the transerable object list contains
    // this port. No other checks are done.
    for (const JS::Value& value : realTransferable) {
      if (!value.isObject()) {
        continue;
      }

      MessagePort* port = nullptr;
      nsresult rv = UNWRAP_OBJECT(MessagePort, &value.toObject(), port);
      if (NS_FAILED(rv)) {
        continue;
      }

      if (port == this) {
        aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
        return;
      }
    }

    // The input sequence only comes from the generated bindings code, which
    // ensures it is rooted.
    JS::HandleValueArray elements =
      JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
                                               realTransferable.Elements());

    JSObject* array =
      JS_NewArrayObject(aCx, elements);
    if (!array) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
      return;
    }

    transferable.setObject(*array);
  }

  RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();

  data->Write(aCx, aMessage, transferable, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return;
  }

  // This message has to be ignored.
  if (mState > eStateEntangled) {
    return;
  }

  // If we are unshipped we are connected to the other port on the same thread.
  if (mState == eStateUnshippedEntangled) {
    MOZ_ASSERT(mUnshippedEntangledPort);
    mUnshippedEntangledPort->mMessages.AppendElement(data);
    mUnshippedEntangledPort->Dispatch();
    return;
  }

  // Not entangled yet, but already closed/disentangled.
  if (mState == eStateEntanglingForDisentangle ||
      mState == eStateEntanglingForClose) {
    return;
  }

  RemoveDocFromBFCache();

  // Not entangled yet.
  if (mState == eStateEntangling) {
    mMessagesForTheOtherPort.AppendElement(data);
    return;
  }

  MOZ_ASSERT(mActor);
  MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());

  AutoTArray<RefPtr<SharedMessagePortMessage>, 1> array;
  array.AppendElement(data);

  AutoTArray<MessagePortMessage, 1> messages;
  SharedMessagePortMessage::FromSharedToMessagesChild(mActor, array, messages);
  mActor->SendPostMessages(messages);
}
Exemple #18
0
already_AddRefed<IDBRequest>
IDBIndex::GetAllInternal(bool aKeysOnly,
                         JSContext* aCx,
                         JS::Handle<JS::Value> aKey,
                         const Optional<uint32_t>& aLimit,
                         ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  IDBTransaction* transaction = mObjectStore->Transaction();
  if (!transaction->IsOpen()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
    return nullptr;
  }

  nsRefPtr<IDBKeyRange> keyRange;
  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  const int64_t objectStoreId = mObjectStore->Id();
  const int64_t indexId = Id();

  OptionalKeyRange optionalKeyRange;
  if (keyRange) {
    SerializedKeyRange serializedKeyRange;
    keyRange->ToSerialized(serializedKeyRange);
    optionalKeyRange = serializedKeyRange;
  } else {
    optionalKeyRange = void_t();
  }

  const uint32_t limit = aLimit.WasPassed() ? aLimit.Value() : 0;

  RequestParams params;
  if (aKeysOnly) {
    params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange,
                                   limit);
  } else {
    params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit);
  }

  nsRefPtr<IDBRequest> request = GenerateRequest(this);
  MOZ_ASSERT(request);

  if (aKeysOnly) {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
                   "getAllKeys(%s, %s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()",
                 IDB_LOG_ID_STRING(),
                 transaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(transaction->Database()),
                 IDB_LOG_STRINGIFY(transaction),
                 IDB_LOG_STRINGIFY(mObjectStore),
                 IDB_LOG_STRINGIFY(this),
                 IDB_LOG_STRINGIFY(keyRange),
                 IDB_LOG_STRINGIFY(aLimit));
  } else {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
                   "getAll(%s, %s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()",
                 IDB_LOG_ID_STRING(),
                 transaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(transaction->Database()),
                 IDB_LOG_STRINGIFY(transaction),
                 IDB_LOG_STRINGIFY(mObjectStore),
                 IDB_LOG_STRINGIFY(this),
                 IDB_LOG_STRINGIFY(keyRange),
                 IDB_LOG_STRINGIFY(aLimit));
  }

  transaction->StartRequest(request, params);

  return request.forget();
}
void
nsDOMFileReader::ReadFileContent(JSContext* aCx,
                                 nsIDOMBlob* aFile,
                                 const nsAString &aCharset,
                                 eDataFormat aDataFormat,
                                 ErrorResult& aRv)
{
  MOZ_ASSERT(aFile);

  //Implicit abort to clear any other activity going on
  Abort();
  mError = nullptr;
  SetDOMStringToNull(mResult);
  mTransferred = 0;
  mTotal = 0;
  mReadyState = nsIDOMFileReader::EMPTY;
  FreeFileData();

  mFile = aFile;
  mDataFormat = aDataFormat;
  CopyUTF16toUTF8(aCharset, mCharset);

  //Establish a channel with our file
  {
    // Hold the internal URL alive only as long as necessary
    // After the channel is created it will own whatever is backing
    // the DOMFile.
    nsDOMFileInternalUrlHolder urlHolder(mFile, mPrincipal);

    nsCOMPtr<nsIURI> uri;
    aRv = NS_NewURI(getter_AddRefs(uri), urlHolder.mUrl);
    NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());

    nsCOMPtr<nsILoadGroup> loadGroup;
    if (HasOrHasHadOwner()) {
      if (!GetOwner()) {
        aRv.Throw(NS_ERROR_FAILURE);
        return;
      }
      nsIDocument* doc = GetOwner()->GetExtantDoc();
      if (doc) {
        loadGroup = doc->GetDocumentLoadGroup();
      }
    }

    aRv = NS_NewChannel(getter_AddRefs(mChannel), uri, nullptr, loadGroup,
                        nullptr, nsIRequest::LOAD_BACKGROUND);
    NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());
  }

  //Obtain the total size of the file before reading
  mTotal = mozilla::dom::kUnknownSize;
  mFile->GetSize(&mTotal);

  aRv = mChannel->AsyncOpen(this, nullptr);
  NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode());

  //FileReader should be in loading state here
  mReadyState = nsIDOMFileReader::LOADING;
  DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));

  if (mDataFormat == FILE_AS_ARRAYBUFFER) {
    RootResultArrayBuffer();
    mResultArrayBuffer = JS_NewArrayBuffer(aCx, mTotal);
    if (!mResultArrayBuffer) {
      NS_WARNING("Failed to create JS array buffer");
      aRv.Throw(NS_ERROR_FAILURE);
    }
  }
}
Exemple #20
0
already_AddRefed<IDBRequest>
IDBIndex::OpenCursorInternal(bool aKeysOnly,
                             JSContext* aCx,
                             JS::Handle<JS::Value> aRange,
                             IDBCursorDirection aDirection,
                             ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  IDBTransaction* transaction = mObjectStore->Transaction();
  if (!transaction->IsOpen()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
    return nullptr;
  }

  nsRefPtr<IDBKeyRange> keyRange;
  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  int64_t objectStoreId = mObjectStore->Id();
  int64_t indexId = Id();

  OptionalKeyRange optionalKeyRange;

  if (keyRange) {
    SerializedKeyRange serializedKeyRange;
    keyRange->ToSerialized(serializedKeyRange);

    optionalKeyRange = Move(serializedKeyRange);
  } else {
    optionalKeyRange = void_t();
  }

  IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);

  OpenCursorParams params;
  if (aKeysOnly) {
    IndexOpenKeyCursorParams openParams;
    openParams.objectStoreId() = objectStoreId;
    openParams.indexId() = indexId;
    openParams.optionalKeyRange() = Move(optionalKeyRange);
    openParams.direction() = direction;

    params = Move(openParams);
  } else {
    IndexOpenCursorParams openParams;
    openParams.objectStoreId() = objectStoreId;
    openParams.indexId() = indexId;
    openParams.optionalKeyRange() = Move(optionalKeyRange);
    openParams.direction() = direction;

    params = Move(openParams);
  }

  nsRefPtr<IDBRequest> request = GenerateRequest(this);
  MOZ_ASSERT(request);

  if (aKeysOnly) {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
                   "openKeyCursor(%s, %s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()",
                 IDB_LOG_ID_STRING(),
                 transaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(transaction->Database()),
                 IDB_LOG_STRINGIFY(transaction),
                 IDB_LOG_STRINGIFY(mObjectStore),
                 IDB_LOG_STRINGIFY(this),
                 IDB_LOG_STRINGIFY(keyRange),
                 IDB_LOG_STRINGIFY(direction));
  } else {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
                   "openCursor(%s, %s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: "
                   "IDBObjectStore.openKeyCursor()",
                 IDB_LOG_ID_STRING(),
                 transaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(transaction->Database()),
                 IDB_LOG_STRINGIFY(transaction),
                 IDB_LOG_STRINGIFY(mObjectStore),
                 IDB_LOG_STRINGIFY(this),
                 IDB_LOG_STRINGIFY(keyRange),
                 IDB_LOG_STRINGIFY(direction));
  }

  BackgroundCursorChild* actor =
    new BackgroundCursorChild(request, this, direction);

  mObjectStore->Transaction()->OpenCursor(actor, params);

  return request.forget();
}
void
IDBCursor::ContinuePrimaryKey(JSContext* aCx,
                             JS::Handle<JS::Value> aKey,
                             JS::Handle<JS::Value> aPrimaryKey,
                             ErrorResult &aRv)
{
  AssertIsOnOwningThread();

  if (!mTransaction->IsOpen()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
    return;
  }

  if (IsSourceDeleted()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
    return;
  }

  if ((mType != Type_Index && mType != Type_IndexKey) ||
      (mDirection != NEXT && mDirection != PREV)) {
    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
    return;
  }

  if (!mHaveValue || mContinueCalled) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
    return;
  }

  Key key;
  aRv = key.SetFromJSVal(aCx, aKey);
  if (aRv.Failed()) {
    return;
  }

#ifdef ENABLE_INTL_API
  if (IsLocaleAware() && !key.IsUnset()) {
    Key tmp;
    aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale());
    if (aRv.Failed()) {
      return;
    }
    key = tmp;
  }

  const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
#else
  const Key& sortKey = mKey;
#endif

  if (key.IsUnset()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
    return;
  }

  Key primaryKey;
  aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey);
  if (aRv.Failed()) {
    return;
  }

  if (primaryKey.IsUnset()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
    return;
  }

  switch (mDirection) {
    case NEXT:
      if (key < sortKey ||
          (key == sortKey && primaryKey <= mPrimaryKey)) {
        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
        return;
      }
      break;

    case PREV:
      if (key > sortKey ||
          (key == sortKey && primaryKey >= mPrimaryKey)) {
        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
        return;
      }
      break;

    default:
      MOZ_CRASH("Unknown direction type!");
  }

  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
  mRequest->SetLoggingSerialNumber(requestSerialNumber);

  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                 "database(%s).transaction(%s).objectStore(%s)."
                 "index(%s).cursor(%s).continuePrimaryKey(%s, %s)",
               "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continuePrimaryKey()",
               IDB_LOG_ID_STRING(),
               mTransaction->LoggingSerialNumber(),
               requestSerialNumber,
               IDB_LOG_STRINGIFY(mTransaction->Database()),
               IDB_LOG_STRINGIFY(mTransaction),
               IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
               IDB_LOG_STRINGIFY(mSourceIndex),
               IDB_LOG_STRINGIFY(mDirection),
               IDB_LOG_STRINGIFY(key),
               IDB_LOG_STRINGIFY(primaryKey));

  mBackgroundActor->SendContinueInternal(ContinuePrimaryKeyParams(key, primaryKey));

  mContinueCalled = true;
}
// XXXkhuey the encoding should be off the main thread, but we're lazy.
void
HTMLCanvasElement::ToBlob(JSContext* aCx,
                          FileCallback& aCallback,
                          const nsAString& aType,
                          const Optional<JS::Handle<JS::Value> >& aParams,
                          ErrorResult& aRv)
{
  // do a trust check if this is a write-only canvas
  if (mWriteOnly && !nsContentUtils::IsCallerChrome()) {
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    return;
  }

  nsAutoString type;
  aRv = nsContentUtils::ASCIIToLower(aType, type);
  if (aRv.Failed()) {
    return;
  }

  JS::Value encoderOptions = aParams.WasPassed()
                             ? aParams.Value()
                             : JS::UndefinedValue();

  nsAutoString params;
  bool usingCustomParseOptions;
  aRv = ParseParams(aCx, type, encoderOptions, params, &usingCustomParseOptions);
  if (aRv.Failed()) {
    return;
  }

  bool fallbackToPNG = false;

  nsCOMPtr<nsIInputStream> stream;
  aRv = ExtractData(type, params, getter_AddRefs(stream), fallbackToPNG);
  // If there are unrecognized custom parse options, we should fall back to
  // the default values for the encoder without any options at all.
  if (aRv.ErrorCode() == NS_ERROR_INVALID_ARG && usingCustomParseOptions) {
    fallbackToPNG = false;
    aRv = ExtractData(type, EmptyString(), getter_AddRefs(stream), fallbackToPNG);
  }

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

  if (fallbackToPNG) {
    type.AssignLiteral("image/png");
  }

  uint64_t imgSize;
  aRv = stream->Available(&imgSize);
  if (aRv.Failed()) {
    return;
  }
  if (imgSize > UINT32_MAX) {
    aRv.Throw(NS_ERROR_FILE_TOO_BIG);
    return;
  }

  void* imgData = nullptr;
  aRv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
  if (aRv.Failed()) {
    return;
  }

  // The DOMFile takes ownership of the buffer
  nsRefPtr<nsDOMMemoryFile> blob =
    new nsDOMMemoryFile(imgData, imgSize, type);

  JSContext* cx = nsContentUtils::GetCurrentJSContext();
  if (cx) {
    JS_updateMallocCounter(cx, imgSize);
  }

  nsRefPtr<ToBlobRunnable> runnable = new ToBlobRunnable(aCallback, blob);
  aRv = NS_DispatchToCurrentThread(runnable);
}
already_AddRefed<IDBRequest>
IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv)
{
  AssertIsOnOwningThread();

  if (!mTransaction->IsOpen()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
    return nullptr;
  }

  if (!mTransaction->IsWriteAllowed()) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
    return nullptr;
  }

  if (IsSourceDeleted() ||
      !mHaveValue ||
      mType == Type_ObjectStoreKey ||
      mType == Type_IndexKey ||
      mContinueCalled) {
    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
    return nullptr;
  }

  MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
  MOZ_ASSERT(!mKey.IsUnset());

  IDBObjectStore* objectStore;
  if (mType == Type_ObjectStore) {
    objectStore = mSourceObjectStore;
  } else {
    objectStore = mSourceIndex->ObjectStore();
  }

  MOZ_ASSERT(objectStore);

  const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;

  JS::Rooted<JS::Value> key(aCx);
  aRv = primaryKey.ToJSVal(aCx, &key);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  RefPtr<IDBRequest> request =
    objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  request->SetSource(this);

  if (mType == Type_ObjectStore) {
  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                 "database(%s).transaction(%s).objectStore(%s)."
                 "cursor(%s).delete(%s)",
               "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
               IDB_LOG_ID_STRING(),
               mTransaction->LoggingSerialNumber(),
               request->LoggingSerialNumber(),
               IDB_LOG_STRINGIFY(mTransaction->Database()),
               IDB_LOG_STRINGIFY(mTransaction),
               IDB_LOG_STRINGIFY(objectStore),
               IDB_LOG_STRINGIFY(mDirection),
               IDB_LOG_STRINGIFY(objectStore, primaryKey));
  } else {
    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                   "database(%s).transaction(%s).objectStore(%s)."
                   "index(%s).cursor(%s).delete(%s)",
                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
                 IDB_LOG_ID_STRING(),
                 mTransaction->LoggingSerialNumber(),
                 request->LoggingSerialNumber(),
                 IDB_LOG_STRINGIFY(mTransaction->Database()),
                 IDB_LOG_STRINGIFY(mTransaction),
                 IDB_LOG_STRINGIFY(objectStore),
                 IDB_LOG_STRINGIFY(mSourceIndex),
                 IDB_LOG_STRINGIFY(mDirection),
                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
  }

  return request.forget();
}
bool HTMLRangeAccessible::SetCurValue(double aValue) {
  ErrorResult er;
  HTMLInputElement::FromNode(mContent)->SetValueAsNumber(aValue, er);
  return !er.Failed();
}
Exemple #25
0
// This function implements the "HTTP Fetch" algorithm from the Fetch spec.
// Functionality is often split between here, the CORS listener proxy and the
// Necko HTTP implementation.
nsresult
FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType)
{
  MOZ_ASSERT(NS_IsMainThread());

  // Step 1. "Let response be null."
  mResponse = nullptr;
  mOnStopRequestCalled = false;
  nsresult rv;

  nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoCString url;
  mRequest->GetURL(url);
  nsCOMPtr<nsIURI> uri;
  rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr, ios);
  NS_ENSURE_SUCCESS(rv, rv);

  // Unsafe requests aren't allowed with when using no-core mode.
  if (mRequest->Mode() == RequestMode::No_cors &&
      mRequest->UnsafeRequest() &&
      (!mRequest->HasSimpleMethod() ||
       !mRequest->Headers()->HasOnlySimpleHeaders())) {
    MOZ_ASSERT(false, "The API should have caught this");
    return NS_ERROR_DOM_BAD_URI;
  }

  // non-GET requests aren't allowed for blob.
  if (IsBlobURI(uri)) {
    nsAutoCString method;
    mRequest->GetMethod(method);
    if (!method.EqualsLiteral("GET")) {
      return NS_ERROR_DOM_NETWORK_ERR;
    }
  }

  // Step 2 deals with letting ServiceWorkers intercept requests. This is
  // handled by Necko after the channel is opened.
  // FIXME(nsm): Bug 1119026: The channel's skip service worker flag should be
  // set based on the Request's flag.

  // Step 3.1 "If the CORS preflight flag is set and one of these conditions is
  // true..." is handled by the CORS proxy.
  //
  // Step 3.2 "Set request's skip service worker flag." This isn't required
  // since Necko will fall back to the network if the ServiceWorker does not
  // respond with a valid Response.
  //
  // NS_StartCORSPreflight() will automatically kick off the original request
  // if it succeeds, so we need to have everything setup for the original
  // request too.

  // Step 3.3 "Let credentials flag be set if one of
  //  - request's credentials mode is "include"
  //  - request's credentials mode is "same-origin" and either the CORS flag
  //    is unset or response tainting is "opaque"
  // is true, and unset otherwise."

  // Set skip serviceworker flag.
  // While the spec also gates on the client being a ServiceWorker, we can't
  // infer that here. Instead we rely on callers to set the flag correctly.
  const nsLoadFlags bypassFlag = mRequest->SkipServiceWorker() ?
                                 nsIChannel::LOAD_BYPASS_SERVICE_WORKER : 0;

  nsSecurityFlags secFlags = nsILoadInfo::SEC_ABOUT_BLANK_INHERITS;
  if (mRequest->Mode() == RequestMode::Cors) {
    secFlags |= nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
  } else if (mRequest->Mode() == RequestMode::Same_origin ||
             mRequest->Mode() == RequestMode::Navigate) {
    secFlags |= nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
  } else if (mRequest->Mode() == RequestMode::No_cors) {
    secFlags |= nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
  } else {
    MOZ_ASSERT_UNREACHABLE("Unexpected request mode!");
    return NS_ERROR_UNEXPECTED;
  }

  if (mRequest->GetRedirectMode() != RequestRedirect::Follow) {
    secFlags |= nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS;
  }

  // This is handles the use credentials flag in "HTTP
  // network or cache fetch" in the spec and decides whether to transmit
  // cookies and other identifying information.
  if (mRequest->GetCredentialsMode() == RequestCredentials::Include) {
    secFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
  } else if (mRequest->GetCredentialsMode() == RequestCredentials::Omit) {
    secFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
  } else if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin) {
    secFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
  } else {
    MOZ_ASSERT_UNREACHABLE("Unexpected credentials mode!");
    return NS_ERROR_UNEXPECTED;
  }

  // From here on we create a channel and set its properties with the
  // information from the InternalRequest. This is an implementation detail.
  MOZ_ASSERT(mLoadGroup);
  nsCOMPtr<nsIChannel> chan;

  nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL |
    bypassFlag | nsIChannel::LOAD_CLASSIFY_URI;
  if (mDocument) {
    MOZ_ASSERT(mDocument->NodePrincipal() == mPrincipal);
    rv = NS_NewChannel(getter_AddRefs(chan),
                       uri,
                       mDocument,
                       secFlags,
                       mRequest->ContentPolicyType(),
                       nullptr, /* aPerformanceStorage */
                       mLoadGroup,
                       nullptr, /* aCallbacks */
                       loadFlags,
                       ios);
  } else if (mClientInfo.isSome()) {
    rv = NS_NewChannel(getter_AddRefs(chan),
                       uri,
                       mPrincipal,
                       mClientInfo.ref(),
                       mController,
                       secFlags,
                       mRequest->ContentPolicyType(),
                       mPerformanceStorage,
                       mLoadGroup,
                       nullptr, /* aCallbacks */
                       loadFlags,
                       ios);
  } else {
    rv = NS_NewChannel(getter_AddRefs(chan),
                       uri,
                       mPrincipal,
                       secFlags,
                       mRequest->ContentPolicyType(),
                       mPerformanceStorage,
                       mLoadGroup,
                       nullptr, /* aCallbacks */
                       loadFlags,
                       ios);
  }
  NS_ENSURE_SUCCESS(rv, rv);

  // Insert ourselves into the notification callbacks chain so we can set
  // headers on redirects.
#ifdef DEBUG
  {
    nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
    chan->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks));
    MOZ_ASSERT(!notificationCallbacks);
  }
#endif
  chan->SetNotificationCallbacks(this);

  nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(chan));
  // Mark channel as urgent-start if the Fetch is triggered by user input
  // events.
  if (cos && EventStateManager::IsHandlingUserInput()) {
    cos->AddClassFlags(nsIClassOfService::UrgentStart);
  }

  // Step 3.5 begins "HTTP network or cache fetch".
  // HTTP network or cache fetch
  // ---------------------------
  // Step 1 "Let HTTPRequest..." The channel is the HTTPRequest.
  nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
  if (httpChan) {
    // Copy the method.
    nsAutoCString method;
    mRequest->GetMethod(method);
    rv = httpChan->SetRequestMethod(method);
    NS_ENSURE_SUCCESS(rv, rv);

    // Set the same headers.
    SetRequestHeaders(httpChan);

    // Step 5 of https://fetch.spec.whatwg.org/#main-fetch
    // If request's referrer policy is the empty string and request's client is
    // non-null, then set request's referrer policy to request's client's
    // associated referrer policy.
    // Basically, "client" is not in our implementation, we use
    // EnvironmentReferrerPolicy of the worker or document context
    net::ReferrerPolicy net_referrerPolicy = mRequest->GetEnvironmentReferrerPolicy();
    if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) {
      mRequest->SetReferrerPolicy(net_referrerPolicy);
    }
    // Step 6 of https://fetch.spec.whatwg.org/#main-fetch
    // If request’s referrer policy is the empty string,
    // then set request’s referrer policy to the user-set default policy.
    if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) {
      nsCOMPtr<nsILoadInfo> loadInfo = httpChan->GetLoadInfo();
      bool isPrivate = loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0;
      net::ReferrerPolicy referrerPolicy = static_cast<net::ReferrerPolicy>(NS_GetDefaultReferrerPolicy(isPrivate));
      mRequest->SetReferrerPolicy(referrerPolicy);
    }

    rv = FetchUtil::SetRequestReferrer(mPrincipal,
                                       mDocument,
                                       httpChan,
                                       mRequest);
    NS_ENSURE_SUCCESS(rv, rv);

    // Bug 1120722 - Authorization will be handled later.
    // Auth may require prompting, we don't support it yet.
    // The next patch in this same bug prevents this from aborting the request.
    // Credentials checks for CORS are handled by nsCORSListenerProxy,

    nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(httpChan);

    // Conversion between enumerations is safe due to static asserts in
    // dom/workers/ServiceWorkerManager.cpp
    rv = internalChan->SetCorsMode(static_cast<uint32_t>(mRequest->Mode()));
    MOZ_ASSERT(NS_SUCCEEDED(rv));
    rv = internalChan->SetRedirectMode(static_cast<uint32_t>(mRequest->GetRedirectMode()));
    MOZ_ASSERT(NS_SUCCEEDED(rv));
    mRequest->MaybeSkipCacheIfPerformingRevalidation();
    rv = internalChan->SetFetchCacheMode(static_cast<uint32_t>(mRequest->GetCacheMode()));
    MOZ_ASSERT(NS_SUCCEEDED(rv));
    rv = internalChan->SetIntegrityMetadata(mRequest->GetIntegrity());
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    // Set the initiator type
    nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChan));
    if (timedChannel) {
      timedChannel->SetInitiatorType(NS_LITERAL_STRING("fetch"));
    }
  }

  // Step 5. Proxy authentication will be handled by Necko.

  // Continue setting up 'HTTPRequest'. Content-Type and body data.
  nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(chan);
  if (uploadChan) {
    nsAutoCString contentType;
    ErrorResult result;
    mRequest->Headers()->GetFirst(NS_LITERAL_CSTRING("content-type"), contentType, result);
    // We don't actually expect "result" to have failed here: that only happens
    // for invalid header names.  But if for some reason it did, just propagate
    // it out.
    if (result.Failed()) {
      return result.StealNSResult();
    }

    // Now contentType is the header that was set in mRequest->Headers(), or a
    // void string if no header was set.
#ifdef DEBUG
    bool hasContentTypeHeader =
      mRequest->Headers()->Has(NS_LITERAL_CSTRING("content-type"), result);
    MOZ_ASSERT(!result.Failed());
    MOZ_ASSERT_IF(!hasContentTypeHeader, contentType.IsVoid());
#endif // DEBUG

    int64_t bodyLength;
    nsCOMPtr<nsIInputStream> bodyStream;
    mRequest->GetBody(getter_AddRefs(bodyStream), &bodyLength);
    if (bodyStream) {
      nsAutoCString method;
      mRequest->GetMethod(method);
      rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType,
                                               bodyLength, method,
                                               false /* aStreamHasHeaders */);
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  // If preflight is required, start a "CORS preflight fetch"
  // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0. All the
  // implementation is handled by the http channel calling into
  // nsCORSListenerProxy. We just inform it which unsafe headers are included
  // in the request.
  if (mRequest->Mode() == RequestMode::Cors) {
    AutoTArray<nsCString, 5> unsafeHeaders;
    mRequest->Headers()->GetUnsafeHeaders(unsafeHeaders);
    nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
    if (loadInfo) {
      loadInfo->SetCorsPreflightInfo(unsafeHeaders, false);
    }
  }

  if (mIsTrackingFetch && nsContentUtils::IsTailingEnabled()) {
    cos->AddClassFlags(nsIClassOfService::Throttleable |
                       nsIClassOfService::Tail);
  }

  if (mIsTrackingFetch && nsContentUtils::IsLowerNetworkPriority()) {
    nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(chan);
    if (p) {
      p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
    }
  }

  // if the preferred alternative data type in InternalRequest is not empty, set
  // the data type on the created channel and also create a AlternativeDataStreamListener
  // to be the stream listener of the channel.
  if (!aPreferredAlternativeDataType.IsEmpty()) {
    nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(chan);
    if (cic) {
      cic->PreferAlternativeDataType(aPreferredAlternativeDataType);
      MOZ_ASSERT(!mAltDataListener);
      mAltDataListener =
        new AlternativeDataStreamListener(this, chan, aPreferredAlternativeDataType);
      rv = chan->AsyncOpen2(mAltDataListener);
    } else {
      rv = chan->AsyncOpen2(this);
    }
  } else {
    rv = chan->AsyncOpen2(this);
  }
  if (NS_FAILED(rv)) {
    return rv;
  }

  // Step 4 onwards of "HTTP Fetch" is handled internally by Necko.

  mChannel = chan;
  return NS_OK;
}
float
nsROCSSPrimitiveValue::GetFloatValue(uint16_t aUnitType, ErrorResult& aRv)
{
  switch(aUnitType) {
    case CSS_PX :
      if (mType == CSS_PX) {
        return nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
      }

      break;
    case CSS_CM :
      if (mType == CSS_PX) {
        return mValue.mAppUnits * CM_PER_INCH_FLOAT /
          nsPresContext::AppUnitsPerCSSInch();
      }

      break;
    case CSS_MM :
      if (mType == CSS_PX) {
        return mValue.mAppUnits * MM_PER_INCH_FLOAT /
          nsPresContext::AppUnitsPerCSSInch();
      }

      break;
    case CSS_IN :
      if (mType == CSS_PX) {
        return mValue.mAppUnits / nsPresContext::AppUnitsPerCSSInch();
      }

      break;
    case CSS_PT :
      if (mType == CSS_PX) {
        return mValue.mAppUnits * POINTS_PER_INCH_FLOAT /
          nsPresContext::AppUnitsPerCSSInch();
      }

      break;
    case CSS_PC :
      if (mType == CSS_PX) {
        return mValue.mAppUnits * 6.0f /
          nsPresContext::AppUnitsPerCSSInch();
      }

      break;
    case CSS_PERCENTAGE :
      if (mType == CSS_PERCENTAGE) {
        return mValue.mFloat * 100;
      }

      break;
    case CSS_NUMBER :
      if (mType == CSS_NUMBER) {
        return mValue.mFloat;
      }

      break;
    case CSS_UNKNOWN :
    case CSS_EMS :
    case CSS_EXS :
    case CSS_DEG :
    case CSS_RAD :
    case CSS_GRAD :
    case CSS_MS :
    case CSS_S :
    case CSS_HZ :
    case CSS_KHZ :
    case CSS_DIMENSION :
    case CSS_STRING :
    case CSS_URI :
    case CSS_IDENT :
    case CSS_ATTR :
    case CSS_COUNTER :
    case CSS_RECT :
    case CSS_RGBCOLOR :
      break;
  }

  aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
  return 0;
}
already_AddRefed<DOMCursor>
MobileMessageManager::GetMessages(const MobileMessageFilter& aFilter,
                                  bool aReverse,
                                  ErrorResult& aRv)
{
  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
  if (!dbService) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  bool hasStartDate = !aFilter.mStartDate.IsNull();
  uint64_t startDate = 0;
  if (hasStartDate) {
    startDate = aFilter.mStartDate.Value();
  }

  bool hasEndDate = !aFilter.mEndDate.IsNull();
  uint64_t endDate = 0;
  if (hasEndDate) {
    endDate = aFilter.mEndDate.Value();
  }

  UniquePtr<const char16_t*[]> ptrNumbers;
  uint32_t numbersCount = 0;
  if (!aFilter.mNumbers.IsNull() &&
      aFilter.mNumbers.Value().Length()) {
    const FallibleTArray<nsString>& numbers = aFilter.mNumbers.Value();
    uint32_t index;

    numbersCount = numbers.Length();
    ptrNumbers = MakeUnique<const char16_t*[]>(numbersCount);
    for (index = 0; index < numbersCount; index++) {
      ptrNumbers[index] = numbers[index].get();
    }
  }

  nsString delivery;
  delivery.SetIsVoid(true);
  if (!aFilter.mDelivery.IsNull()) {
    const uint32_t index = static_cast<uint32_t>(aFilter.mDelivery.Value());
    const EnumEntry& entry =
      MobileMessageFilterDeliveryValues::strings[index];
    delivery.AssignASCII(entry.value, entry.length);
  }

  bool hasRead = !aFilter.mRead.IsNull();
  bool read = false;
  if (hasRead) {
    read = aFilter.mRead.Value();
  }

  bool hasThreadId = !aFilter.mThreadId.IsNull();
  uint64_t threadId = 0;
  if (hasThreadId) {
    threadId = aFilter.mThreadId.Value();
  }

  RefPtr<MobileMessageCursorCallback> cursorCallback =
    new MobileMessageCursorCallback();
  nsCOMPtr<nsICursorContinueCallback> continueCallback;
  nsresult rv = dbService->CreateMessageCursor(hasStartDate, startDate,
                                               hasEndDate, endDate,
                                               ptrNumbers.get(), numbersCount,
                                               delivery,
                                               hasRead, read,
                                               hasThreadId, threadId,
                                               aReverse, cursorCallback,
                                               getter_AddRefs(continueCallback));
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
    return nullptr;
  }

  nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
  if (!window) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  cursorCallback->mDOMCursor =
    new MobileMessageCursor(window, continueCallback);

  RefPtr<DOMCursor> cursor(cursorCallback->mDOMCursor);
  return cursor.forget();
}
already_AddRefed<nsIDOMCounter>
nsROCSSPrimitiveValue::GetCounterValue(ErrorResult& aRv)
{
  aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
  return nullptr;
}
nsresult
nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
                                bool* aDidPrettyPrint)
{
    *aDidPrettyPrint = false;

    // Check for iframe with display:none. Such iframes don't have presshells
    if (!aDocument->GetShell()) {
        return NS_OK;
    }

    // check if we're in an invisible iframe
    nsPIDOMWindowOuter *internalWin = aDocument->GetWindow();
    nsCOMPtr<Element> frameElem;
    if (internalWin) {
        frameElem = internalWin->GetFrameElementInternal();
    }

    if (frameElem) {
        nsCOMPtr<nsICSSDeclaration> computedStyle;
        if (nsIDocument* frameOwnerDoc = frameElem->OwnerDoc()) {
            nsPIDOMWindowOuter* window = frameOwnerDoc->GetDefaultView();
            if (window) {
                nsCOMPtr<nsPIDOMWindowInner> innerWindow =
                    window->GetCurrentInnerWindow();

                ErrorResult dummy;
                computedStyle = innerWindow->GetComputedStyle(*frameElem,
                                                              EmptyString(),
                                                              dummy);
                dummy.SuppressException();
            }
        }

        if (computedStyle) {
            nsAutoString visibility;
            computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"),
                                            visibility);
            if (!visibility.EqualsLiteral("visible")) {

                return NS_OK;
            }
        }
    }

    // check the pref
    if (!Preferences::GetBool("layout.xml.prettyprint", true)) {
        return NS_OK;
    }

    // Ok, we should prettyprint. Let's do it!
    *aDidPrettyPrint = true;
    nsresult rv = NS_OK;

    // Load the XSLT
    nsCOMPtr<nsIURI> xslUri;
    rv = NS_NewURI(getter_AddRefs(xslUri),
                   NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIDOMDocument> xslDocument;
    rv = nsSyncLoadService::LoadDocument(xslUri, nsIContentPolicy::TYPE_XSLT,
                                         nsContentUtils::GetSystemPrincipal(),
                                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                                         nullptr, true, mozilla::net::RP_Default,
                                         getter_AddRefs(xslDocument));
    NS_ENSURE_SUCCESS(rv, rv);

    // Transform the document
    nsCOMPtr<nsIXSLTProcessor> transformer =
        do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt", &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = transformer->ImportStylesheet(xslDocument);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIDOMDocumentFragment> resultFragment;
    nsCOMPtr<nsIDOMDocument> sourceDocument = do_QueryInterface(aDocument);
    rv = transformer->TransformToFragment(sourceDocument, sourceDocument,
                                          getter_AddRefs(resultFragment));
    NS_ENSURE_SUCCESS(rv, rv);

    //
    // Apply the prettprint XBL binding.
    //
    // We take some shortcuts here. In particular, we don't bother invoking the
    // contstructor (since the binding has no constructor), and we don't bother
    // calling LoadBindingDocument because it's a chrome:// URI and thus will get
    // sync loaded no matter what.
    //

    // Grab the XBL service.
    nsXBLService* xblService = nsXBLService::GetInstance();
    NS_ENSURE_TRUE(xblService, NS_ERROR_NOT_AVAILABLE);

    // Compute the binding URI.
    nsCOMPtr<nsIURI> bindingUri;
    rv = NS_NewURI(getter_AddRefs(bindingUri),
        NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint"));
    NS_ENSURE_SUCCESS(rv, rv);

    // Compute the bound element.
    nsCOMPtr<nsIContent> rootCont = aDocument->GetRootElement();
    NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED);

    // Grab the system principal.
    nsCOMPtr<nsIPrincipal> sysPrincipal;
    nsContentUtils::GetSecurityManager()->
        GetSystemPrincipal(getter_AddRefs(sysPrincipal));

    // Load the bindings.
    RefPtr<nsXBLBinding> unused;
    bool ignored;
    rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal,
                                  getter_AddRefs(unused), &ignored);
    NS_ENSURE_SUCCESS(rv, rv);

    // Fire an event at the bound element to pass it |resultFragment|.
    RefPtr<CustomEvent> event =
      NS_NewDOMCustomEvent(rootCont, nullptr, nullptr);
    MOZ_ASSERT(event);
    nsCOMPtr<nsIWritableVariant> resultFragmentVariant = new nsVariant();
    rv = resultFragmentVariant->SetAsISupports(resultFragment);
    MOZ_ASSERT(NS_SUCCEEDED(rv));
    rv = event->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"),
                                /* bubbles = */ false, /* cancelable = */ false,
                                /* detail = */ resultFragmentVariant);
    NS_ENSURE_SUCCESS(rv, rv);
    event->SetTrusted(true);
    bool dummy;
    rv = rootCont->DispatchEvent(event, &dummy);
    NS_ENSURE_SUCCESS(rv, rv);

    // Observe the document so we know when to switch to "normal" view
    aDocument->AddObserver(this);
    mDocument = aDocument;

    NS_ADDREF_THIS();

    return NS_OK;
}
Exemple #30
0
void
Crypto::Logout(ErrorResult& aRv)
{
  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}