Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/CustomElementTypes.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/sessionstore/SessionStoreTypes.h"
#include "mozilla/dom/WindowContext.h"
#include "nsISessionStoreRestoreData.h"
#include "nsNetUtil.h"
namespace mozilla {
namespace dom {
bool SessionStoreRestoreData::IsEmpty() {
return (!mURI && mScroll.IsEmpty() && mInnerHTML.IsEmpty() &&
mEntries.IsEmpty() && mChildren.IsEmpty());
}
SessionStoreRestoreData* SessionStoreRestoreData::FindDataForChild(
BrowsingContext* aContext) {
nsTArray<uint32_t> path;
if (!aContext->GetOffsetPath(path)) {
return nullptr;
}
SessionStoreRestoreData* data = this;
for (uint32_t offset : Reversed(path)) {
if (!data || data->mChildren.Length() <= offset ||
!data->mChildren[offset] || data->mChildren[offset]->IsEmpty()) {
return nullptr;
}
data = data->mChildren[offset];
}
return data;
}
bool SessionStoreRestoreData::CanRestoreInto(nsIURI* aDocumentURI) {
if (!mURI) {
// This should mean that we don't have form data. It's fine to restore this
// data into any document — the worst that will happen is that we restore an
// incorrect scroll position.
MOZ_ASSERT(mEntries.IsEmpty());
MOZ_ASSERT(mInnerHTML.IsEmpty());
return true;
}
bool equalsExceptRef = false;
return (aDocumentURI &&
NS_SUCCEEDED(mURI->EqualsExceptRef(aDocumentURI, &equalsExceptRef)) &&
equalsExceptRef);
}
bool SessionStoreRestoreData::RestoreInto(RefPtr<BrowsingContext> aContext) {
if (!aContext->IsInProcess()) {
return false;
}
if (WindowContext* window = aContext->GetCurrentWindowContext()) {
if (!mScroll.IsEmpty()) {
if (nsGlobalWindowInner* inner = window->GetInnerWindow()) {
SessionStoreUtils::RestoreScrollPosition(*inner, mScroll);
}
}
if (mURI) {
if (nsCOMPtr<Document> doc = window->GetExtantDoc()) {
if (!CanRestoreInto(doc->GetDocumentURI())) {
return false;
}
SessionStoreUtils::RestoreFormData(*doc, mInnerHTML, mEntries);
}
}
}
return true;
}
void SessionStoreRestoreData::AddFormEntry(
bool aIsXPath, const nsAString& aIdOrXPath,
sessionstore::FormEntryValue aValue) {
mEntries.AppendElement(
Entry{sessionstore::FormEntry{nsString(aIdOrXPath), aValue}, aIsXPath});
}
NS_IMPL_ISUPPORTS(SessionStoreRestoreData, nsISessionStoreRestoreData,
SessionStoreRestoreData)
NS_IMETHODIMP
SessionStoreRestoreData::GetUrl(nsACString& aURL) {
if (mURI) {
nsresult rv = mURI->GetSpec(aURL);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::SetUrl(const nsACString& aURL) {
nsresult rv = NS_NewURI(getter_AddRefs(mURI), aURL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::GetInnerHTML(nsAString& aInnerHTML) {
aInnerHTML = mInnerHTML;
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::SetInnerHTML(const nsAString& aInnerHTML) {
mInnerHTML = aInnerHTML;
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::GetScroll(nsACString& aScroll) {
aScroll = mScroll;
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::SetScroll(const nsACString& aScroll) {
mScroll = aScroll;
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddTextField(bool aIsXPath,
const nsAString& aIdOrXPath,
const nsAString& aValue) {
AddFormEntry(aIsXPath, aIdOrXPath, sessionstore::TextField{nsString(aValue)});
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddCheckbox(bool aIsXPath, const nsAString& aIdOrXPath,
const bool aValue) {
AddFormEntry(aIsXPath, aIdOrXPath, sessionstore::Checkbox{aValue});
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddFileList(bool aIsXPath, const nsAString& aIdOrXPath,
const nsAString& aType,
const nsTArray<nsString>& aFileList) {
AddFormEntry(aIsXPath, aIdOrXPath, sessionstore::FileList{aFileList});
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddSingleSelect(bool aIsXPath,
const nsAString& aIdOrXPath,
uint32_t aSelectedIndex,
const nsAString& aValue) {
AddFormEntry(aIsXPath, aIdOrXPath,
sessionstore::SingleSelect{aSelectedIndex, nsString(aValue)});
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddMultipleSelect(bool aIsXPath,
const nsAString& aIdOrXPath,
const nsTArray<nsString>& aValues) {
AddFormEntry(aIsXPath, aIdOrXPath, sessionstore::MultipleSelect{aValues});
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddCustomElement(bool aIsXPath,
const nsAString& aIdOrXPath,
JS::Handle<JS::Value> aValue,
JS::Handle<JS::Value> aState) {
AutoJSContext cx;
Nullable<OwningFileOrUSVStringOrFormData> value;
if (!aValue.isNull() && !value.SetValue().Init(cx, aValue)) {
return NS_ERROR_FAILURE;
}
Nullable<OwningFileOrUSVStringOrFormData> state;
if (!aState.isNull() && !state.SetValue().Init(cx, aState)) {
return NS_ERROR_FAILURE;
}
AddFormEntry(aIsXPath, aIdOrXPath,
CustomElementTuple(
nsContentUtils::ConvertToCustomElementFormValue(value),
nsContentUtils::ConvertToCustomElementFormValue(state)));
return NS_OK;
}
NS_IMETHODIMP
SessionStoreRestoreData::AddChild(nsISessionStoreRestoreData* aChild,
uint32_t aIndex) {
if (nsCOMPtr<SessionStoreRestoreData> child = do_QueryInterface(aChild)) {
if (aIndex > mChildren.Length()) {
mChildren.SetLength(aIndex);
}
mChildren.InsertElementAt(aIndex, child);
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla