/* -*- 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 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 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 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& 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& aValues) { AddFormEntry(aIsXPath, aIdOrXPath, sessionstore::MultipleSelect{aValues}); return NS_OK; } NS_IMETHODIMP SessionStoreRestoreData::AddCustomElement(bool aIsXPath, const nsAString& aIdOrXPath, JS::Handle aValue, JS::Handle aState) { AutoJSContext cx; Nullable value; if (!aValue.isNull() && !value.SetValue().Init(cx, aValue)) { return NS_ERROR_FAILURE; } Nullable 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 child = do_QueryInterface(aChild)) { if (aIndex > mChildren.Length()) { mChildren.SetLength(aIndex); } mChildren.InsertElementAt(aIndex, child); } return NS_OK; } } // namespace dom } // namespace mozilla