nsresult
SessionStorageCache::SetItem(DataSetType aDataSetType, const nsAString& aKey,
                             const nsAString& aValue, nsString& aOldValue)
{
  int64_t delta = 0;
  DataSet* dataSet = Set(aDataSetType);

  if (!dataSet->mKeys.Get(aKey, &aOldValue)) {
    SetDOMStringToNull(aOldValue);

    // We only consider key size if the key doesn't exist before.
    delta = static_cast<int64_t>(aKey.Length());
  }

  delta += static_cast<int64_t>(aValue.Length()) -
           static_cast<int64_t>(aOldValue.Length());

  if (aValue == aOldValue &&
      DOMStringIsNull(aValue) == DOMStringIsNull(aOldValue)) {
    return NS_SUCCESS_DOM_NO_OPERATION;
  }

  if (!dataSet->ProcessUsageDelta(delta)) {
    return NS_ERROR_DOM_QUOTA_REACHED;
  }

  dataSet->mKeys.Put(aKey, nsString(aValue));
  return NS_OK;
}
nsresult
LocalStorageCache::SetItem(const LocalStorage* aStorage, const nsAString& aKey,
                           const nsString& aValue, nsString& aOld,
                           const MutationSource aSource)
{
  // Size of the cache that will change after this action.
  int64_t delta = 0;

  if (Persist(aStorage)) {
    WaitForPreload(Telemetry::LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS);
    if (NS_FAILED(mLoadResult)) {
      return mLoadResult;
    }
  }

  Data& data = DataSet(aStorage);
  if (!data.mKeys.Get(aKey, &aOld)) {
    SetDOMStringToNull(aOld);

    // We only consider key size if the key doesn't exist before.
    delta += static_cast<int64_t>(aKey.Length());
  }

  delta += static_cast<int64_t>(aValue.Length()) -
           static_cast<int64_t>(aOld.Length());

  if (!ProcessUsageDelta(aStorage, delta, aSource)) {
    return NS_ERROR_DOM_QUOTA_REACHED;
  }

  if (aValue == aOld && DOMStringIsNull(aValue) == DOMStringIsNull(aOld)) {
    return NS_SUCCESS_DOM_NO_OPERATION;
  }

  data.mKeys.Put(aKey, aValue);

  if (aSource == ContentMutation && Persist(aStorage)) {
    if (!sDatabase) {
      NS_ERROR("Writing to localStorage after the database has been shut down"
               ", data lose!");
      return NS_ERROR_NOT_INITIALIZED;
    }

    if (DOMStringIsNull(aOld)) {
      return sDatabase->AsyncAddItem(this, aKey, aValue);
    }

    return sDatabase->AsyncUpdateItem(this, aKey, aValue);
  }

  return NS_OK;
}
nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
    (nsIAtom* aPrefix, int32_t& aID)
{
    aID = kNameSpaceID_Unknown;

    if (!mResolver) {
        return NS_ERROR_DOM_NAMESPACE_ERR;
    }

    nsAutoString prefix;
    if (aPrefix) {
        aPrefix->ToString(prefix);
    }

    nsVoidableString ns;
    nsresult rv = mResolver->LookupNamespaceURI(prefix, ns);
    NS_ENSURE_SUCCESS(rv, rv);

    if (DOMStringIsNull(ns)) {
        return NS_ERROR_DOM_NAMESPACE_ERR;
    }

    if (ns.IsEmpty()) {
        aID = kNameSpaceID_None;

        return NS_OK;
    }

    // get the namespaceID for the URI
    return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
}
nsresult
DOMStorageCache::SetItem(const DOMStorage* aStorage, const nsAString& aKey,
                         const nsString& aValue, nsString& aOld)
{
  if (Persist(aStorage)) {
    WaitForPreload(Telemetry::LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS);
    if (NS_FAILED(mLoadResult)) {
      return mLoadResult;
    }
  }

  Data& data = DataSet(aStorage);
  if (!data.mKeys.Get(aKey, &aOld)) {
    SetDOMStringToNull(aOld);
  }

  // Check the quota first
  const int64_t delta = static_cast<int64_t>(aValue.Length()) -
                        static_cast<int64_t>(aOld.Length());
  if (!ProcessUsageDelta(aStorage, delta)) {
    return NS_ERROR_DOM_QUOTA_REACHED;
  }

  if (aValue == aOld && DOMStringIsNull(aValue) == DOMStringIsNull(aOld)) {
    return NS_SUCCESS_DOM_NO_OPERATION;
  }

  data.mKeys.Put(aKey, aValue);

  if (Persist(aStorage)) {
    if (!sDatabase) {
      NS_ERROR("Writing to localStorage after the database has been shut down"
               ", data lose!");
      return NS_ERROR_NOT_INITIALIZED;
    }

    if (DOMStringIsNull(aOld)) {
      return sDatabase->AsyncAddItem(this, aKey, aValue);
    }

    return sDatabase->AsyncUpdateItem(this, aKey, aValue);
  }

  return NS_OK;
}
nsresult
DOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
                                  const nsAString& aQualifiedName,
                                  nsIDOMDocumentType* aDoctype,
                                  nsIDocument** aDocument,
                                  nsIDOMDocument** aDOMDocument)
{
  *aDocument = nullptr;
  *aDOMDocument = nullptr;

  nsresult rv;
  if (!aQualifiedName.IsEmpty()) {
    const nsAFlatString& qName = PromiseFlatString(aQualifiedName);
    const char16_t *colon;
    rv = nsContentUtils::CheckQName(qName, true, &colon);
    NS_ENSURE_SUCCESS(rv, rv);

    if (colon &&
        (DOMStringIsNull(aNamespaceURI) ||
         (Substring(qName.get(), colon).EqualsLiteral("xml") &&
          !aNamespaceURI.EqualsLiteral("http://www.w3.org/XML/1998/namespace")))) {
      return NS_ERROR_DOM_NAMESPACE_ERR;
    }
  }

  nsCOMPtr<nsIGlobalObject> scriptHandlingObject =
    do_QueryReferent(mScriptObject);

  NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);

  nsCOMPtr<nsIDOMDocument> document;

  rv = NS_NewDOMDocument(getter_AddRefs(document),
                         aNamespaceURI, aQualifiedName, aDoctype,
                         mDocumentURI, mBaseURI,
                         mOwner->NodePrincipal(),
                         true, scriptHandlingObject,
                         DocumentFlavorLegacyGuess);
  NS_ENSURE_SUCCESS(rv, rv);

  // When DOMImplementation's createDocument method is invoked with
  // namespace set to HTML Namespace use the registry of the associated
  // document to the new instance.
  nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
  if (aNamespaceURI.EqualsLiteral("http://www.w3.org/1999/xhtml")) {
    doc->UseRegistryFromDocument(mOwner);
  }

  doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);

  doc.forget(aDocument);
  document.forget(aDOMDocument);
  return NS_OK;
}
nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
    (nsIAtom* aPrefix, int32_t& aID)
{
    aID = kNameSpaceID_Unknown;

    if (!mResolver && !mResolverNode) {
        return NS_ERROR_DOM_NAMESPACE_ERR;
    }

    nsAutoString prefix;
    if (aPrefix) {
        aPrefix->ToString(prefix);
    }

    nsVoidableString ns;
    if (mResolver) {
        ErrorResult rv;
        mResolver->LookupNamespaceURI(prefix, ns, rv);
        if (rv.Failed()) {
            return rv.StealNSResult();
        }
    } else {
        if (aPrefix == nsGkAtoms::xml) {
            ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
        } else {
            mResolverNode->LookupNamespaceURI(prefix, ns);
        }
    }

    if (DOMStringIsNull(ns)) {
        return NS_ERROR_DOM_NAMESPACE_ERR;
    }

    if (ns.IsEmpty()) {
        aID = kNameSpaceID_None;

        return NS_OK;
    }

    // get the namespaceID for the URI
    return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
}
nsresult
DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
                                      nsIDocument** aDocument,
                                      nsIDOMDocument** aDOMDocument)
{
  *aDocument = nullptr;
  *aDOMDocument = nullptr;

  NS_ENSURE_STATE(mOwner);

  nsCOMPtr<nsIDOMDocumentType> doctype;
  // Indicate that there is no internal subset (not just an empty one)
  nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype),
                                      mOwner->NodeInfoManager(),
                                      nsGkAtoms::html, // aName
                                      EmptyString(), // aPublicId
                                      EmptyString(), // aSystemId
                                      NullString()); // aInternalSubset
  NS_ENSURE_SUCCESS(rv, rv);


  nsCOMPtr<nsIGlobalObject> scriptHandlingObject =
    do_QueryReferent(mScriptObject);

  NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);

  nsCOMPtr<nsIDOMDocument> document;
  rv = NS_NewDOMDocument(getter_AddRefs(document),
                         EmptyString(), EmptyString(),
                         doctype, mDocumentURI, mBaseURI,
                         mOwner->NodePrincipal(),
                         true, scriptHandlingObject,
                         DocumentFlavorLegacyGuess);
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);

  nsCOMPtr<nsIContent> root;
  rv = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr, kNameSpaceID_XHTML,
                       getter_AddRefs(root));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = doc->AppendChildTo(root, false);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIContent> head;
  rv = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr, kNameSpaceID_XHTML,
                       getter_AddRefs(head));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = root->AppendChildTo(head, false);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!DOMStringIsNull(aTitle)) {
    nsCOMPtr<nsIContent> title;
    rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr,
                         kNameSpaceID_XHTML, getter_AddRefs(title));
    NS_ENSURE_SUCCESS(rv, rv);
    rv = head->AppendChildTo(title, false);
    NS_ENSURE_SUCCESS(rv, rv);

    nsRefPtr<nsTextNode> titleText = new nsTextNode(doc->NodeInfoManager());
    rv = titleText->SetText(aTitle, false);
    NS_ENSURE_SUCCESS(rv, rv);
    rv = title->AppendChildTo(titleText, false);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsCOMPtr<nsIContent> body;
  rv = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML,
                       getter_AddRefs(body));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = root->AppendChildTo(body, false);
  NS_ENSURE_SUCCESS(rv, rv);

  doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);

  doc.forget(aDocument);
  document.forget(aDOMDocument);
  return NS_OK;
}