import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,40 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIBFCacheEntry.idl',
'nsIGroupedSHistory.idl',
'nsIPartialSHistory.idl',
'nsIPartialSHistoryListener.idl',
'nsISHContainer.idl',
'nsISHEntry.idl',
'nsISHistory.idl',
'nsISHistoryInternal.idl',
'nsISHistoryListener.idl',
'nsISHTransaction.idl',
]
XPIDL_MODULE = 'shistory'
EXPORTS += [
'nsSHEntryShared.h',
]
UNIFIED_SOURCES += [
'nsSHEntry.cpp',
'nsSHEntryShared.cpp',
'nsSHistory.cpp',
'nsSHTransaction.cpp',
]
LOCAL_INCLUDES += [
'/docshell/base',
]
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsISupports.idl"
/**
* This interface lets you evict a document from the back/forward cache.
*/
[scriptable, uuid(a576060e-c7df-4d81-aa8c-5b52bd6ad25d)]
interface nsIBFCacheEntry : nsISupports
{
void RemoveFromBFCacheSync();
void RemoveFromBFCacheAsync();
readonly attribute unsigned long long ID;
};

View file

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIFrameLoader;
interface nsIPartialSHistory;
/**
* nsIGroupedSHistory represent a combined session history across multiple
* root docshells (usually browser tabs). The participating nsISHistory can
* either be in chrome process or in content process, but nsIGroupedSHistory
* itself lives in chrome process. The communication is proxyed through
* nsIPartialSHistory.
*/
[scriptable, builtinclass, uuid(813e498d-73a8-449a-be09-6187e62c5352)]
interface nsIGroupedSHistory : nsISupports
{
// The total number of entries of all its partial session histories.
[infallible] readonly attribute unsigned long count;
/**
* Remove all partial histories after currently active one (if any) and then
* append the given partial session history to the end of the list.
*/
void appendPartialSessionHistory(in nsIPartialSHistory aPartialHistory);
/**
* Notify the grouped session history that the active partial session history
* has been modified. All partial session histories after the active one
* will be removed and destroy.
*/
void onPartialSessionHistoryChange(in nsIPartialSHistory aPartialHistory);
/**
* Find the proper partial session history and navigate to the entry
* corresponding to the given global index. Note it doesn't swap frameloaders,
* but rather return the target loader for the caller to swap.
*
* @param aGlobalIndex The global index to navigate to.
* @param aTargetLoaderToSwap The owner frameloader of the to-be-navigate
* partial session history.
*/
void gotoIndex(in unsigned long aGlobalIndex, out nsIFrameLoader aTargetLoaderToSwap);
};

View file

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIFrameLoader;
/**
* nsIPartialSHistory represents a part of nsIGroupedSHistory. It associates to
* a "partial" nsISHistory in either local or remote process.
*/
[scriptable, builtinclass, uuid(5cd75e28-838c-4a0a-972e-6005f736ef7a)]
interface nsIPartialSHistory : nsISupports
{
// The number of entries of its corresponding nsISHistory.
[infallible] readonly attribute unsigned long count;
// If it's part of a grouped session history, globalIndexOffset denotes the
// number of entries ahead.
[infallible] readonly attribute unsigned long globalIndexOffset;
// The frameloader which owns this partial session history.
readonly attribute nsIFrameLoader ownerFrameLoader;
/**
* Notify that it's been added to a grouped session history. It also implies
* it's becoming the active partial history of the group.
*
* @param aOffset The number of entries in preceding partial
* session histories.
*/
void onAttachGroupedSessionHistory(in unsigned long aOffset);
/**
* Notify that one or more entries in its associated nsISHistory object
* have been changed (i.e. add / remove / replace). It's mainly used for
* cross-process case, since in the in-process case we can just register an
* nsISHistoryListener instead.
*
* @param aCount The number of entries in the associated session history.
* It can be the same as the old value if entries were replaced.
*/
void onSessionHistoryChange(in unsigned long aCount);
/**
* Notify that the partial session history has been swapped in as the active
* session history. Only an active session history can possibly add / remove /
* replace its history entries.
*
* @param aGlobalLength The up-to-date global length.
* @param aTargetLocalIndex The local index to navigate to.
*/
void onActive(in unsigned long aGlobalLength, in unsigned long aTargetLocalIndex);
/**
* Notify that the partial session history has been swapped out and is no
* longer active.
*/
void onDeactive();
};

View file

@ -0,0 +1,24 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
/**
* Listener to handle cross partial nsISHistory navigation requests.
*/
[scriptable, uuid(be0cd2b6-6f03-4366-9fe2-184c914ff3df)]
interface nsIPartialSHistoryListener : nsISupports
{
/**
* Called when the navigation target belongs to another nsISHistory within
* the same nsIGroupedSHistory, and it needs to initiate cross nsISHistory
* navigation.
*
* @param aIndex The index of complete history to navigate to.
*/
void onRequestCrossBrowserNavigation(in unsigned long aIndex);
};

View file

@ -0,0 +1,49 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
interface nsISHEntry;
/**
* The nsISHEntryContainer. The interface to access child entries
* of an nsISHEntry.
*
*/
[scriptable, uuid(67dd0357-8372-4122-bff6-217435e8b7e4)]
interface nsISHContainer : nsISupports
{
/**
* The current number of nsISHEntries which are immediate children of the
* current SHEntry
*/
readonly attribute long childCount;
/**
* Add a new child SHEntry. If offset is -1 adds to the end of the list.
*/
void AddChild(in nsISHEntry child, in long offset);
/**
* Removes a child SHEntry
*/
void RemoveChild(in nsISHEntry child);
/**
* Get child at an index
*/
nsISHEntry GetChildAt(in long index);
/**
* Replaces a child which is for the same docshell as aNewChild
* with aNewChild.
* @throw if nothing was replaced.
*/
void ReplaceChild(in nsISHEntry aNewChild);
};

View file

@ -0,0 +1,352 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
/**
* The interface to nsISHentry. Each document or subframe in
* Session History will have a nsISHEntry associated with it which will
* hold all information required to recreate the document from history
*
*/
#include "nsISupports.idl"
interface nsIMutableArray;
interface nsILayoutHistoryState;
interface nsIContentViewer;
interface nsIURI;
interface nsIInputStream;
interface nsIDocShellTreeItem;
interface nsIStructuredCloneContainer;
interface nsIBFCacheEntry;
interface nsIPrincipal;
%{C++
#include "nsRect.h"
class nsDocShellEditorData;
class nsSHEntryShared;
%}
[ref] native nsIntRect(nsIntRect);
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
[ptr] native nsSHEntryShared(nsSHEntryShared);
[scriptable, uuid(0dad26b8-a259-42c7-93f1-2fa7fc076e45)]
interface nsISHEntry : nsISupports
{
/**
* A readonly property that returns the URI
* of the current entry. The object returned is
* of type nsIURI
*/
readonly attribute nsIURI URI;
/**
* A readonly property that returns the original URI of the current entry.
* If an entry is the result of a redirect this attribute holds original
* URI. The object returned is of type nsIURI
*/
attribute nsIURI originalURI;
/**
* This flag remembers whether channel has LOAD_REPLACE set.
*/
attribute boolean loadReplace;
/**
* A readonly property that returns the title
* of the current entry. The object returned
* is a encoded string
*/
readonly attribute wstring title;
/**
* A readonly property that returns a boolean
* flag which indicates if the entry was created as a
* result of a subframe navigation. This flag will be
* 'false' when a frameset page is visited for
* the first time. This flag will be 'true' for all
* history entries created as a result of a subframe
* navigation.
*/
readonly attribute boolean isSubFrame;
/** URI for the document */
void setURI(in nsIURI aURI);
/** Referrer URI */
attribute nsIURI referrerURI;
/** Referrer policy, holding one of the values (REFERRER_POLICY_*)
* defined in nsIHttpChannel.
*/
attribute unsigned long referrerPolicy;
/** Content viewer, for fast restoration of presentation */
attribute nsIContentViewer contentViewer;
/** Whether the content viewer is marked "sticky" */
attribute boolean sticky;
/** Saved state of the global window object */
attribute nsISupports windowState;
/**
* Saved position and dimensions of the content viewer; we must adjust the
* root view's widget accordingly if this has changed when the presentation
* is restored.
*/
[noscript] void getViewerBounds(in nsIntRect bounds);
[noscript] void setViewerBounds([const] in nsIntRect bounds);
/**
* Saved child docshells corresponding to contentViewer. The child shells
* are restored as children of the parent docshell, in this order, when the
* parent docshell restores a saved presentation.
*/
/** Append a child shell to the end of our list. */
void addChildShell(in nsIDocShellTreeItem shell);
/**
* Get the child shell at |index|; returns null if |index| is out of bounds.
*/
nsIDocShellTreeItem childShellAt(in long index);
/**
* Clear the child shell list.
*/
void clearChildShells();
/** Saved refresh URI list for the content viewer */
attribute nsIMutableArray refreshURIList;
/**
* Ensure that the cached presentation members are self-consistent.
* If either |contentViewer| or |windowState| are null, then all of the
* following members are cleared/reset:
* contentViewer, sticky, windowState, viewerBounds, childShells,
* refreshURIList.
*/
void syncPresentationState();
/** Title for the document */
void setTitle(in AString aTitle);
/** Post Data for the document */
attribute nsIInputStream postData;
/** LayoutHistoryState for scroll position and form values */
attribute nsILayoutHistoryState layoutHistoryState;
/** parent of this entry */
attribute nsISHEntry parent;
/**
* The loadType for this entry. This is typically loadHistory except
* when reload is pressed, it has the appropriate reload flag
*/
attribute unsigned long loadType;
/**
* An ID to help identify this entry from others during
* subframe navigation
*/
attribute unsigned long ID;
/** attribute to set and get the cache key for the entry */
attribute nsISupports cacheKey;
/** attribute to indicate whether layoutHistoryState should be saved */
attribute boolean saveLayoutStateFlag;
/** attribute to indicate whether the page is already expired in cache */
attribute boolean expirationStatus;
/**
* attribute to indicate the content-type of the document that this
* is a session history entry for
*/
attribute ACString contentType;
/**
* If we created this SHEntry via history.pushState or modified it via
* history.replaceState, and if we changed the SHEntry's URI via the
* push/replaceState call, and if the SHEntry's new URI differs from its
* old URI by more than just the hash, then we set this field to true.
*
* Additionally, if this SHEntry was created by calling pushState from a
* SHEntry whose URI was modified, this SHEntry's URIWasModified field is
* true.
*
*/
attribute boolean URIWasModified;
/** Set/Get scrollers' positon in anchored pages */
void setScrollPosition(in long x, in long y);
void getScrollPosition(out long x, out long y);
/** Additional ways to create an entry */
[noscript] void create(in nsIURI URI, in AString title,
in nsIInputStream inputStream,
in nsILayoutHistoryState layoutHistoryState,
in nsISupports cacheKey, in ACString contentType,
in nsIPrincipal triggeringPrincipal,
in nsIPrincipal principalToInherit,
in unsigned long long docshellID,
in boolean dynamicCreation);
nsISHEntry clone();
/** Attribute that indicates if this entry is for a subframe navigation */
void setIsSubFrame(in boolean aFlag);
/** Return any content viewer present in or below this node in the
nsSHEntry tree. This will differ from contentViewer in the case
where a child nsSHEntry has the content viewer for this tree. */
nsIContentViewer getAnyContentViewer(out nsISHEntry ownerEntry);
/**
* Get the principal, if any, that was associated with the channel
* that the document that was loaded to create this history entry
* came from.
*/
attribute nsIPrincipal triggeringPrincipal;
/**
* Get the principal, if any, that is used when the inherit flag
* is set.
*/
attribute nsIPrincipal principalToInherit;
/**
* Get/set data associated with this history state via a pushState() call,
* serialized using structured clone.
**/
attribute nsIStructuredCloneContainer stateData;
/**
* Gets the owning pointer to the editor data assosicated with
* this shistory entry. This forgets its pointer, so free it when
* you're done.
*/
[noscript, notxpcom] nsDocShellEditorDataPtr forgetEditorData();
/**
* Sets the owning pointer to the editor data assosicated with
* this shistory entry. Unless forgetEditorData() is called, this
* shentry will destroy the editor data when it's destroyed.
*/
[noscript, notxpcom] void setEditorData(in nsDocShellEditorDataPtr aData);
/** Returns true if this shistory entry is storing a detached editor. */
[noscript, notxpcom] boolean hasDetachedEditor();
/**
* Returns true if the related docshell was added because of
* dynamic addition of an iframe/frame.
*/
boolean isDynamicallyAdded();
/**
* Returns true if any of the child entries returns true
* when isDynamicallyAdded is called on it.
*/
boolean hasDynamicallyAddedChild();
/**
* The history ID of the docshell.
*/
attribute unsigned long long docshellID;
readonly attribute nsIBFCacheEntry BFCacheEntry;
/**
* Does this SHEntry point to the given BFCache entry? If so, evicting
* the BFCache entry will evict the SHEntry, since the two entries
* correspond to the same document.
*/
[notxpcom, noscript]
boolean hasBFCacheEntry(in nsIBFCacheEntry aEntry);
/**
* Adopt aEntry's BFCacheEntry, so now both this and aEntry point to
* aEntry's BFCacheEntry.
*/
void adoptBFCacheEntry(in nsISHEntry aEntry);
/**
* Create a new BFCache entry and drop our reference to our old one. This
* call unlinks this SHEntry from any other SHEntries for its document.
*/
void abandonBFCacheEntry();
/**
* Does this SHEntry correspond to the same document as aEntry? This is
* true iff the two SHEntries have the same BFCacheEntry. So in
* particular, sharesDocumentWith(aEntry) is guaranteed to return true if
* it's preceeded by a call to adoptBFCacheEntry(aEntry).
*/
boolean sharesDocumentWith(in nsISHEntry aEntry);
/**
* True if this SHEntry corresponds to a document created by a srcdoc iframe.
* Set when a value is assigned to srcdocData.
*/
readonly attribute boolean isSrcdocEntry;
/**
* Contents of the srcdoc attribute in a srcdoc iframe to be loaded instead
* of the URI. Similar to a Data URI, this information is needed to
* recreate the document at a later stage.
* Setting this sets isSrcdocEntry to true
*/
attribute AString srcdocData;
/**
* When isSrcdocEntry is true, this contains the baseURI of the srcdoc
* document for use in situations where it cannot otherwise be determined,
* for example with view-source.
*/
attribute nsIURI baseURI;
/**
* Sets/gets the current scroll restoration state,
* if true == "manual", false == "auto".
*/
attribute boolean scrollRestorationIsManual;
};
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]
interface nsISHEntryInternal : nsISupports
{
[notxpcom] void RemoveFromBFCacheAsync();
[notxpcom] void RemoveFromBFCacheSync();
/**
* A number that is assigned by the sHistory when the entry is activated
*/
attribute unsigned long lastTouched;
/**
* Some state, particularly that related to the back/forward cache, is
* shared between SHEntries which correspond to the same document. This
* method gets a pointer to that shared state.
*
* This shared state is the SHEntry's BFCacheEntry. So
* hasBFCacheEntry(getSharedState()) is guaranteed to return true.
*/
[noscript, notxpcom]
nsSHEntryShared getSharedState();
};
%{ C++
// {BFD1A791-AD9F-11d3-BDC7-0050040A9B44}
#define NS_SHENTRY_CID \
{0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
#define NS_SHENTRY_CONTRACTID \
"@mozilla.org/browser/session-history-entry;1"
%}

View file

@ -0,0 +1,56 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
interface nsISHEntry;
/**
* The nsISHTransaction.
*/
[scriptable, uuid(2EDF705F-D252-4971-9F09-71DD0F760DC6)]
interface nsISHTransaction : nsISupports
{
/**
* The nsISHEntry for the current transaction
*/
attribute nsISHEntry sHEntry;
/**
* The parent of this transaction
*/
attribute nsISHTransaction prev;
/**
* The legitimate child of this transaction
*/
attribute nsISHTransaction next;
/**
* Specifies if this transaction should persist. If not it will be replaced
* by new additions to the list.
*/
attribute boolean persist;
/**
* Create a transaction with parent and History Entry
*/
void create(in nsISHEntry aSHEntry, in nsISHTransaction aPrev);
};
%{ C++
// {BFD1A792-AD9F-11d3-BDC7-0050040A9B44}
#define NS_SHTRANSACTION_CID \
{0xbfd1a792, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
#define NS_SHTRANSACTION_CONTRACTID \
"@mozilla.org/browser/session-history-transaction;1"
%}

View file

@ -0,0 +1,221 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsISHEntry;
interface nsISHistoryListener;
interface nsISimpleEnumerator;
interface nsIPartialSHistoryListener;
/**
* An interface to the primary properties of the Session History
* component. In an embedded browser environment, the nsIWebBrowser
* object creates an instance of session history for each open window.
* A handle to the session history object can be obtained from
* nsIWebNavigation. In a non-embedded situation, the owner of the
* session history component must create a instance of it and set
* it in the nsIWebNavigation object.
* This interface is accessible from javascript.
*/
%{C++
#define NS_SHISTORY_CID \
{0x7b807041, 0xe60a, 0x4384, {0x93, 0x5f, 0xaf, 0x30, 0x61, 0xd8, 0xb8, 0x15}}
#define NS_SHISTORY_CONTRACTID "@mozilla.org/browser/shistory;1"
%}
[scriptable, uuid(7b807041-e60a-4384-935f-af3061d8b815)]
interface nsISHistory: nsISupports
{
/**
* An attribute denoting whether the nsISHistory is associated to a grouped
* session history.
*
* The abstraction of grouped session history is implemented at
* nsIWebNavigation level, so those canGoBack / canGoForward / gotoIndex
* functions work transparently;
*
* On the other hand, nsISHistory works on partial session history directly.
* Unless otherwise specified, count / index attributes and parameters all
* indicate local count / index, so we won't mess up docshell.
*/
readonly attribute bool isPartial;
/**
* A readonly property of the interface that returns
* the number of toplevel documents currently available
* in session history.
*/
readonly attribute long count;
/**
* If isPartial, globalCount denotes the total number of entries in the
* grouped session history; Otherwise it has the same value as count.
*/
readonly attribute long globalCount;
/**
* A readonly property which represents the difference between global indices
* of grouped session history and local indices of this particular session
* history object.
*/
readonly attribute long globalIndexOffset;
/**
* A readonly property of the interface that returns
* the index of the current document in session history.
*/
readonly attribute long index;
/**
* A readonly property of the interface that returns
* the index of the last document that started to load and
* didn't finished yet. When document finishes the loading
* value -1 is returned.
*/
readonly attribute long requestedIndex;
/**
* A read/write property of the interface, used to Get/Set
* the maximum number of toplevel documents, session history
* can hold for each instance.
*/
attribute long maxLength;
/**
* Called to obtain handle to the history entry at a
* given index.
*
* @param index The index value whose entry is requested.
* The oldest entry is located at index == 0.
* @param modifyIndex A boolean flag that indicates if the current
* index of session history should be modified
* to the parameter index.
*
* @return <code>NS_OK</code> history entry for
* the index is obtained successfully.
* <code>NS_ERROR_FAILURE</code> Error in obtaining
* history entry for the given index.
*/
nsISHEntry getEntryAtIndex(in long index, in boolean modifyIndex);
/**
* Called to purge older documents from history.
* Documents can be removed from session history for various
* reasons. For example to control memory usage of the browser, to
* prevent users from loading documents from history, to erase evidence of
* prior page loads etc...
*
* @param numEntries The number of toplevel documents to be
* purged from history. During purge operation,
* the latest documents are maintained and older
* 'numEntries' documents are removed from history.
* @throws <code>NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA</code> Purge was vetod.
* @throws <code>NS_ERROR_FAILURE</code> numEntries is
* invalid or out of bounds with the size of history.
*
*/
void PurgeHistory(in long numEntries);
/**
* Called to register a listener for the session history component.
* Listeners are notified when pages are loaded or purged from history.
*
* @param aListener Listener object to be notified for all
* page loads that initiate in session history.
*
* @note A listener object must implement
* nsISHistoryListener and nsSupportsWeakReference
*
* @see nsISHistoryListener
* @see nsSupportsWeakReference
*/
void addSHistoryListener(in nsISHistoryListener aListener);
/**
* Called to remove a listener for the session history component.
* Listeners are notified when pages are loaded from history.
*
* @param aListener Listener object to be removed from
* session history.
*
* @note A listener object must implement
* nsISHistoryListener and nsSupportsWeakReference
* @see nsISHistoryListener
* @see nsSupportsWeakReference
*/
void removeSHistoryListener(in nsISHistoryListener aListener);
/**
* Set the listener to handle cross nsISHistory navigation when it works
* in "partial" mode.
*/
void setPartialSHistoryListener(in nsIPartialSHistoryListener aListener);
/**
* Called to obtain a enumerator for all the documents stored in
* session history. The enumerator object thus returned by this method
* can be traversed using nsISimpleEnumerator.
*
* @note To access individual history entries of the enumerator, perform the
* following steps:
* 1) Call nsISHistory->GetSHistoryEnumerator() to obtain handle
* the nsISimpleEnumerator object.
* 2) Use nsISimpleEnumerator->GetNext() on the object returned
* by step #1 to obtain handle to the next object in the list.
* The object returned by this step is of type nsISupports.
* 3) Perform a QueryInterface on the object returned by step #2
* to nsISHEntry.
* 4) Use nsISHEntry to access properties of each history entry.
*
* @see nsISimpleEnumerator
* @see nsISHEntry
* @see QueryInterface()
* @see do_QueryInterface()
*/
readonly attribute nsISimpleEnumerator SHistoryEnumerator;
void reloadCurrentEntry();
/**
* Called to obtain the index to a given history entry.
*
* @param aEntry The entry to obtain the index of.
*
* @return <code>NS_OK</code> index for the history entry
* is obtained successfully.
* <code>NS_ERROR_FAILURE</code> Error in obtaining
* index for the given history entry.
*/
long getIndexOfEntry(in nsISHEntry aEntry);
/**
* Called when this nsISHistory has became the active history of a grouped
* session history.
*
* @param globalLength The up to date number of entries in the grouped
* session history.
* @param targetIndex The local index to navigate to.
*/
void onPartialSessionHistoryActive(in long globalLength, in long targetIndex);
/**
* Called when this nsISHistory has became inactive history of a grouped
* session history.
*/
void onPartialSessionHistoryDeactive();
/**
* Called when it's attached to a nsIGroupedSHistory instance.
*
* @param offset The number of entries in the grouped session
* history before this session history object.
*/
void onAttachGroupedSessionHistory(in long offset);
};

View file

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIBFCacheEntry;
interface nsISHEntry;
interface nsISHistoryListener;
interface nsISHTransaction;
interface nsIDocShell;
interface nsIURI;
%{C++
#define NS_SHISTORY_INTERNAL_CID \
{ 0x3dfb2f54, 0x378d, 0x4d3c, \
{ 0xa9, 0xf9, 0x95, 0xdd, 0x26, 0x73, 0x24, 0x8c } }
#define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1"
#include "nsTArrayForwardDeclare.h"
%}
[ref] native nsDocshellIDArray(nsTArray<uint64_t>);
[scriptable, uuid(3dfb2f54-378d-4d3c-a9f9-95dd2673248c)]
interface nsISHistoryInternal: nsISupports
{
/**
* Add a new Entry to the History List
* @param aEntry - The entry to add
* @param aPersist - If true this specifies that the entry should persist
* in the list. If false, this means that when new entries are added
* this element will not appear in the session history list.
*/
void addEntry(in nsISHEntry aEntry, in boolean aPersist);
/**
* Get the root transaction
*/
readonly attribute nsISHTransaction rootTransaction;
/**
* Sets the toplevel docshell object to which this SHistory object belongs to.
*/
void setRootDocShell(in nsIDocShell rootDocShell);
/**
* Update the index maintained by sessionHistory
*/
void updateIndex();
/**
* Replace the nsISHEntry at a particular index
* @param aIndex - The index at which the entry should be replaced
* @param aReplaceEntry - The replacement entry for the index.
*/
void replaceEntry(in long aIndex, in nsISHEntry aReplaceEntry);
/**
* Notifies all registered session history listeners about an impending
* reload.
*
* @param aReloadURI The URI of the document to be reloaded.
* @param aReloadFlags Flags that indicate how the document is to be
* refreshed. See constants on the nsIWebNavigation
* interface.
* @return Whether the operation can proceed.
*/
boolean notifyOnHistoryReload(in nsIURI aReloadURI, in unsigned long aReloadFlags);
/**
* Evict content viewers which don't lie in the "safe" range around aIndex.
* In practice, this should leave us with no more than gHistoryMaxViewers
* viewers associated with this SHistory object.
*
* Also make sure that the total number of content viewers in all windows is
* not greater than our global max; if it is, evict viewers as appropriate.
*
* @param aIndex - The index around which the "safe" range is centered. In
* general, if you just navigated the history, aIndex should be the index
* history was navigated to.
*/
void evictOutOfRangeContentViewers(in long aIndex);
/**
* Evict the content viewer associated with a bfcache entry
* that has timed out.
*/
void evictExpiredContentViewerForEntry(in nsIBFCacheEntry aEntry);
/**
* Evict all the content viewers in this session history
*/
void evictAllContentViewers();
/**
* Removes entries from the history if their docshellID is in
* aIDs array.
*/
[noscript, notxpcom] void RemoveEntries(in nsDocshellIDArray aIDs,
in long aStartIndex);
};

View file

@ -0,0 +1,108 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
interface nsIURI;
/**
* nsISHistoryListener defines the interface one can implement to receive
* notifications about activities in session history and to be able to
* cancel them.
*
* A session history listener will be notified when pages are added, removed
* and loaded from session history. It can prevent any action (except adding
* a new session history entry) from happening by returning false from the
* corresponding callback method.
*
* A session history listener can be registered on a particular nsISHistory
* instance via the nsISHistory::addSHistoryListener() method.
*/
[scriptable, uuid(125c0833-746a-400e-9b89-d2d18545c08a)]
interface nsISHistoryListener : nsISupports
{
/**
* Called when a new document is added to session history. New documents are
* added to session history by docshell when new pages are loaded in a frame
* or content area, for example via nsIWebNavigation::loadURI()
*
* @param aNewURI The URI of the document to be added to session history.
* @param aOldIndex The index of the current history item before the operation.
*/
void OnHistoryNewEntry(in nsIURI aNewURI, in long aOldIndex);
/**
* Called when navigating to a previous session history entry, for example
* due to a nsIWebNavigation::goBack() call.
*
* @param aBackURI The URI of the session history entry being navigated to.
* @return Whether the operation can proceed.
*/
boolean OnHistoryGoBack(in nsIURI aBackURI);
/**
* Called when navigating to a next session history entry, for example
* due to a nsIWebNavigation::goForward() call.
*
* @param aForwardURI The URI of the session history entry being navigated to.
* @return Whether the operation can proceed.
*/
boolean OnHistoryGoForward(in nsIURI aForwardURI);
/**
* Called when the current document is reloaded, for example due to a
* nsIWebNavigation::reload() call.
*
* @param aReloadURI The URI of the document to be reloaded.
* @param aReloadFlags Flags that indicate how the document is to be
* refreshed. See constants on the nsIWebNavigation
* interface.
* @return Whether the operation can proceed.
*
* @see nsIWebNavigation
*/
boolean OnHistoryReload(in nsIURI aReloadURI, in unsigned long aReloadFlags);
/**
* Called when navigating to a session history entry by index, for example,
* when nsIWebNavigation::gotoIndex() is called.
*
* @param aIndex The index in session history of the entry to be loaded.
* @param aGotoURI The URI of the session history entry to be loaded.
* @return Whether the operation can proceed.
*/
boolean OnHistoryGotoIndex(in long aIndex, in nsIURI aGotoURI);
/**
* Called when entries are removed from session history. Entries can be
* removed from session history for various reasons, for example to control
* the memory usage of the browser, to prevent users from loading documents
* from history, to erase evidence of prior page loads, etc.
*
* To purge documents from session history call nsISHistory::PurgeHistory()
*
* @param aNumEntries The number of entries to be removed from session history.
* @return Whether the operation can proceed.
*/
boolean OnHistoryPurge(in long aNumEntries);
/**
* Called when an entry is replaced in the session history. Entries are
* replaced when navigating away from non-persistent history entries (such as
* about pages) and when history.replaceState is called.
*
* @param aIndex The index in session history of the entry being
* replaced
*/
void OnHistoryReplaceEntry(in long aIndex);
/**
* Called when nsISHistory::count has been updated. Unlike OnHistoryNewEntry
* and OnHistoryPurge which happen before the modifications are actually done
* and maybe cancellable, this function is called after these modifications.
*/
void OnLengthChange(in long aCount);
};

View file

@ -0,0 +1,944 @@
/* -*- 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 "nsSHEntry.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIDocShellTreeItem.h"
#include "nsDocShellEditorData.h"
#include "nsSHEntryShared.h"
#include "nsILayoutHistoryState.h"
#include "nsIContentViewer.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIInputStream.h"
#include "nsIURI.h"
#include "mozilla/net/ReferrerPolicy.h"
#include <algorithm>
namespace dom = mozilla::dom;
static uint32_t gEntryID = 0;
nsSHEntry::nsSHEntry()
: mShared(new nsSHEntryShared())
, mLoadReplace(false)
, mReferrerPolicy(mozilla::net::RP_Default)
, mLoadType(0)
, mID(gEntryID++)
, mScrollPositionX(0)
, mScrollPositionY(0)
, mParent(nullptr)
, mURIWasModified(false)
, mIsSrcdocEntry(false)
, mScrollRestorationIsManual(false)
{
}
nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
: mShared(aOther.mShared)
, mURI(aOther.mURI)
, mOriginalURI(aOther.mOriginalURI)
, mLoadReplace(aOther.mLoadReplace)
, mReferrerURI(aOther.mReferrerURI)
, mReferrerPolicy(aOther.mReferrerPolicy)
, mTitle(aOther.mTitle)
, mPostData(aOther.mPostData)
, mLoadType(0) // XXX why not copy?
, mID(aOther.mID)
, mScrollPositionX(0) // XXX why not copy?
, mScrollPositionY(0) // XXX why not copy?
, mParent(aOther.mParent)
, mURIWasModified(aOther.mURIWasModified)
, mStateData(aOther.mStateData)
, mIsSrcdocEntry(aOther.mIsSrcdocEntry)
, mScrollRestorationIsManual(false)
, mSrcdocData(aOther.mSrcdocData)
, mBaseURI(aOther.mBaseURI)
{
}
static bool
ClearParentPtr(nsISHEntry* aEntry, void* /* aData */)
{
if (aEntry) {
aEntry->SetParent(nullptr);
}
return true;
}
nsSHEntry::~nsSHEntry()
{
// Null out the mParent pointers on all our kids.
mChildren.EnumerateForwards(ClearParentPtr, nullptr);
}
NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
NS_IMETHODIMP
nsSHEntry::SetScrollPosition(int32_t aX, int32_t aY)
{
mScrollPositionX = aX;
mScrollPositionY = aY;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetScrollPosition(int32_t* aX, int32_t* aY)
{
*aX = mScrollPositionX;
*aY = mScrollPositionY;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetURIWasModified(bool* aOut)
{
*aOut = mURIWasModified;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetURIWasModified(bool aIn)
{
mURIWasModified = aIn;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetURI(nsIURI** aURI)
{
*aURI = mURI;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetURI(nsIURI* aURI)
{
mURI = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI)
{
*aOriginalURI = mOriginalURI;
NS_IF_ADDREF(*aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
{
mOriginalURI = aOriginalURI;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLoadReplace(bool* aLoadReplace)
{
*aLoadReplace = mLoadReplace;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLoadReplace(bool aLoadReplace)
{
mLoadReplace = aLoadReplace;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetReferrerURI(nsIURI** aReferrerURI)
{
*aReferrerURI = mReferrerURI;
NS_IF_ADDREF(*aReferrerURI);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetReferrerURI(nsIURI* aReferrerURI)
{
mReferrerURI = aReferrerURI;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetReferrerPolicy(uint32_t* aReferrerPolicy)
{
*aReferrerPolicy = mReferrerPolicy;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetReferrerPolicy(uint32_t aReferrerPolicy)
{
mReferrerPolicy = aReferrerPolicy;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetContentViewer(nsIContentViewer* aViewer)
{
return mShared->SetContentViewer(aViewer);
}
NS_IMETHODIMP
nsSHEntry::GetContentViewer(nsIContentViewer** aResult)
{
*aResult = mShared->mContentViewer;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetAnyContentViewer(nsISHEntry** aOwnerEntry,
nsIContentViewer** aResult)
{
// Find a content viewer in the root node or any of its children,
// assuming that there is only one content viewer total in any one
// nsSHEntry tree
GetContentViewer(aResult);
if (*aResult) {
#ifdef DEBUG_PAGE_CACHE
printf("Found content viewer\n");
#endif
*aOwnerEntry = this;
NS_ADDREF(*aOwnerEntry);
return NS_OK;
}
// The root SHEntry doesn't have a ContentViewer, so check child nodes
for (int32_t i = 0; i < mChildren.Count(); i++) {
nsISHEntry* child = mChildren[i];
if (child) {
#ifdef DEBUG_PAGE_CACHE
printf("Evaluating SHEntry child %d\n", i);
#endif
child->GetAnyContentViewer(aOwnerEntry, aResult);
if (*aResult) {
return NS_OK;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSticky(bool aSticky)
{
mShared->mSticky = aSticky;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSticky(bool* aSticky)
{
*aSticky = mShared->mSticky;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetTitle(char16_t** aTitle)
{
// Check for empty title...
if (mTitle.IsEmpty() && mURI) {
// Default title is the URL.
nsAutoCString spec;
if (NS_SUCCEEDED(mURI->GetSpec(spec))) {
AppendUTF8toUTF16(spec, mTitle);
}
}
*aTitle = ToNewUnicode(mTitle);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetTitle(const nsAString& aTitle)
{
mTitle = aTitle;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetPostData(nsIInputStream** aResult)
{
*aResult = mPostData;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetPostData(nsIInputStream* aPostData)
{
mPostData = aPostData;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult)
{
*aResult = mShared->mLayoutHistoryState;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState)
{
mShared->mLayoutHistoryState = aState;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(
!mShared->mSaveLayoutState);
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLoadType(uint32_t* aResult)
{
*aResult = mLoadType;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLoadType(uint32_t aLoadType)
{
mLoadType = aLoadType;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetID(uint32_t* aResult)
{
*aResult = mID;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetID(uint32_t aID)
{
mID = aID;
return NS_OK;
}
nsSHEntryShared*
nsSHEntry::GetSharedState()
{
return mShared;
}
NS_IMETHODIMP
nsSHEntry::GetIsSubFrame(bool* aFlag)
{
*aFlag = mShared->mIsFrameNavigation;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetIsSubFrame(bool aFlag)
{
mShared->mIsFrameNavigation = aFlag;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetCacheKey(nsISupports** aResult)
{
*aResult = mShared->mCacheKey;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetCacheKey(nsISupports* aCacheKey)
{
mShared->mCacheKey = aCacheKey;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag)
{
*aFlag = mShared->mSaveLayoutState;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSaveLayoutStateFlag(bool aFlag)
{
mShared->mSaveLayoutState = aFlag;
if (mShared->mLayoutHistoryState) {
mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetExpirationStatus(bool* aFlag)
{
*aFlag = mShared->mExpired;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetExpirationStatus(bool aFlag)
{
mShared->mExpired = aFlag;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetContentType(nsACString& aContentType)
{
aContentType = mShared->mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetContentType(const nsACString& aContentType)
{
mShared->mContentType = aContentType;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
nsIInputStream* aInputStream,
nsILayoutHistoryState* aLayoutHistoryState,
nsISupports* aCacheKey, const nsACString& aContentType,
nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aPrincipalToInherit,
uint64_t aDocShellID,
bool aDynamicCreation)
{
mURI = aURI;
mTitle = aTitle;
mPostData = aInputStream;
// Set the LoadType by default to loadHistory during creation
mLoadType = (uint32_t)nsIDocShellLoadInfo::loadHistory;
mShared->mCacheKey = aCacheKey;
mShared->mContentType = aContentType;
mShared->mTriggeringPrincipal = aTriggeringPrincipal;
mShared->mPrincipalToInherit = aPrincipalToInherit;
mShared->mDocShellID = aDocShellID;
mShared->mDynamicallyCreated = aDynamicCreation;
// By default all entries are set false for subframe flag.
// nsDocShell::CloneAndReplace() which creates entries for
// all subframe navigations, sets the flag to true.
mShared->mIsFrameNavigation = false;
// By default we save LayoutHistoryState
mShared->mSaveLayoutState = true;
mShared->mLayoutHistoryState = aLayoutHistoryState;
// By default the page is not expired
mShared->mExpired = false;
mIsSrcdocEntry = false;
mSrcdocData = NullString();
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::Clone(nsISHEntry** aResult)
{
*aResult = new nsSHEntry(*this);
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetParent(nsISHEntry** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mParent;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetParent(nsISHEntry* aParent)
{
/* parent not Addrefed on purpose to avoid cyclic reference
* Null parent is OK
*
* XXX this method should not be scriptable if this is the case!!
*/
mParent = aParent;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetWindowState(nsISupports* aState)
{
mShared->mWindowState = aState;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetWindowState(nsISupports** aState)
{
NS_IF_ADDREF(*aState = mShared->mWindowState);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetViewerBounds(const nsIntRect& aBounds)
{
mShared->mViewerBounds = aBounds;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetViewerBounds(nsIntRect& aBounds)
{
aBounds = mShared->mViewerBounds;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetTriggeringPrincipal(nsIPrincipal** aTriggeringPrincipal)
{
NS_IF_ADDREF(*aTriggeringPrincipal = mShared->mTriggeringPrincipal);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
{
mShared->mTriggeringPrincipal = aTriggeringPrincipal;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit)
{
NS_IF_ADDREF(*aPrincipalToInherit = mShared->mPrincipalToInherit);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit)
{
mShared->mPrincipalToInherit = aPrincipalToInherit;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry** aEntry)
{
NS_ENSURE_ARG_POINTER(aEntry);
NS_IF_ADDREF(*aEntry = mShared);
return NS_OK;
}
bool
nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry)
{
return static_cast<nsIBFCacheEntry*>(mShared) == aEntry;
}
NS_IMETHODIMP
nsSHEntry::AdoptBFCacheEntry(nsISHEntry* aEntry)
{
nsCOMPtr<nsISHEntryInternal> shEntry = do_QueryInterface(aEntry);
NS_ENSURE_STATE(shEntry);
nsSHEntryShared* shared = shEntry->GetSharedState();
NS_ENSURE_STATE(shared);
mShared = shared;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SharesDocumentWith(nsISHEntry* aEntry, bool* aOut)
{
NS_ENSURE_ARG_POINTER(aOut);
nsCOMPtr<nsISHEntryInternal> internal = do_QueryInterface(aEntry);
NS_ENSURE_STATE(internal);
*aOut = mShared == internal->GetSharedState();
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::AbandonBFCacheEntry()
{
mShared = nsSHEntryShared::Duplicate(mShared);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry)
{
*aIsSrcdocEntry = mIsSrcdocEntry;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSrcdocData(nsAString& aSrcdocData)
{
aSrcdocData = mSrcdocData;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSrcdocData(const nsAString& aSrcdocData)
{
mSrcdocData = aSrcdocData;
mIsSrcdocEntry = true;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetBaseURI(nsIURI** aBaseURI)
{
*aBaseURI = mBaseURI;
NS_IF_ADDREF(*aBaseURI);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetBaseURI(nsIURI* aBaseURI)
{
mBaseURI = aBaseURI;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetScrollRestorationIsManual(bool* aIsManual)
{
*aIsManual = mScrollRestorationIsManual;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetScrollRestorationIsManual(bool aIsManual)
{
mScrollRestorationIsManual = aIsManual;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetChildCount(int32_t* aCount)
{
*aCount = mChildren.Count();
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::AddChild(nsISHEntry* aChild, int32_t aOffset)
{
if (aChild) {
NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE);
}
if (aOffset < 0) {
mChildren.AppendObject(aChild);
return NS_OK;
}
//
// Bug 52670: Ensure children are added in order.
//
// Later frames in the child list may load faster and get appended
// before earlier frames, causing session history to be scrambled.
// By growing the list here, they are added to the right position.
//
// Assert that aOffset will not be so high as to grow us a lot.
//
NS_ASSERTION(aOffset < (mChildren.Count() + 1023), "Large frames array!\n");
bool newChildIsDyn = false;
if (aChild) {
aChild->IsDynamicallyAdded(&newChildIsDyn);
}
// If the new child is dynamically added, try to add it to aOffset, but if
// there are non-dynamically added children, the child must be after those.
if (newChildIsDyn) {
int32_t lastNonDyn = aOffset - 1;
for (int32_t i = aOffset; i < mChildren.Count(); ++i) {
nsISHEntry* entry = mChildren[i];
if (entry) {
bool dyn = false;
entry->IsDynamicallyAdded(&dyn);
if (dyn) {
break;
} else {
lastNonDyn = i;
}
}
}
// InsertObjectAt allows only appending one object.
// If aOffset is larger than Count(), we must first manually
// set the capacity.
if (aOffset > mChildren.Count()) {
mChildren.SetCount(aOffset);
}
if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) {
NS_WARNING("Adding a child failed!");
aChild->SetParent(nullptr);
return NS_ERROR_FAILURE;
}
} else {
// If the new child isn't dynamically added, it should be set to aOffset.
// If there are dynamically added children before that, those must be
// moved to be after aOffset.
if (mChildren.Count() > 0) {
int32_t start = std::min(mChildren.Count() - 1, aOffset);
int32_t dynEntryIndex = -1;
nsISHEntry* dynEntry = nullptr;
for (int32_t i = start; i >= 0; --i) {
nsISHEntry* entry = mChildren[i];
if (entry) {
bool dyn = false;
entry->IsDynamicallyAdded(&dyn);
if (dyn) {
dynEntryIndex = i;
dynEntry = entry;
} else {
break;
}
}
}
if (dynEntry) {
nsCOMArray<nsISHEntry> tmp;
tmp.SetCount(aOffset - dynEntryIndex + 1);
mChildren.InsertObjectsAt(tmp, dynEntryIndex);
NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
}
}
// Make sure there isn't anything at aOffset.
if (aOffset < mChildren.Count()) {
nsISHEntry* oldChild = mChildren[aOffset];
if (oldChild && oldChild != aChild) {
NS_ERROR("Adding a child where we already have a child? This may misbehave");
oldChild->SetParent(nullptr);
}
}
mChildren.ReplaceObjectAt(aChild, aOffset);
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::RemoveChild(nsISHEntry* aChild)
{
NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
bool childRemoved = false;
bool dynamic = false;
aChild->IsDynamicallyAdded(&dynamic);
if (dynamic) {
childRemoved = mChildren.RemoveObject(aChild);
} else {
int32_t index = mChildren.IndexOfObject(aChild);
if (index >= 0) {
mChildren.ReplaceObjectAt(nullptr, index);
childRemoved = true;
}
}
if (childRemoved) {
aChild->SetParent(nullptr);
// reduce the child count, i.e. remove empty children at the end
for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) {
if (!mChildren.RemoveObjectAt(i)) {
break;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry** aResult)
{
if (aIndex >= 0 && aIndex < mChildren.Count()) {
*aResult = mChildren[aIndex];
// yes, mChildren can have holes in it. AddChild's offset parameter makes
// that possible.
NS_IF_ADDREF(*aResult);
} else {
*aResult = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::ReplaceChild(nsISHEntry* aNewEntry)
{
NS_ENSURE_STATE(aNewEntry);
uint64_t docshellID;
aNewEntry->GetDocshellID(&docshellID);
uint64_t otherID;
for (int32_t i = 0; i < mChildren.Count(); ++i) {
if (mChildren[i] && NS_SUCCEEDED(mChildren[i]->GetDocshellID(&otherID)) &&
docshellID == otherID) {
mChildren[i]->SetParent(nullptr);
mChildren.ReplaceObjectAt(aNewEntry, i);
return aNewEntry->SetParent(this);
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell)
{
NS_ASSERTION(aShell, "Null child shell added to history entry");
mShared->mChildShells.AppendObject(aShell);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell)
{
NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex));
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::ClearChildShells()
{
mShared->mChildShells.Clear();
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetRefreshURIList(nsIMutableArray** aList)
{
NS_IF_ADDREF(*aList = mShared->mRefreshURIList);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetRefreshURIList(nsIMutableArray* aList)
{
mShared->mRefreshURIList = aList;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SyncPresentationState()
{
return mShared->SyncPresentationState();
}
void
nsSHEntry::RemoveFromBFCacheSync()
{
mShared->RemoveFromBFCacheSync();
}
void
nsSHEntry::RemoveFromBFCacheAsync()
{
mShared->RemoveFromBFCacheAsync();
}
nsDocShellEditorData*
nsSHEntry::ForgetEditorData()
{
// XXX jlebar Check how this is used.
return mShared->mEditorData.forget();
}
void
nsSHEntry::SetEditorData(nsDocShellEditorData* aData)
{
NS_ASSERTION(!(aData && mShared->mEditorData),
"We're going to overwrite an owning ref!");
if (mShared->mEditorData != aData) {
mShared->mEditorData = aData;
}
}
bool
nsSHEntry::HasDetachedEditor()
{
return mShared->mEditorData != nullptr;
}
NS_IMETHODIMP
nsSHEntry::GetStateData(nsIStructuredCloneContainer** aContainer)
{
NS_ENSURE_ARG_POINTER(aContainer);
NS_IF_ADDREF(*aContainer = mStateData);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetStateData(nsIStructuredCloneContainer* aContainer)
{
mStateData = aContainer;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::IsDynamicallyAdded(bool* aAdded)
{
*aAdded = mShared->mDynamicallyCreated;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::HasDynamicallyAddedChild(bool* aAdded)
{
*aAdded = false;
for (int32_t i = 0; i < mChildren.Count(); ++i) {
nsISHEntry* entry = mChildren[i];
if (entry) {
entry->IsDynamicallyAdded(aAdded);
if (*aAdded) {
break;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetDocshellID(uint64_t* aID)
{
*aID = mShared->mDocShellID;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetDocshellID(uint64_t aID)
{
mShared->mDocShellID = aID;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLastTouched(uint32_t* aLastTouched)
{
*aLastTouched = mShared->mLastTouched;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLastTouched(uint32_t aLastTouched)
{
mShared->mLastTouched = aLastTouched;
return NS_OK;
}

View file

@ -0,0 +1,71 @@
/* -*- 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/. */
#ifndef nsSHEntry_h
#define nsSHEntry_h
// Helper Classes
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
// Interfaces needed
#include "nsISHEntry.h"
#include "nsISHContainer.h"
class nsSHEntryShared;
class nsIInputStream;
class nsIURI;
class nsSHEntry final : public nsISHEntry,
public nsISHContainer,
public nsISHEntryInternal
{
public:
nsSHEntry();
nsSHEntry(const nsSHEntry& aOther);
NS_DECL_ISUPPORTS
NS_DECL_NSISHENTRY
NS_DECL_NSISHENTRYINTERNAL
NS_DECL_NSISHCONTAINER
void DropPresentationState();
static nsresult Startup();
static void Shutdown();
private:
~nsSHEntry();
// We share the state in here with other SHEntries which correspond to the
// same document.
RefPtr<nsSHEntryShared> mShared;
// See nsSHEntry.idl for comments on these members.
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
bool mLoadReplace;
nsCOMPtr<nsIURI> mReferrerURI;
uint32_t mReferrerPolicy;
nsString mTitle;
nsCOMPtr<nsIInputStream> mPostData;
uint32_t mLoadType;
uint32_t mID;
int32_t mScrollPositionX;
int32_t mScrollPositionY;
nsISHEntry* mParent;
nsCOMArray<nsISHEntry> mChildren;
bool mURIWasModified;
nsCOMPtr<nsIStructuredCloneContainer> mStateData;
bool mIsSrcdocEntry;
bool mScrollRestorationIsManual;
nsString mSrcdocData;
nsCOMPtr<nsIURI> mBaseURI;
};
#endif /* nsSHEntry_h */

View file

@ -0,0 +1,385 @@
/* -*- 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 "nsSHEntryShared.h"
#include "nsIDOMDocument.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
#include "nsIDocument.h"
#include "nsIWebNavigation.h"
#include "nsIContentViewer.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsDocShellEditorData.h"
#include "nsThreadUtils.h"
#include "nsILayoutHistoryState.h"
#include "mozilla/Attributes.h"
#include "mozilla/Preferences.h"
#include "nsArray.h"
namespace dom = mozilla::dom;
namespace {
uint64_t gSHEntrySharedID = 0;
} // namespace
#define CONTENT_VIEWER_TIMEOUT_SECONDS "browser.sessionhistory.contentViewerTimeout"
// Default this to time out unused content viewers after 30 minutes
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30 * 60)
typedef nsExpirationTracker<nsSHEntryShared, 3> HistoryTrackerBase;
class HistoryTracker final : public HistoryTrackerBase
{
public:
explicit HistoryTracker(uint32_t aTimeout)
: HistoryTrackerBase(1000 * aTimeout / 2, "HistoryTracker")
{
}
protected:
virtual void NotifyExpired(nsSHEntryShared* aObj)
{
RemoveObject(aObj);
aObj->Expire();
}
};
static HistoryTracker* gHistoryTracker = nullptr;
void
nsSHEntryShared::EnsureHistoryTracker()
{
if (!gHistoryTracker) {
// nsExpirationTracker doesn't allow one to change the timer period,
// so just set it once when the history tracker is used for the first time.
gHistoryTracker = new HistoryTracker(
mozilla::Preferences::GetUint(CONTENT_VIEWER_TIMEOUT_SECONDS,
CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT));
}
}
void
nsSHEntryShared::Shutdown()
{
delete gHistoryTracker;
gHistoryTracker = nullptr;
}
nsSHEntryShared::nsSHEntryShared()
: mDocShellID(0)
, mIsFrameNavigation(false)
, mSaveLayoutState(true)
, mSticky(true)
, mDynamicallyCreated(false)
, mLastTouched(0)
, mID(gSHEntrySharedID++)
, mExpired(false)
, mViewerBounds(0, 0, 0, 0)
{
}
nsSHEntryShared::~nsSHEntryShared()
{
RemoveFromExpirationTracker();
#ifdef DEBUG
if (gHistoryTracker) {
// Check that we're not still on track to expire. We shouldn't be, because
// we just removed ourselves!
nsExpirationTracker<nsSHEntryShared, 3>::Iterator iterator(gHistoryTracker);
nsSHEntryShared* elem;
while ((elem = iterator.Next()) != nullptr) {
NS_ASSERTION(elem != this, "Found dead entry still in the tracker!");
}
}
#endif
if (mContentViewer) {
RemoveFromBFCacheSync();
}
}
NS_IMPL_ISUPPORTS(nsSHEntryShared, nsIBFCacheEntry, nsIMutationObserver)
already_AddRefed<nsSHEntryShared>
nsSHEntryShared::Duplicate(nsSHEntryShared* aEntry)
{
RefPtr<nsSHEntryShared> newEntry = new nsSHEntryShared();
newEntry->mDocShellID = aEntry->mDocShellID;
newEntry->mChildShells.AppendObjects(aEntry->mChildShells);
newEntry->mTriggeringPrincipal = aEntry->mTriggeringPrincipal;
newEntry->mPrincipalToInherit = aEntry->mPrincipalToInherit;
newEntry->mContentType.Assign(aEntry->mContentType);
newEntry->mIsFrameNavigation = aEntry->mIsFrameNavigation;
newEntry->mSaveLayoutState = aEntry->mSaveLayoutState;
newEntry->mSticky = aEntry->mSticky;
newEntry->mDynamicallyCreated = aEntry->mDynamicallyCreated;
newEntry->mCacheKey = aEntry->mCacheKey;
newEntry->mLastTouched = aEntry->mLastTouched;
return newEntry.forget();
}
void
nsSHEntryShared::RemoveFromExpirationTracker()
{
if (gHistoryTracker && GetExpirationState()->IsTracked()) {
gHistoryTracker->RemoveObject(this);
}
}
nsresult
nsSHEntryShared::SyncPresentationState()
{
if (mContentViewer && mWindowState) {
// If we have a content viewer and a window state, we should be ok.
return NS_OK;
}
DropPresentationState();
return NS_OK;
}
void
nsSHEntryShared::DropPresentationState()
{
RefPtr<nsSHEntryShared> kungFuDeathGrip = this;
if (mDocument) {
mDocument->SetBFCacheEntry(nullptr);
mDocument->RemoveMutationObserver(this);
mDocument = nullptr;
}
if (mContentViewer) {
mContentViewer->ClearHistoryEntry();
}
RemoveFromExpirationTracker();
mContentViewer = nullptr;
mSticky = true;
mWindowState = nullptr;
mViewerBounds.SetRect(0, 0, 0, 0);
mChildShells.Clear();
mRefreshURIList = nullptr;
mEditorData = nullptr;
}
void
nsSHEntryShared::Expire()
{
// This entry has timed out. If we still have a content viewer, we need to
// evict it.
if (!mContentViewer) {
return;
}
nsCOMPtr<nsIDocShell> container;
mContentViewer->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
if (!treeItem) {
return;
}
// We need to find the root DocShell since only that object has an
// SHistory and we need the SHistory to evict content viewers
nsCOMPtr<nsIDocShellTreeItem> root;
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
nsCOMPtr<nsISHistory> history;
webNav->GetSessionHistory(getter_AddRefs(history));
nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
if (!historyInt) {
return;
}
historyInt->EvictExpiredContentViewerForEntry(this);
}
nsresult
nsSHEntryShared::SetContentViewer(nsIContentViewer* aViewer)
{
NS_PRECONDITION(!aViewer || !mContentViewer,
"SHEntryShared already contains viewer");
if (mContentViewer || !aViewer) {
DropPresentationState();
}
mContentViewer = aViewer;
if (mContentViewer) {
EnsureHistoryTracker();
gHistoryTracker->AddObject(this);
nsCOMPtr<nsIDOMDocument> domDoc;
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
// Store observed document in strong pointer in case it is removed from
// the contentviewer
mDocument = do_QueryInterface(domDoc);
if (mDocument) {
mDocument->SetBFCacheEntry(this);
mDocument->AddMutationObserver(this);
}
}
return NS_OK;
}
nsresult
nsSHEntryShared::RemoveFromBFCacheSync()
{
NS_ASSERTION(mContentViewer && mDocument, "we're not in the bfcache!");
nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
DropPresentationState();
// Warning! The call to DropPresentationState could have dropped the last
// reference to this object, so don't access members beyond here.
if (viewer) {
viewer->Destroy();
}
return NS_OK;
}
class DestroyViewerEvent : public mozilla::Runnable
{
public:
DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument)
: mViewer(aViewer)
, mDocument(aDocument)
{
}
NS_IMETHOD Run() override
{
if (mViewer) {
mViewer->Destroy();
}
return NS_OK;
}
nsCOMPtr<nsIContentViewer> mViewer;
nsCOMPtr<nsIDocument> mDocument;
};
nsresult
nsSHEntryShared::RemoveFromBFCacheAsync()
{
NS_ASSERTION(mContentViewer && mDocument, "we're not in the bfcache!");
// Release the reference to the contentviewer asynchronously so that the
// document doesn't get nuked mid-mutation.
nsCOMPtr<nsIRunnable> evt = new DestroyViewerEvent(mContentViewer, mDocument);
nsresult rv = NS_DispatchToCurrentThread(evt);
if (NS_FAILED(rv)) {
NS_WARNING("failed to dispatch DestroyViewerEvent");
} else {
// Drop presentation. Only do this if we succeeded in posting the event
// since otherwise the document could be torn down mid-mutation, causing
// crashes.
DropPresentationState();
}
// Careful! The call to DropPresentationState could have dropped the last
// reference to this nsSHEntryShared, so don't access members beyond here.
return NS_OK;
}
nsresult
nsSHEntryShared::GetID(uint64_t* aID)
{
*aID = mID;
return NS_OK;
}
void
nsSHEntryShared::NodeWillBeDestroyed(const nsINode* aNode)
{
NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
}
void
nsSHEntryShared::CharacterDataWillChange(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
}
void
nsSHEntryShared::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
RemoveFromBFCacheAsync();
}
void
nsSHEntryShared::AttributeWillChange(nsIDocument* aDocument,
dom::Element* aContent,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aNewValue)
{
}
void
nsSHEntryShared::NativeAnonymousChildListChange(nsIDocument* aDocument,
nsIContent* aContent,
bool aIsRemove)
{
}
void
nsSHEntryShared::AttributeChanged(nsIDocument* aDocument,
dom::Element* aElement,
int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aOldValue)
{
RemoveFromBFCacheAsync();
}
void
nsSHEntryShared::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aFirstNewContent,
int32_t /* unused */)
{
RemoveFromBFCacheAsync();
}
void
nsSHEntryShared::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
int32_t /* unused */)
{
RemoveFromBFCacheAsync();
}
void
nsSHEntryShared::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
int32_t aIndexInContainer,
nsIContent* aPreviousSibling)
{
RemoveFromBFCacheAsync();
}
void
nsSHEntryShared::ParentChainChanged(nsIContent* aContent)
{
}

View file

@ -0,0 +1,97 @@
/* -*- 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/. */
#ifndef nsSHEntryShared_h__
#define nsSHEntryShared_h__
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsIBFCacheEntry.h"
#include "nsIMutationObserver.h"
#include "nsExpirationTracker.h"
#include "nsRect.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
class nsSHEntry;
class nsISHEntry;
class nsIDocument;
class nsIContentViewer;
class nsIDocShellTreeItem;
class nsILayoutHistoryState;
class nsDocShellEditorData;
class nsIMutableArray;
// A document may have multiple SHEntries, either due to hash navigations or
// calls to history.pushState. SHEntries corresponding to the same document
// share many members; in particular, they share state related to the
// back/forward cache.
//
// nsSHEntryShared is the vehicle for this sharing.
class nsSHEntryShared final
: public nsIBFCacheEntry
, public nsIMutationObserver
{
public:
static void EnsureHistoryTracker();
static void Shutdown();
nsSHEntryShared();
NS_DECL_ISUPPORTS
NS_DECL_NSIMUTATIONOBSERVER
NS_DECL_NSIBFCACHEENTRY
nsExpirationState *GetExpirationState() { return &mExpirationState; }
private:
~nsSHEntryShared();
friend class nsSHEntry;
friend class HistoryTracker;
static already_AddRefed<nsSHEntryShared> Duplicate(nsSHEntryShared* aEntry);
void RemoveFromExpirationTracker();
void Expire();
nsresult SyncPresentationState();
void DropPresentationState();
nsresult SetContentViewer(nsIContentViewer* aViewer);
// See nsISHEntry.idl for an explanation of these members.
// These members are copied by nsSHEntryShared::Duplicate(). If you add a
// member here, be sure to update the Duplicate() implementation.
uint64_t mDocShellID;
nsCOMArray<nsIDocShellTreeItem> mChildShells;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsCString mContentType;
bool mIsFrameNavigation;
bool mSaveLayoutState;
bool mSticky;
bool mDynamicallyCreated;
nsCOMPtr<nsISupports> mCacheKey;
uint32_t mLastTouched;
// These members aren't copied by nsSHEntryShared::Duplicate() because
// they're specific to a particular content viewer.
uint64_t mID;
nsCOMPtr<nsIContentViewer> mContentViewer;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
bool mExpired;
nsCOMPtr<nsISupports> mWindowState;
nsIntRect mViewerBounds;
nsCOMPtr<nsIMutableArray> mRefreshURIList;
nsExpirationState mExpirationState;
nsAutoPtr<nsDocShellEditorData> mEditorData;
};
#endif

View file

@ -0,0 +1,107 @@
/* -*- 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 "nsSHTransaction.h"
#include "nsISHEntry.h"
nsSHTransaction::nsSHTransaction()
: mPersist(true)
, mPrev(nullptr)
{
}
nsSHTransaction::~nsSHTransaction()
{
}
NS_IMPL_ADDREF(nsSHTransaction)
NS_IMPL_RELEASE(nsSHTransaction)
NS_INTERFACE_MAP_BEGIN(nsSHTransaction)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISHTransaction)
NS_INTERFACE_MAP_ENTRY(nsISHTransaction)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsSHTransaction::Create(nsISHEntry* aSHEntry, nsISHTransaction* aPrev)
{
SetSHEntry(aSHEntry);
if (aPrev) {
aPrev->SetNext(this);
}
SetPrev(aPrev);
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::GetSHEntry(nsISHEntry** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mSHEntry;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::SetSHEntry(nsISHEntry* aSHEntry)
{
mSHEntry = aSHEntry;
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::GetNext(nsISHTransaction** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mNext;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::SetNext(nsISHTransaction* aNext)
{
if (aNext) {
NS_ENSURE_SUCCESS(aNext->SetPrev(this), NS_ERROR_FAILURE);
}
mNext = aNext;
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::SetPrev(nsISHTransaction* aPrev)
{
/* This is weak reference to parent. Do not Addref it */
mPrev = aPrev;
return NS_OK;
}
nsresult
nsSHTransaction::GetPrev(nsISHTransaction** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mPrev;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::SetPersist(bool aPersist)
{
mPersist = aPersist;
return NS_OK;
}
NS_IMETHODIMP
nsSHTransaction::GetPersist(bool* aPersist)
{
NS_ENSURE_ARG_POINTER(aPersist);
*aPersist = mPersist;
return NS_OK;
}

View file

@ -0,0 +1,37 @@
/* -*- 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/. */
#ifndef nsSHTransaction_h
#define nsSHTransaction_h
// Helper Classes
#include "nsCOMPtr.h"
// Needed interfaces
#include "nsISHTransaction.h"
class nsISHEntry;
class nsSHTransaction : public nsISHTransaction
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISHTRANSACTION
nsSHTransaction();
protected:
virtual ~nsSHTransaction();
protected:
bool mPersist;
nsISHTransaction* mPrev; // Weak Reference
nsCOMPtr<nsISHTransaction> mNext;
nsCOMPtr<nsISHEntry> mSHEntry;
};
#endif /* nsSHTransaction_h */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
/* -*- 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/. */
#ifndef nsSHistory_h
#define nsSHistory_h
#include "nsCOMPtr.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
#include "nsIWebNavigation.h"
#include "nsISimpleEnumerator.h"
#include "nsTObserverArray.h"
#include "nsWeakPtr.h"
#include "nsIPartialSHistoryListener.h"
#include "prclist.h"
class nsIDocShell;
class nsSHEnumerator;
class nsSHistoryObserver;
class nsISHEntry;
class nsISHTransaction;
class nsSHistory final : public PRCList,
public nsISHistory,
public nsISHistoryInternal,
public nsIWebNavigation
{
public:
nsSHistory();
NS_DECL_ISUPPORTS
NS_DECL_NSISHISTORY
NS_DECL_NSISHISTORYINTERNAL
NS_DECL_NSIWEBNAVIGATION
// One time initialization method called upon docshell module construction
static nsresult Startup();
static void Shutdown();
static void UpdatePrefs();
// Max number of total cached content viewers. If the pref
// browser.sessionhistory.max_total_viewers is negative, then
// this value is calculated based on the total amount of memory.
// Otherwise, it comes straight from the pref.
static uint32_t GetMaxTotalViewers() { return sHistoryMaxTotalViewers; }
private:
virtual ~nsSHistory();
friend class nsSHEnumerator;
friend class nsSHistoryObserver;
// Could become part of nsIWebNavigation
NS_IMETHOD GetTransactionAtIndex(int32_t aIndex, nsISHTransaction** aResult);
nsresult LoadDifferingEntries(nsISHEntry* aPrevEntry, nsISHEntry* aNextEntry,
nsIDocShell* aRootDocShell, long aLoadType,
bool& aDifferenceFound);
nsresult InitiateLoad(nsISHEntry* aFrameEntry, nsIDocShell* aFrameDS,
long aLoadType);
NS_IMETHOD LoadEntry(int32_t aIndex, long aLoadType, uint32_t aHistCmd);
#ifdef DEBUG
nsresult PrintHistory();
#endif
// Evict content viewers in this window which don't lie in the "safe" range
// around aIndex.
void EvictOutOfRangeWindowContentViewers(int32_t aIndex);
static void GloballyEvictContentViewers();
static void GloballyEvictAllContentViewers();
// Calculates a max number of total
// content viewers to cache, based on amount of total memory
static uint32_t CalcMaxTotalViewers();
void RemoveDynEntries(int32_t aOldIndex, int32_t aNewIndex);
nsresult LoadNextPossibleEntry(int32_t aNewIndex, long aLoadType,
uint32_t aHistCmd);
// aIndex is the index of the transaction which may be removed.
// If aKeepNext is true, aIndex is compared to aIndex + 1,
// otherwise comparison is done to aIndex - 1.
bool RemoveDuplicate(int32_t aIndex, bool aKeepNext);
nsCOMPtr<nsISHTransaction> mListRoot;
int32_t mIndex;
int32_t mLength;
int32_t mRequestedIndex;
// Set to true if attached to a grouped session history.
bool mIsPartial;
// The number of entries before this session history object.
int32_t mGlobalIndexOffset;
// The number of entries after this session history object.
int32_t mEntriesInFollowingPartialHistories;
// Session History listeners
nsAutoTObserverArray<nsWeakPtr, 2> mListeners;
// Partial session history listener
nsWeakPtr mPartialHistoryListener;
// Weak reference. Do not refcount this.
nsIDocShell* mRootDocShell;
// Max viewers allowed total, across all SHistory objects
static int32_t sHistoryMaxTotalViewers;
};
class nsSHEnumerator : public nsISimpleEnumerator
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
explicit nsSHEnumerator(nsSHistory* aHistory);
protected:
friend class nsSHistory;
virtual ~nsSHEnumerator();
private:
int32_t mIndex;
nsSHistory* mSHistory;
};
#endif /* nsSHistory */