зеркало из https://github.com/mozilla/gecko-dev.git
Add support for caching content viewers in session history to speed up back/forward (bug 274784). This initial landing has the feature disabled by default; set browser.sessionhistory.max_viewers to the maximum number of pages to cache to enable the feature. r=bzbarsky, sr/a=brendan.
This commit is contained in:
Родитель
47bc88d786
Коммит
aed69207f0
|
@ -498,7 +498,9 @@ nsAccessNode::GetDocShellTreeItemFor(nsIDOMNode *aStartNode)
|
|||
NS_ASSERTION(doc, "No document for node passed in");
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsIDocShellTreeItem *docShellTreeItem = nsnull;
|
||||
CallQueryInterface(container, &docShellTreeItem);
|
||||
if (container) {
|
||||
CallQueryInterface(container, &docShellTreeItem);
|
||||
}
|
||||
|
||||
return docShellTreeItem;
|
||||
}
|
||||
|
|
|
@ -88,10 +88,9 @@ class nsHTMLStyleSheet;
|
|||
class nsIHTMLCSSStyleSheet;
|
||||
|
||||
// IID for the nsIDocument interface
|
||||
// f01b47c6-6271-4c0d-b786-eb5eee222b45
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xf01b47c6, 0x6271, 0x4c0d, \
|
||||
{ 0xb7, 0x86, 0xeb, 0x5e, 0xee, 0x22, 0x2b, 0x45 } }
|
||||
{ 0x8bc6ae5f, 0xb396, 0x11d9, \
|
||||
{ 0xb1, 0x4f, 0x00, 0x11, 0x24, 0x78, 0xd6, 0x26 } }
|
||||
|
||||
// The base value for the content ID counter.
|
||||
// This counter is used by the document to
|
||||
|
@ -665,6 +664,47 @@ public:
|
|||
return mPartID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the document by resetting all input elements and forms that have
|
||||
* autocomplete=off to their default values.
|
||||
*/
|
||||
virtual nsresult Sanitize() = 0;
|
||||
|
||||
/**
|
||||
* Enumerate all subdocuments.
|
||||
* The enumerator callback should return PR_TRUE to continue enumerating, or
|
||||
* PR_FALSE to stop.
|
||||
*/
|
||||
typedef PRBool (*nsSubDocEnumFunc)(nsIDocument *aDocument, void *aData);
|
||||
virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
|
||||
void *aData) = 0;
|
||||
|
||||
/**
|
||||
* Check whether it is safe to cache the presentation of this document
|
||||
* and all of its subdocuments. This method checks the following conditions
|
||||
* recursively:
|
||||
* - Some document types, such as plugin documents, cannot be safely cached.
|
||||
* - If there are any pending requests, we don't allow the presentation
|
||||
* to be cached. Ideally these requests would be suspended and resumed,
|
||||
* but that is difficult in some cases, such as XMLHttpRequest.
|
||||
* - If there are any beforeunload or unload listeners, we must fire them
|
||||
* for correctness, but this likely puts the document into a state where
|
||||
* it would not function correctly if restored.
|
||||
*
|
||||
* |aNewRequest| should be the request for a new document which will
|
||||
* replace this document in the docshell. The new document's request
|
||||
* will be ignored when checking for active requests. If there is no
|
||||
* request associated with the new document, this parameter may be null.
|
||||
*/
|
||||
virtual PRBool CanSavePresentation(nsIRequest *aNewRequest) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that its associated ContentViewer is being destroyed.
|
||||
* This releases circular references so that the document can go away.
|
||||
* Destroy() is only called on documents that have a content viewer.
|
||||
*/
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
~nsIDocument()
|
||||
{
|
||||
|
|
|
@ -126,6 +126,8 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
|||
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIRequest.h"
|
||||
|
||||
#include "nsICharsetAlias.h"
|
||||
static NS_DEFINE_CID(kCharsetAliasCID, NS_CHARSETALIAS_CID);
|
||||
|
@ -1851,37 +1853,6 @@ nsDocument::GetScriptGlobalObject() const
|
|||
void
|
||||
nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
||||
{
|
||||
// XXX HACK ALERT! If the script context owner is null, the document
|
||||
// will soon be going away. So tell our content that to lose its
|
||||
// reference to the document. This has to be done before we actually
|
||||
// set the script context owner to null so that the content elements
|
||||
// can remove references to their script objects.
|
||||
if (!aScriptGlobalObject) {
|
||||
PRInt32 count, indx;
|
||||
|
||||
count = mChildren.Count();
|
||||
|
||||
mIsGoingAway = PR_TRUE;
|
||||
|
||||
for (indx = 0; indx < count; ++indx) {
|
||||
mChildren[indx]->UnbindFromTree();
|
||||
}
|
||||
|
||||
// Propagate the out-of-band notification to each PresShell's
|
||||
// anonymous content as well. This ensures that there aren't any
|
||||
// accidental script references left in anonymous content keeping
|
||||
// the document alive. (While not strictly necessary -- the
|
||||
// PresShell owns us -- it's tidy.)
|
||||
for (count = mPresShells.Count() - 1; count >= 0; --count) {
|
||||
nsCOMPtr<nsIPresShell> shell =
|
||||
NS_STATIC_CAST(nsIPresShell*, mPresShells[count]);
|
||||
if (!shell)
|
||||
continue;
|
||||
|
||||
shell->ReleaseAnonymousContent();
|
||||
}
|
||||
}
|
||||
|
||||
mScriptGlobalObject = aScriptGlobalObject;
|
||||
}
|
||||
|
||||
|
@ -4609,3 +4580,202 @@ nsDocument::UnsetProperty(nsIAtom *aPropertyName, nsresult *aStatus)
|
|||
{
|
||||
return mPropertyTable.UnsetProperty(this, aPropertyName, aStatus);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::Sanitize()
|
||||
{
|
||||
// Sanitize the document by resetting all password fields and any form
|
||||
// fields with autocomplete=off to their default values. We do this now,
|
||||
// instead of when the presentation is restored, to offer some protection
|
||||
// in case there is ever an exploit that allows a cached document to be
|
||||
// accessed from a different document.
|
||||
|
||||
// First locate all input elements, regardless of whether they are
|
||||
// in a form, and reset the password and autocomplete=off elements.
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
nsresult rv = GetElementsByTagName(NS_LITERAL_STRING("input"),
|
||||
getter_AddRefs(nodes));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 length = 0;
|
||||
if (nodes)
|
||||
nodes->GetLength(&length);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> item;
|
||||
nsAutoString value;
|
||||
PRUint32 i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
nodes->Item(i, getter_AddRefs(item));
|
||||
NS_ASSERTION(item, "null item in node list!");
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(item);
|
||||
if (!input)
|
||||
continue;
|
||||
|
||||
PRBool resetValue = PR_FALSE;
|
||||
|
||||
input->GetAttribute(NS_LITERAL_STRING("autocomplete"), value);
|
||||
if (value.LowerCaseEqualsLiteral("off")) {
|
||||
resetValue = PR_TRUE;
|
||||
} else {
|
||||
input->GetType(value);
|
||||
if (value.LowerCaseEqualsLiteral("password"))
|
||||
resetValue = PR_TRUE;
|
||||
}
|
||||
|
||||
if (resetValue) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(input);
|
||||
fc->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Now locate all _form_ elements that have autocomplete=off and reset them
|
||||
rv = GetElementsByTagName(NS_LITERAL_STRING("form"), getter_AddRefs(nodes));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
length = 0;
|
||||
if (nodes)
|
||||
nodes->GetLength(&length);
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
nodes->Item(i, getter_AddRefs(item));
|
||||
NS_ASSERTION(item, "null item in nodelist");
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = do_QueryInterface(item);
|
||||
if (!form)
|
||||
continue;
|
||||
|
||||
form->GetAttribute(NS_LITERAL_STRING("autocomplete"), value);
|
||||
if (value.LowerCaseEqualsLiteral("off"))
|
||||
form->Reset();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct SubDocEnumArgs
|
||||
{
|
||||
nsIDocument::nsSubDocEnumFunc callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
SubDocHashEnum(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
SubDocMapEntry *entry = NS_STATIC_CAST(SubDocMapEntry*, hdr);
|
||||
SubDocEnumArgs *args = NS_STATIC_CAST(SubDocEnumArgs*, arg);
|
||||
|
||||
nsIDocument *subdoc = entry->mSubDocument;
|
||||
PRBool next = subdoc ? args->callback(subdoc, args->data) : PR_TRUE;
|
||||
|
||||
return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
|
||||
{
|
||||
if (mSubDocuments) {
|
||||
SubDocEnumArgs args = { aCallback, aData };
|
||||
PL_DHashTableEnumerate(mSubDocuments, SubDocHashEnum, &args);
|
||||
}
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
CanCacheSubDocument(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
SubDocMapEntry *entry = NS_STATIC_CAST(SubDocMapEntry*, hdr);
|
||||
PRBool *canCacheArg = NS_STATIC_CAST(PRBool*, arg);
|
||||
|
||||
nsIDocument *subdoc = entry->mSubDocument;
|
||||
|
||||
// The aIgnoreRequest we were passed is only for us, so don't pass it on.
|
||||
PRBool canCache = subdoc ? subdoc->CanSavePresentation(nsnull) : PR_FALSE;
|
||||
if (!canCache) {
|
||||
*canCacheArg = PR_FALSE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_bryner
|
||||
#define DEBUG_PAGE_CACHE
|
||||
#endif
|
||||
|
||||
PRBool
|
||||
nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
||||
{
|
||||
// Check our event listneer manager for unload/beforeunload listeners.
|
||||
nsCOMPtr<nsIDOMEventReceiver> er = do_QueryInterface(mScriptGlobalObject);
|
||||
if (er) {
|
||||
nsCOMPtr<nsIEventListenerManager> manager;
|
||||
er->GetListenerManager(getter_AddRefs(manager));
|
||||
if (manager && manager->HasUnloadListeners()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
if (loadGroup) {
|
||||
nsCOMPtr<nsISimpleEnumerator> requests;
|
||||
loadGroup->GetRequests(getter_AddRefs(requests));
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
|
||||
while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> elem;
|
||||
requests->GetNext(getter_AddRefs(elem));
|
||||
|
||||
nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
|
||||
if (request && request != aNewRequest) {
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
nsCAutoString requestName, docSpec;
|
||||
request->GetName(requestName);
|
||||
if (mDocumentURI)
|
||||
mDocumentURI->GetSpec(docSpec);
|
||||
|
||||
printf("document %s has request %s\n",
|
||||
docSpec.get(), requestName.get());
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool canCache = PR_TRUE;
|
||||
if (mSubDocuments)
|
||||
PL_DHashTableEnumerate(mSubDocuments, CanCacheSubDocument, &canCache);
|
||||
|
||||
return canCache;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::Destroy()
|
||||
{
|
||||
// The ContentViewer wants to release the document now. So, tell our content
|
||||
// to drop any references to the document so that it can be destroyed.
|
||||
PRInt32 count = mChildren.Count();
|
||||
|
||||
mIsGoingAway = PR_TRUE;
|
||||
|
||||
for (PRInt32 indx = 0; indx < count; ++indx) {
|
||||
mChildren[indx]->UnbindFromTree();
|
||||
}
|
||||
|
||||
// Propagate the out-of-band notification to each PresShell's anonymous
|
||||
// content as well. This ensures that there aren't any accidental references
|
||||
// left in anonymous content keeping the document alive. (While not strictly
|
||||
// necessary -- the PresShell owns us -- it's tidy.)
|
||||
for (count = mPresShells.Count() - 1; count >= 0; --count) {
|
||||
nsCOMPtr<nsIPresShell> shell =
|
||||
NS_STATIC_CAST(nsIPresShell*, mPresShells[count]);
|
||||
if (!shell)
|
||||
continue;
|
||||
|
||||
shell->ReleaseAnonymousContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -530,6 +530,14 @@ public:
|
|||
virtual NS_HIDDEN_(void*) UnsetProperty(nsIAtom *aPropertyName,
|
||||
nsresult *aStatus = nsnull);
|
||||
|
||||
virtual NS_HIDDEN_(nsresult) Sanitize();
|
||||
|
||||
virtual NS_HIDDEN_(void) EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
|
||||
void *aData);
|
||||
|
||||
virtual NS_HIDDEN_(PRBool) CanSavePresentation(nsIRequest *aNewRequest);
|
||||
virtual NS_HIDDEN_(void) Destroy();
|
||||
|
||||
protected:
|
||||
|
||||
void RetrieveRelevantHeaders(nsIChannel *aChannel);
|
||||
|
@ -592,7 +600,7 @@ protected:
|
|||
|
||||
nsHashtable mRadioGroups;
|
||||
|
||||
// True if the document is being destroyed.
|
||||
// True if the document has been detached from its content viewer.
|
||||
PRPackedBool mIsGoingAway;
|
||||
|
||||
// True if the document is being destroyed.
|
||||
|
|
|
@ -2586,7 +2586,9 @@ nsGenericElement::SetFocus(nsPresContext* aPresContext)
|
|||
PRBool
|
||||
nsGenericElement::ShouldFocus(nsIContent *aContent)
|
||||
{
|
||||
PRBool visible = PR_TRUE;
|
||||
// Default to false, since if the document is not attached to a window,
|
||||
// we should not focus any of its content.
|
||||
PRBool visible = PR_FALSE;
|
||||
|
||||
// Figure out if we're focusing an element in an inactive (hidden)
|
||||
// tab (whose docshell is not visible), if so, drop this focus
|
||||
|
|
|
@ -120,6 +120,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
|
@ -161,6 +162,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
protected:
|
||||
nsWeakPtr mParent;
|
||||
|
@ -249,6 +251,18 @@ txLoadListenerProxy::Error(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
txLoadListenerProxy::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMLoadListener> listener = do_QueryReferent(mParent);
|
||||
|
||||
if (listener) {
|
||||
return listener->PageRestore(aEvent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsForceXMLListener : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
|
@ -512,6 +526,12 @@ nsSyncLoader::Error(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncLoader::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncLoader::OnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
|
|
|
@ -53,9 +53,8 @@ class nsIAtom;
|
|||
* Event listener manager interface.
|
||||
*/
|
||||
#define NS_IEVENTLISTENERMANAGER_IID \
|
||||
{ /* cd91bcf0-ded9-11d1-bd85-00805f8ae3f4 */ \
|
||||
0xcd91bcf0, 0xded9, 0x11d1, \
|
||||
{0xbd, 0x85, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} }
|
||||
{0xc23b877c, 0xb396, 0x11d9, \
|
||||
{0x86, 0xbd, 0x00, 0x11, 0x24, 0x78, 0xd6, 0x26} }
|
||||
|
||||
class nsIEventListenerManager : public nsISupports {
|
||||
|
||||
|
@ -185,6 +184,12 @@ public:
|
|||
* Loop pass for evaluation of system event listeners.
|
||||
*/
|
||||
NS_IMETHOD GetSystemEventGroupLM(nsIDOMEventGroup** aGroup) = 0;
|
||||
|
||||
/**
|
||||
* Allows us to quickly determine whether we have unload or beforeunload
|
||||
* listeners registered.
|
||||
*/
|
||||
virtual PRBool HasUnloadListeners() = 0;
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -58,8 +58,8 @@ static const char* const sEventNames[] = {
|
|||
"mousedown", "mouseup", "click", "dblclick", "mouseover",
|
||||
"mouseout", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
|
||||
"focus", "blur", "load", "beforeunload", "unload", "abort", "error",
|
||||
"submit", "reset", "change", "select", "input", "paint" ,"text",
|
||||
"compositionstart", "compositionend", "popupshowing", "popupshown",
|
||||
"DOMPageRestore", "submit", "reset", "change", "select", "input", "paint",
|
||||
"text", "compositionstart", "compositionend", "popupshowing", "popupshown",
|
||||
"popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
|
||||
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
|
||||
"scroll","overflow", "underflow", "overflowchanged",
|
||||
|
@ -434,6 +434,8 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
|
|||
mEvent->message = NS_IMAGE_ABORT;
|
||||
else if (atom == nsLayoutAtoms::onerror)
|
||||
mEvent->message = NS_IMAGE_ERROR;
|
||||
else if (atom == nsLayoutAtoms::onDOMPageRestore)
|
||||
mEvent->message = NS_PAGE_RESTORE;
|
||||
} else if (mEvent->eventStructType == NS_MUTATION_EVENT) {
|
||||
if (atom == nsLayoutAtoms::onDOMAttrModified)
|
||||
mEvent->message = NS_MUTATION_ATTRMODIFIED;
|
||||
|
@ -794,6 +796,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
|||
case NS_IMAGE_ERROR:
|
||||
case NS_SCRIPT_ERROR:
|
||||
return sEventNames[eDOMEvents_error];
|
||||
case NS_PAGE_RESTORE:
|
||||
return sEventNames[eDOMEvents_DOMPageRestore];
|
||||
case NS_FORM_SUBMIT:
|
||||
return sEventNames[eDOMEvents_submit];
|
||||
case NS_FORM_RESET:
|
||||
|
|
|
@ -85,6 +85,7 @@ public:
|
|||
eDOMEvents_unload,
|
||||
eDOMEvents_abort,
|
||||
eDOMEvents_error,
|
||||
eDOMEvents_DOMPageRestore,
|
||||
eDOMEvents_submit,
|
||||
eDOMEvents_reset,
|
||||
eDOMEvents_change,
|
||||
|
|
|
@ -241,7 +241,8 @@ static const EventDispatchData sLoadEvents[] = {
|
|||
{NS_PAGE_UNLOAD, HANDLER(&nsIDOMLoadListener::Unload),NS_EVENT_BITS_LOAD_UNLOAD},
|
||||
{NS_IMAGE_ERROR, HANDLER(&nsIDOMLoadListener::Error), NS_EVENT_BITS_LOAD_ERROR},
|
||||
{NS_SCRIPT_ERROR,HANDLER(&nsIDOMLoadListener::Error), NS_EVENT_BITS_LOAD_ERROR},
|
||||
{NS_BEFORE_PAGE_UNLOAD,HANDLER(&nsIDOMLoadListener::BeforeUnload), NS_EVENT_BITS_LOAD_BEFORE_UNLOAD}
|
||||
{NS_BEFORE_PAGE_UNLOAD,HANDLER(&nsIDOMLoadListener::BeforeUnload), NS_EVENT_BITS_LOAD_BEFORE_UNLOAD},
|
||||
{NS_PAGE_RESTORE,HANDLER(&nsIDOMLoadListener::PageRestore), NS_EVENT_BITS_LOAD_PAGE_RESTORE}
|
||||
};
|
||||
|
||||
static const EventDispatchData sPaintEvents[] = {
|
||||
|
@ -891,6 +892,10 @@ nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType,
|
|||
*aArrayType = eEventArrayType_Load;
|
||||
*aFlags = NS_EVENT_BITS_LOAD_ERROR;
|
||||
}
|
||||
else if (aType == nsLayoutAtoms::onDOMPageRestore) {
|
||||
*aArrayType = eEventArrayType_Load;
|
||||
*aFlags = NS_EVENT_BITS_LOAD_PAGE_RESTORE;
|
||||
}
|
||||
else if (aType == nsLayoutAtoms::onpaint) {
|
||||
*aArrayType = eEventArrayType_Paint;
|
||||
*aFlags = NS_EVENT_BITS_PAINT_PAINT;
|
||||
|
@ -2232,6 +2237,26 @@ nsEventListenerManager::GetCoordinatesFor(nsIDOMElement *aCurrentEl,
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEventListenerManager::HasUnloadListeners()
|
||||
{
|
||||
nsVoidArray *listeners = GetListenersByType(eEventArrayType_Load, nsnull,
|
||||
PR_FALSE);
|
||||
if (listeners) {
|
||||
PRInt32 count = listeners->Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
PRUint32 subtype = NS_STATIC_CAST(nsListenerStruct*,
|
||||
listeners->FastElementAt(i))->mSubType;
|
||||
if (subtype == NS_EVENT_BITS_NONE ||
|
||||
subtype & (NS_EVENT_BITS_LOAD_UNLOAD |
|
||||
NS_EVENT_BITS_LOAD_BEFORE_UNLOAD))
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult)
|
||||
{
|
||||
|
|
|
@ -164,6 +164,8 @@ public:
|
|||
|
||||
NS_IMETHOD GetSystemEventGroupLM(nsIDOMEventGroup** aGroup);
|
||||
|
||||
virtual PRBool HasUnloadListeners();
|
||||
|
||||
static nsresult GetIdentifiersForType(nsIAtom* aType,
|
||||
EventArrayType* aArrayType,
|
||||
PRInt32* aSubType);
|
||||
|
@ -301,6 +303,7 @@ protected:
|
|||
#define NS_EVENT_BITS_LOAD_ABORT 0x04
|
||||
#define NS_EVENT_BITS_LOAD_ERROR 0x08
|
||||
#define NS_EVENT_BITS_LOAD_BEFORE_UNLOAD 0x10
|
||||
#define NS_EVENT_BITS_LOAD_PAGE_RESTORE 0x20
|
||||
|
||||
//nsIDOMXULListener
|
||||
#define NS_EVENT_BITS_XUL_NONE 0x00
|
||||
|
|
|
@ -1538,15 +1538,17 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
|
|||
// nothing else.
|
||||
nsCOMPtr<nsPIDOMWindow> win =
|
||||
do_QueryInterface(document->GetScriptGlobalObject());
|
||||
nsIFocusController *focusController =
|
||||
win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
|
||||
if(domElement)
|
||||
focusController->SetFocusedElement(domElement);
|
||||
break;
|
||||
if (win) {
|
||||
nsIFocusController *focusController =
|
||||
win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
|
||||
if(domElement)
|
||||
focusController->SetFocusedElement(domElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aPresContext->EventStateManager()->
|
||||
|
|
|
@ -1070,14 +1070,16 @@ nsHTMLInputElement::SetFocus(nsPresContext* aPresContext)
|
|||
// nothing else.
|
||||
nsCOMPtr<nsPIDOMWindow> win =
|
||||
do_QueryInterface(doc->GetScriptGlobalObject());
|
||||
nsIFocusController *focusController = win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
focusController->SetFocusedWindow(win);
|
||||
focusController->SetFocusedElement(this);
|
||||
if (win) {
|
||||
nsIFocusController *focusController = win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
focusController->SetFocusedWindow(win);
|
||||
focusController->SetFocusedElement(this);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aPresContext->EventStateManager()->SetContentState(this,
|
||||
|
@ -1120,14 +1122,16 @@ nsHTMLInputElement::Select()
|
|||
// nothing else.
|
||||
nsCOMPtr<nsPIDOMWindow> win =
|
||||
do_QueryInterface(doc->GetScriptGlobalObject());
|
||||
nsIFocusController *focusController = win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
focusController->SetFocusedWindow(win);
|
||||
focusController->SetFocusedElement(this);
|
||||
SelectAll(presContext);
|
||||
return NS_OK;
|
||||
if (win) {
|
||||
nsIFocusController *focusController = win->GetRootFocusController();
|
||||
PRBool isActive = PR_FALSE;
|
||||
focusController->GetActive(&isActive);
|
||||
if (!isActive) {
|
||||
focusController->SetFocusedWindow(win);
|
||||
focusController->SetFocusedElement(this);
|
||||
SelectAll(presContext);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Just like SetFocus() but without the ScrollIntoView()!
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
nsIContentSink* aSink = nsnull);
|
||||
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
|
||||
virtual void Destroy();
|
||||
|
||||
NS_DECL_NSIIMAGEDOCUMENT
|
||||
|
||||
|
@ -288,27 +289,38 @@ nsImageDocument::StartDocumentLoad(const char* aCommand,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsImageDocument::Destroy()
|
||||
{
|
||||
// Remove our event listener from the image content.
|
||||
if (mImageResizingEnabled) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageContent);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
|
||||
}
|
||||
|
||||
// Break reference cycle with mImageContent, if we have one
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
|
||||
if (imageLoader) {
|
||||
imageLoader->RemoveObserver(this);
|
||||
}
|
||||
|
||||
mImageContent = nsnull;
|
||||
|
||||
nsMediaDocument::Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
|
||||
{
|
||||
if (!aScriptGlobalObject) {
|
||||
if (mImageResizingEnabled) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageContent);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
|
||||
|
||||
target = do_QueryInterface(mScriptGlobalObject);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
// Break reference cycle with mImageContent, if we have one
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
|
||||
if (imageLoader) {
|
||||
imageLoader->RemoveObserver(this);
|
||||
}
|
||||
|
||||
mImageContent = nsnull;
|
||||
// If the script global object is changing, we need to unhook our event
|
||||
// listeners on the window.
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
if (mImageResizingEnabled && mScriptGlobalObject &&
|
||||
aScriptGlobalObject != mScriptGlobalObject) {
|
||||
target = do_QueryInterface(mScriptGlobalObject);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this,
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
// Set the script global object on the superclass before doing
|
||||
|
@ -316,16 +328,18 @@ nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObjec
|
|||
nsHTMLDocument::SetScriptGlobalObject(aScriptGlobalObject);
|
||||
|
||||
if (aScriptGlobalObject) {
|
||||
// Create synthetic document
|
||||
nsresult rv = CreateSyntheticDocument();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
if (!mRootContent) {
|
||||
// Create synthetic document
|
||||
nsresult rv = CreateSyntheticDocument();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic document");
|
||||
|
||||
if (mImageResizingEnabled) {
|
||||
target = do_QueryInterface(mImageContent);
|
||||
target->AddEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (mImageResizingEnabled) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageContent);
|
||||
target->AddEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
|
||||
|
||||
target = do_QueryInterface(aScriptGlobalObject);
|
||||
target->AddEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
|
||||
target->AddEventListener(NS_LITERAL_STRING("keypress"), this, PR_FALSE);
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
nsIContentSink* aSink = nsnull);
|
||||
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
|
||||
virtual PRBool CanSavePresentation(nsIRequest *aNewRequest);
|
||||
|
||||
protected:
|
||||
nsresult CreateSyntheticPluginDocument();
|
||||
|
@ -103,6 +104,15 @@ nsPluginDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObje
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsPluginDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
||||
{
|
||||
// Full-page plugins cannot be cached, currently, because we don't have
|
||||
// the stream listener data to feed to the plugin instance.
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsPluginDocument::StartDocumentLoad(const char* aCommand,
|
||||
nsIChannel* aChannel,
|
||||
|
|
|
@ -289,6 +289,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
privateWindow = do_QueryInterface(doc->GetScriptGlobalObject());
|
||||
if (!privateWindow)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
focusController = privateWindow->GetRootFocusController();
|
||||
|
|
|
@ -229,11 +229,12 @@ public:
|
|||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
NS_IMETHOD Load(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD Unload(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; };
|
||||
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
NS_IMETHOD Unload(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
static nsIXULPrototypeCache* gXULCache;
|
||||
|
|
|
@ -166,9 +166,12 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
|||
|
||||
#if defined(DEBUG_bryner)
|
||||
//#define DEBUG_DOCSHELL_FOCUS
|
||||
#define DEBUG_PAGE_CACHE
|
||||
#endif
|
||||
|
||||
#include "plevent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
|
||||
// Number of documents currently loading
|
||||
static PRInt32 gNumberOfDocumentsLoading = 0;
|
||||
|
@ -246,6 +249,7 @@ nsDocShell::nsDocShell():
|
|||
mIsBeingDestroyed(PR_FALSE),
|
||||
mIsExecutingOnLoadHandler(PR_FALSE),
|
||||
mIsPrintingOrPP(PR_FALSE),
|
||||
mSavingOldViewer(PR_FALSE),
|
||||
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
|
||||
mChildOffset(0),
|
||||
mBusyFlags(BUSY_FLAGS_NONE),
|
||||
|
@ -1355,12 +1359,7 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
|
|||
isRoot = PR_TRUE;
|
||||
}
|
||||
if (mLSHE) {
|
||||
nsCOMPtr<nsIHistoryEntry> historyEntry(do_QueryInterface(mLSHE));
|
||||
|
||||
// Check if this is a subframe navigation
|
||||
if (historyEntry) {
|
||||
historyEntry->GetIsSubFrame(&isSubFrame);
|
||||
}
|
||||
mLSHE->GetIsSubFrame(&isSubFrame);
|
||||
}
|
||||
|
||||
if (!isSubFrame && !isRoot) {
|
||||
|
@ -1675,6 +1674,20 @@ nsDocShell::TabToTreeOwner(PRBool aForward, PRBool* aTookFocus)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSecurityUI(nsISecureBrowserUI **aSecurityUI)
|
||||
{
|
||||
NS_IF_ADDREF(*aSecurityUI = mSecurityUI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetSecurityUI(nsISecureBrowserUI *aSecurityUI)
|
||||
{
|
||||
mSecurityUI = aSecurityUI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsDocShell::nsIDocShellTreeItem
|
||||
//*****************************************************************************
|
||||
|
@ -3257,12 +3270,11 @@ nsDocShell::LoadPage(nsISupports *aPageDescriptor, PRUint32 aDisplayType)
|
|||
// load the page as view-source
|
||||
//
|
||||
if (nsIWebPageDescriptor::DISPLAY_AS_SOURCE == aDisplayType) {
|
||||
nsCOMPtr<nsIHistoryEntry> srcHE(do_QueryInterface(shEntry));
|
||||
nsCOMPtr<nsIURI> oldUri, newUri;
|
||||
nsCString spec, newSpec;
|
||||
|
||||
// Create a new view-source URI and replace the original.
|
||||
rv = srcHE->GetURI(getter_AddRefs(oldUri));
|
||||
rv = shEntry->GetURI(getter_AddRefs(oldUri));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -3716,7 +3728,7 @@ nsDocShell::SetTitle(const PRUnichar * aTitle)
|
|||
// would suffice.
|
||||
if (mOSHE && (mLoadType != LOAD_BYPASS_HISTORY) &&
|
||||
(mLoadType != LOAD_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
|
||||
mOSHE->SetTitle(mTitle.get());
|
||||
mOSHE->SetTitle(mTitle);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4312,6 +4324,60 @@ nsDocShell::CancelRefreshURITimers()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SuspendRefreshURIs()
|
||||
{
|
||||
if (mRefreshURIList) {
|
||||
PRUint32 n = 0;
|
||||
mRefreshURIList->Count(&n);
|
||||
|
||||
for (PRUint32 i = 0; i < n; ++i) {
|
||||
nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
|
||||
if (!timer)
|
||||
continue; // this must be a nsRefreshURI already
|
||||
|
||||
// Replace this timer object with a nsRefreshTimer object.
|
||||
nsCOMPtr<nsITimerCallback> callback;
|
||||
timer->GetCallback(getter_AddRefs(callback));
|
||||
|
||||
timer->Cancel();
|
||||
|
||||
nsCOMPtr<nsRefreshTimer> rt = do_QueryInterface(callback);
|
||||
NS_ASSERTION(rt, "RefreshURIList timer callbacks should only be RefreshTimer objects");
|
||||
|
||||
mRefreshURIList->ReplaceElementAt(rt, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Suspend refresh URIs for our child shells as well.
|
||||
PRInt32 n = mChildList.Count();
|
||||
|
||||
for (PRInt32 i = 0; i < n; ++i) {
|
||||
nsCOMPtr<nsIDocShell> shell = do_QueryInterface(ChildAt(i));
|
||||
if (shell)
|
||||
shell->SuspendRefreshURIs();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::ResumeRefreshURIs()
|
||||
{
|
||||
RefreshURIFromQueue();
|
||||
|
||||
// Resume refresh URIs for our child shells as well.
|
||||
PRInt32 n = mChildList.Count();
|
||||
|
||||
for (PRInt32 i = 0; i < n; ++i) {
|
||||
nsCOMPtr<nsIDocShell> shell = do_QueryInterface(ChildAt(i));
|
||||
if (shell)
|
||||
shell->ResumeRefreshURIs();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::RefreshURIFromQueue()
|
||||
{
|
||||
if (!mRefreshURIList)
|
||||
|
@ -4697,6 +4763,433 @@ nsDocShell::CreateAboutBlankContentViewer()
|
|||
return rv;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDocShell::CanSavePresentation(nsIRequest *aNewRequest)
|
||||
{
|
||||
if (!mOSHE)
|
||||
return PR_FALSE; // no entry to save into
|
||||
|
||||
// Only save presentation for "normal" loads and link loads. Anything else
|
||||
// probably wants to refetch the page, so caching the old presentation
|
||||
// would be incorrect.
|
||||
if (mLoadType != LOAD_NORMAL &&
|
||||
mLoadType != LOAD_HISTORY &&
|
||||
mLoadType != LOAD_LINK)
|
||||
return PR_FALSE;
|
||||
|
||||
// If the session history entry has the saveLayoutState flag set to false,
|
||||
// then we should not cache the presentation.
|
||||
PRBool canSaveState;
|
||||
mOSHE->GetSaveLayoutStateFlag(&canSaveState);
|
||||
if (canSaveState == PR_FALSE)
|
||||
return PR_FALSE;
|
||||
|
||||
// If the document is not done loading, don't cache it.
|
||||
nsCOMPtr<nsPIDOMWindow> pWin = do_QueryInterface(mScriptGlobal);
|
||||
if (!pWin || pWin->IsLoading())
|
||||
return PR_FALSE;
|
||||
|
||||
// Avoid doing the work of saving the presentation state in the case where
|
||||
// the content viewer cache is disabled.
|
||||
PRInt32 maxViewers = 0;
|
||||
mPrefs->GetIntPref("browser.sessionhistory.max_viewers", &maxViewers);
|
||||
if (maxViewers == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
// If the document does not want its presentation cached, then don't.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(pWin->GetExtantDocument());
|
||||
if (!doc || !doc->CanSavePresentation(aNewRequest))
|
||||
return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::CaptureState()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> privWin = do_QueryInterface(mScriptGlobal);
|
||||
if (!privWin || !mOSHE)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupports> windowState;
|
||||
nsresult rv = privWin->SaveWindowState(getter_AddRefs(windowState));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mOSHE->GetURI(getter_AddRefs(uri));
|
||||
nsCAutoString spec;
|
||||
if (uri)
|
||||
uri->GetSpec(spec);
|
||||
printf("Saving presentation into session history\n");
|
||||
printf(" SH URI: %s\n", spec.get());
|
||||
#endif
|
||||
|
||||
rv = mOSHE->SetWindowState(windowState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Suspend refresh URIs and save off the timer queue
|
||||
SuspendRefreshURIs();
|
||||
rv = mOSHE->SetRefreshURIList(mRefreshURIList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mRefreshURIList = nsnull;
|
||||
|
||||
// Capture the current content viewer bounds.
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsDocShell::GetPresShell(getter_AddRefs(shell));
|
||||
if (shell) {
|
||||
nsIViewManager *vm = shell->GetViewManager();
|
||||
if (vm) {
|
||||
nsIView *rootView = nsnull;
|
||||
vm->GetRootView(rootView);
|
||||
if (rootView) {
|
||||
nsIWidget *widget = rootView->GetWidget();
|
||||
if (widget) {
|
||||
nsRect bounds(0, 0, 0, 0);
|
||||
widget->GetBounds(bounds);
|
||||
rv = mOSHE->SetViewerBounds(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Capture the docshell hierarchy.
|
||||
mOSHE->ClearChildShells();
|
||||
|
||||
PRInt32 childCount = mChildList.Count();
|
||||
for (PRInt32 i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
|
||||
NS_ASSERTION(childShell, "null child shell");
|
||||
|
||||
mOSHE->AddChildShell(childShell);
|
||||
}
|
||||
|
||||
// Capture the security state.
|
||||
nsCOMPtr<nsISupports> securityState;
|
||||
if (mSecurityUI)
|
||||
mSecurityUI->CaptureState(getter_AddRefs(securityState));
|
||||
|
||||
return mOSHE->SetSecurityState(securityState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::FireRestoreEvents()
|
||||
{
|
||||
// These events fire bottom-up, so call this on our children first.
|
||||
PRInt32 n = mChildList.Count();
|
||||
for (PRInt32 i = 0; i < n; ++i) {
|
||||
nsCOMPtr<nsIDocShell> child = do_QueryInterface(ChildAt(i));
|
||||
if (child) {
|
||||
child->FireRestoreEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch events. This is a little messy. We need to avoid firing
|
||||
// onload so that it is visible from the content DOM window, but we _do_
|
||||
// want the chrome to see it for chrome/extensions that look for page load.
|
||||
// In addition, we need to fire DOMPageRestore on the content window.
|
||||
|
||||
nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(mContentViewer);
|
||||
NS_ASSERTION(docViewer, "should not be called with a null viewer");
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
docViewer->GetPresShell(getter_AddRefs(shell));
|
||||
NS_ENSURE_TRUE(shell, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsEvent event(PR_TRUE, NS_PAGE_LOAD);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> privWin = do_QueryInterface(mScriptGlobal);
|
||||
NS_ENSURE_TRUE(privWin, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIChromeEventHandler> handler = privWin->GetChromeEventHandler();
|
||||
|
||||
PRUint32 flags = NS_EVENT_FLAG_INIT;
|
||||
event.flags |= flags;
|
||||
flags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL);
|
||||
flags |= NS_EVENT_FLAG_BUBBLE | NS_EVENT_FLAG_CAPTURE;
|
||||
|
||||
nsIDOMEvent *domEvt = nsnull;
|
||||
nsPresContext *pc = shell->GetPresContext();
|
||||
|
||||
nsresult rv = handler->HandleChromeEvent(pc, &event, &domEvt,
|
||||
flags & NS_EVENT_CAPTURE_MASK,
|
||||
&status);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (domEvt) {
|
||||
nsrefcnt rc;
|
||||
NS_RELEASE2(domEvt, rc);
|
||||
if (0 != rc) {
|
||||
// Okay, so someone in the DOM loop (a listener, JS object)
|
||||
// still has a ref to the DOM Event but the internal data
|
||||
// hasn't been malloc'd. Force a copy of the data here so the
|
||||
// DOM Event is still valid.
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent =
|
||||
do_QueryInterface(domEvt);
|
||||
|
||||
if (privateEvent) {
|
||||
privateEvent->DuplicatePrivateData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = nsEventStatus_eIgnore;
|
||||
nsEvent restoreEvent(PR_TRUE, NS_PAGE_RESTORE);
|
||||
|
||||
return mScriptGlobal->HandleDOMEvent(pc, &restoreEvent, nsnull,
|
||||
NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, PRBool aSavePresentation,
|
||||
PRBool *aRestored)
|
||||
{
|
||||
NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,
|
||||
"RestorePresentation should only be called for history loads");
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aSHEntry->GetURI(getter_AddRefs(uri));
|
||||
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
aSHEntry->GetContentViewer(getter_AddRefs(viewer));
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
nsCAutoString spec;
|
||||
if (uri)
|
||||
uri->GetSpec(spec);
|
||||
#endif
|
||||
|
||||
*aRestored = PR_FALSE;
|
||||
|
||||
if (!viewer) {
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("no saved presentation for uri: %s\n", spec.get());
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mContentViewer != viewer, "Restoring existing presentation");
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("restoring presentation from session history: %s\n", spec.get());
|
||||
#endif
|
||||
|
||||
// Save off the root view's parent and sibling so that we can insert the
|
||||
// new content viewer's root view at the same position. Also save the
|
||||
// bounds of the root view's widget.
|
||||
|
||||
nsIView *rootViewSibling = nsnull, *rootViewParent = nsnull;
|
||||
nsRect newBounds(0, 0, 0, 0);
|
||||
|
||||
nsCOMPtr<nsIPresShell> oldPresShell;
|
||||
nsDocShell::GetPresShell(getter_AddRefs(oldPresShell));
|
||||
if (oldPresShell) {
|
||||
nsIViewManager *vm = oldPresShell->GetViewManager();
|
||||
if (vm) {
|
||||
nsIView *oldRootView = nsnull;
|
||||
vm->GetRootView(oldRootView);
|
||||
|
||||
if (oldRootView) {
|
||||
rootViewSibling = oldRootView->GetNextSibling();
|
||||
rootViewParent = oldRootView->GetParent();
|
||||
|
||||
nsIWidget *widget = oldRootView->GetWidget();
|
||||
if (widget) {
|
||||
widget->GetBounds(newBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer ownership to mContentViewer. By ensuring that either the
|
||||
// docshell or the session history, but not both, have references to the
|
||||
// content viewer, we prevent the viewer from being torn down after
|
||||
// Destroy() is called.
|
||||
|
||||
if (!aSavePresentation)
|
||||
FireUnloadNotification();
|
||||
|
||||
mFiredUnloadEvent = PR_FALSE;
|
||||
|
||||
if (mContentViewer) {
|
||||
mContentViewer->Close();
|
||||
|
||||
if (aSavePresentation)
|
||||
mContentViewer->SetHistoryEntry(mOSHE);
|
||||
|
||||
mContentViewer->Destroy();
|
||||
}
|
||||
|
||||
mContentViewer.swap(viewer);
|
||||
viewer = nsnull; // force a release to complete ownership transfer
|
||||
|
||||
// Reattach to the window object.
|
||||
nsresult rv = mContentViewer->Open();
|
||||
|
||||
// Now remove it from the cached presentation.
|
||||
aSHEntry->SetContentViewer(nsnull);
|
||||
|
||||
// Restore our child docshell hierarchy.
|
||||
DestroyChildren();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 i = 0;
|
||||
nsCOMPtr<nsIDocShellTreeItem> childShell;
|
||||
while (NS_SUCCEEDED(aSHEntry->ChildShellAt(i++,
|
||||
getter_AddRefs(childShell))) &&
|
||||
childShell) {
|
||||
AddChild(childShell);
|
||||
}
|
||||
|
||||
// And release the references in the history entry.
|
||||
aSHEntry->ClearChildShells();
|
||||
|
||||
// Restore the sticky state of the viewer. The viewer has set this state
|
||||
// on the history entry in Destroy() just before marking itself non-sticky,
|
||||
// to avoid teardown of the presentation.
|
||||
PRBool sticky;
|
||||
aSHEntry->GetSticky(&sticky);
|
||||
mContentViewer->SetSticky(sticky);
|
||||
|
||||
// get the previous content viewer size
|
||||
nsRect oldBounds(0, 0, 0, 0);
|
||||
aSHEntry->GetViewerBounds(oldBounds);
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsDocShell::GetPresShell(getter_AddRefs(shell));
|
||||
|
||||
nsIViewManager *newVM = shell ? shell->GetViewManager() : nsnull;
|
||||
nsIView *newRootView = nsnull;
|
||||
if (newVM)
|
||||
newVM->GetRootView(newRootView);
|
||||
|
||||
// Insert the new root view at the correct location in the view tree.
|
||||
if (rootViewParent) {
|
||||
nsIViewManager *parentVM = rootViewParent->GetViewManager();
|
||||
|
||||
if (parentVM && newRootView) {
|
||||
parentVM->InsertChild(rootViewParent, newRootView,
|
||||
rootViewSibling, PR_TRUE);
|
||||
|
||||
NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,
|
||||
"error in InsertChild");
|
||||
}
|
||||
}
|
||||
|
||||
// restore the state of the window object
|
||||
nsCOMPtr<nsPIDOMWindow> privWin =
|
||||
do_GetInterface(NS_STATIC_CAST(nsIInterfaceRequestor*, this));
|
||||
NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface");
|
||||
|
||||
nsCOMPtr<nsISupports> windowState;
|
||||
aSHEntry->GetWindowState(getter_AddRefs(windowState));
|
||||
|
||||
rv = privWin->RestoreWindowState(windowState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aSHEntry->SetWindowState(nsnull);
|
||||
|
||||
// Restore the refresh URI list. The refresh timers will be restarted
|
||||
// when EndPageLoad() is called.
|
||||
aSHEntry->GetRefreshURIList(getter_AddRefs(mRefreshURIList));
|
||||
aSHEntry->SetRefreshURIList(nsnull);
|
||||
|
||||
// Restore the page title. Re-setting the current title on the document
|
||||
// will update the docshell title and dispatch DOMTitleChanged.
|
||||
nsIDocument *doc = shell->GetDocument();
|
||||
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(doc);
|
||||
if (doc && nsDoc) {
|
||||
const nsAFlatString &title = doc->GetDocumentTitle();
|
||||
nsDoc->SetTitle(title);
|
||||
}
|
||||
|
||||
mOSHE = aSHEntry;
|
||||
|
||||
// mEODForCurrentDocument is true here, so EndPageLoad will not fire
|
||||
// onload (we fire that below, in a special way so that the content window
|
||||
// does not see it).
|
||||
EndPageLoad(nsnull, nsnull, NS_OK);
|
||||
|
||||
// Meta-refresh timers have been restarted for this shell, but not
|
||||
// for our children. Walk the child shells and restart their timers.
|
||||
PRInt32 n = mChildList.Count();
|
||||
for (i = 0; i < n; ++i) {
|
||||
nsCOMPtr<nsIDocShell> child = do_QueryInterface(ChildAt(i));
|
||||
if (child)
|
||||
child->ResumeRefreshURIs();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> rootSH;
|
||||
GetRootSessionHistory(getter_AddRefs(rootSH));
|
||||
if (rootSH) {
|
||||
nsCOMPtr<nsISHistoryInternal> hist = do_QueryInterface(rootSH);
|
||||
hist->UpdateIndex();
|
||||
}
|
||||
|
||||
// Make sure this presentation is the same size as the previous
|
||||
// presentation. If this is not the same size we showed it at last time,
|
||||
// then we need to resize the widget.
|
||||
|
||||
// XXXbryner This interacts poorly with Firefox's infobar. If the old
|
||||
// presentation had the infobar visible, then we will resize the new
|
||||
// presentation to that smaller size. However, firing the locationchanged
|
||||
// event will hide the infobar, which will immediately resize the window
|
||||
// back to the larger size. A future optimization might be to restore
|
||||
// the presentation at the "wrong" size, then fire the locationchanged
|
||||
// event and check whether the docshell's new size is the same as the
|
||||
// cached viewer size (skipping the resize if they are equal).
|
||||
|
||||
if (newRootView) {
|
||||
nsIWidget *widget = newRootView->GetWidget();
|
||||
if (widget && !newBounds.IsEmpty() && newBounds != oldBounds) {
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("resize widget(%d, %d, %d, %d)\n", newBounds.x,
|
||||
newBounds.y, newBounds.width, newBounds.height);
|
||||
#endif
|
||||
|
||||
widget->Resize(newBounds.x, newBounds.y, newBounds.width,
|
||||
newBounds.height, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the security state
|
||||
if (mSecurityUI) {
|
||||
nsCOMPtr<nsISupports> securityState;
|
||||
aSHEntry->GetSecurityState(getter_AddRefs(securityState));
|
||||
if (securityState)
|
||||
mSecurityUI->TransitionToState(securityState);
|
||||
}
|
||||
|
||||
SetCurrentURI(uri);
|
||||
|
||||
// Dispatch onload and DOMPageRestore.
|
||||
rv = FireRestoreEvents();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mContentViewer->Show();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Restart plugins
|
||||
if (shell)
|
||||
shell->Thaw();
|
||||
|
||||
// XXXbryner Making this invalidate synchronous causes unpainted areas
|
||||
// (on Mac, at least) if the above locationchanged event hides Firefox's
|
||||
// infobar. Doing it asynchronously seems to work around the problem, but
|
||||
// shouldn't the style change that hides the infobar handle all necessary
|
||||
// invalidation, including the newly-exposed area?
|
||||
|
||||
rv = mParentWidget->Invalidate(PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aRestored = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::CreateContentViewer(const char *aContentType,
|
||||
nsIRequest * request,
|
||||
|
@ -4723,7 +5216,10 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
|||
// is changed within the DocShell - otherwise, javascript will get the
|
||||
// wrong information :-(
|
||||
//
|
||||
(void) FireUnloadNotification();
|
||||
|
||||
PRBool savePresentation = CanSavePresentation(request);
|
||||
if (!savePresentation)
|
||||
FireUnloadNotification();
|
||||
|
||||
// Set mFiredUnloadEvent = PR_FALSE so that the unload handler for the
|
||||
// *new* document will fire.
|
||||
|
@ -4738,6 +5234,18 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
|||
|
||||
PRBool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, PR_FALSE);
|
||||
|
||||
if (savePresentation) {
|
||||
// The old content viewer will be saved during the call to Embed().
|
||||
rv = CaptureState();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mSavingOldViewer = PR_TRUE;
|
||||
} else {
|
||||
if (mOSHE) {
|
||||
mOSHE->SyncPresentationState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let's try resetting the load group if we need to...
|
||||
nsCOMPtr<nsILoadGroup> currentLoadGroup;
|
||||
NS_ENSURE_SUCCESS(aOpenedChannel->
|
||||
|
@ -4779,6 +5287,7 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
|||
NS_ENSURE_SUCCESS(Embed(viewer, "", (nsISupports *) nsnull),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
mSavingOldViewer = PR_FALSE;
|
||||
mEODForCurrentDocument = PR_FALSE;
|
||||
|
||||
// if this document is part of a multipart document,
|
||||
|
@ -5028,6 +5537,13 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
|
|||
|
||||
mContentViewer->Close();
|
||||
aNewViewer->SetPreviousViewer(mContentViewer);
|
||||
|
||||
if (mSavingOldViewer) {
|
||||
// Tell the old content viewer to hibernate in session history when
|
||||
// it is destroyed.
|
||||
mContentViewer->SetHistoryEntry(mOSHE);
|
||||
}
|
||||
|
||||
mContentViewer = nsnull;
|
||||
}
|
||||
|
||||
|
@ -5568,7 +6084,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
NS_ENSURE_TRUE(hEntry, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(hEntry));
|
||||
if (shEntry)
|
||||
shEntry->SetTitle(mTitle.get());
|
||||
shEntry->SetTitle(mTitle);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -5588,6 +6104,12 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
}
|
||||
}
|
||||
|
||||
// Check for saving the presentation here, before calling Stop().
|
||||
// This is necessary so that we can catch any pending requests.
|
||||
// Since the new request has not been created yet, we pass null for the
|
||||
// new request parameter.
|
||||
PRBool savePresentation = CanSavePresentation(nsnull);
|
||||
|
||||
// Don't stop current network activity for javascript: URL's since
|
||||
// they might not result in any data, and thus nothing should be
|
||||
// stopped in those cases. In the case where they do result in
|
||||
|
@ -5623,6 +6145,30 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
// been called.
|
||||
mLSHE = aSHEntry;
|
||||
|
||||
// If we have a saved content viewer in history, restore and show it now.
|
||||
if (aSHEntry) {
|
||||
if (savePresentation) {
|
||||
rv = CaptureState();
|
||||
if (NS_FAILED(rv) && mOSHE)
|
||||
mOSHE->SyncPresentationState();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
|
||||
PRBool restored;
|
||||
rv = RestorePresentation(aSHEntry, savePresentation &&
|
||||
NS_SUCCEEDED(rv), &restored);
|
||||
if (restored)
|
||||
return rv;
|
||||
|
||||
// We failed to restore the presentation, so clean up.
|
||||
// Both the old and new history entries could potentially be in
|
||||
// an inconsistent state.
|
||||
if (oldEntry)
|
||||
oldEntry->SyncPresentationState();
|
||||
|
||||
aSHEntry->SyncPresentationState();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
rv = DoURILoad(aURI, aReferrer,
|
||||
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
|
||||
|
@ -6520,12 +7066,11 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
|
|||
}
|
||||
|
||||
//Title is set in nsDocShell::SetTitle()
|
||||
entry->Create(aURI, // uri
|
||||
nsnull, // Title
|
||||
nsnull, // DOMDocument
|
||||
inputStream, // Post data stream
|
||||
nsnull, // LayoutHistory state
|
||||
cacheKey, // CacheKey
|
||||
entry->Create(aURI, // uri
|
||||
EmptyString(), // Title
|
||||
inputStream, // Post data stream
|
||||
nsnull, // LayoutHistory state
|
||||
cacheKey, // CacheKey
|
||||
mContentTypeHint); // Content-type
|
||||
entry->SetReferrerURI(referrerURI);
|
||||
/* If cache got a 'no-store', ask SH not to store
|
||||
|
@ -6556,7 +7101,6 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
|
|||
if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
|
||||
// Replace current entry in session history.
|
||||
PRInt32 index = 0;
|
||||
nsCOMPtr<nsIHistoryEntry> hEntry;
|
||||
mSessionHistory->GetIndex(&index);
|
||||
nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory));
|
||||
// Replace the current entry with the new entry
|
||||
|
@ -6601,10 +7145,8 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType)
|
|||
nsCAutoString contentType;
|
||||
|
||||
NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIHistoryEntry> hEntry(do_QueryInterface(aEntry));
|
||||
NS_ENSURE_TRUE(hEntry, NS_ERROR_FAILURE);
|
||||
|
||||
NS_ENSURE_SUCCESS(hEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
|
||||
NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
|
||||
|
@ -6699,9 +7241,8 @@ nsDocShell::CloneAndReplace(nsISHEntry * src, PRUint32 aCloneID,
|
|||
nsISHEntry *dest = (nsISHEntry *) nsnull;
|
||||
PRUint32 srcID;
|
||||
src->GetID(&srcID);
|
||||
nsCOMPtr<nsIHistoryEntry> srcHE(do_QueryInterface(src));
|
||||
|
||||
if (!src || !replaceEntry || !srcHE)
|
||||
if (!src || !replaceEntry)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (srcID == aCloneID) {
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
#include "nsIHttpChannel.h"
|
||||
#include "nsDocShellTransferableHooks.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsISecureBrowserUI.h"
|
||||
|
||||
/**
|
||||
* Load flag for error pages. This should be bigger than all flags on
|
||||
|
@ -340,7 +341,7 @@ protected:
|
|||
NS_IMETHOD EnsureEditorData();
|
||||
nsresult EnsureTransferableHookData();
|
||||
NS_IMETHOD EnsureFind();
|
||||
NS_IMETHOD RefreshURIFromQueue();
|
||||
nsresult RefreshURIFromQueue();
|
||||
NS_IMETHOD DisplayLoadError(nsresult aError, nsIURI *aURI,
|
||||
const PRUnichar *aURL,
|
||||
nsIChannel* aFailedChannel = nsnull);
|
||||
|
@ -395,6 +396,50 @@ protected:
|
|||
PRBool SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
|
||||
PRBool aFireOnLocationChange);
|
||||
|
||||
// The following methods deal with saving and restoring content viewers
|
||||
// in session history.
|
||||
|
||||
// mContentViewer points to the current content viewer associated with
|
||||
// this docshell. When loading a new document, the content viewer is
|
||||
// either destroyed or stored into a session history entry. To make sure
|
||||
// that destruction happens in a controlled fashion, a given content viewer
|
||||
// is always owned in exactly one of these ways:
|
||||
// 1) The content viewer is active and owned by a docshell's
|
||||
// mContentViewer.
|
||||
// 2) The content viewer is still being displayed while we begin loading
|
||||
// a new document. The content viewer is owned by the _new_
|
||||
// content viewer's mPreviousViewer, and has a pointer to the
|
||||
// nsISHEntry where it will eventually be stored. The content viewer
|
||||
// has been close()d by the docshell, which detaches the document from
|
||||
// the window object.
|
||||
// 3) The content viewer is cached in session history. The nsISHEntry
|
||||
// has the only owning reference to the content viewer. The viewer
|
||||
// has released its nsISHEntry pointer to prevent circular ownership.
|
||||
//
|
||||
// When restoring a content viewer from session history, open() is called
|
||||
// to reattach the document to the window object. The content viewer is
|
||||
// then placed into mContentViewer and removed from the history entry.
|
||||
// (mContentViewer is put into session history as described above, if
|
||||
// applicable).
|
||||
|
||||
// Determines whether we can safely cache the current mContentViewer in
|
||||
// session history. This checks a number of factors such as cache policy,
|
||||
// pending requests, and unload handlers. |aNewRequest| should be the
|
||||
// request for the document to be loaded in place of the current document.
|
||||
PRBool CanSavePresentation(nsIRequest *aNewRequest);
|
||||
|
||||
// Captures the state of the supporting elements of the presentation
|
||||
// (the "window" object, docshell tree, meta-refresh loads, and security
|
||||
// state) and stores them on |mOSHE|.
|
||||
nsresult CaptureState();
|
||||
|
||||
// Restores the presentation stored in |aSHEntry|. The old presentation
|
||||
// is saved in session history if |aSavePresentation| is true.
|
||||
// If a presentation could be restored, |aRestored| is set to true.
|
||||
nsresult RestorePresentation(nsISHEntry *aSHEntry,
|
||||
PRBool aSavePresentation,
|
||||
PRBool *aRestored);
|
||||
|
||||
protected:
|
||||
// Override the parent setter from nsDocLoader
|
||||
virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
|
||||
|
@ -426,6 +471,10 @@ protected:
|
|||
// Indicates that a DocShell in this "docshell tree" is printing
|
||||
PRPackedBool mIsPrintingOrPP;
|
||||
|
||||
// Indicates to SetupNewViewer() that we are in the process of saving the
|
||||
// presentation for mContentViewer.
|
||||
PRPackedBool mSavingOldViewer;
|
||||
|
||||
PRUint32 mAppType;
|
||||
|
||||
// Offset in the parent's child list.
|
||||
|
@ -474,6 +523,9 @@ protected:
|
|||
// Transferable hooks/callbacks
|
||||
nsCOMPtr<nsIClipboardDragDropHookList> mTransferableHookData;
|
||||
|
||||
// Secure browser UI object
|
||||
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
|
||||
|
||||
// WEAK REFERENCES BELOW HERE.
|
||||
// Note these are intentionally not addrefd. Doing so will create a cycle.
|
||||
// For that reasons don't use nsCOMPtr.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMDocument;
|
||||
interface nsISHEntry;
|
||||
|
||||
|
||||
%{ C++
|
||||
|
@ -13,7 +14,7 @@ struct nsRect;
|
|||
[ptr] native nsIDeviceContextPtr(nsIDeviceContext);
|
||||
[ref] native nsRectRef(nsRect);
|
||||
|
||||
[scriptable, uuid(70b8f22d-135c-4c94-8044-1bd3238d0990)]
|
||||
[scriptable, uuid(e2c68a4d-b396-11d9-a3d1-00112478d626)]
|
||||
interface nsIContentViewer : nsISupports
|
||||
{
|
||||
|
||||
|
@ -68,4 +69,22 @@ interface nsIContentViewer : nsISupports
|
|||
*/
|
||||
|
||||
boolean requestWindowClose();
|
||||
|
||||
/**
|
||||
* Attach the content viewer to its DOM window and docshell.
|
||||
*/
|
||||
void open();
|
||||
|
||||
/**
|
||||
* Set the session history entry for the content viewer. If this is set,
|
||||
* then the following actions will happen when destroy() is called (*):
|
||||
* - Sanitize() will be called on the viewer's document
|
||||
* - The content viewer will set the contentViewer property on the
|
||||
* history entry, and release its reference (ownership reversal).
|
||||
* - hide() will be called, and no further destruction will happen.
|
||||
*
|
||||
* (*) unless the document is currently being printed, in which case
|
||||
* it will never be saved in session history.
|
||||
*/
|
||||
void setHistoryEntry(in nsISHEntry entry);
|
||||
};
|
||||
|
|
|
@ -64,8 +64,9 @@ interface nsIInputStream;
|
|||
interface nsIRequest;
|
||||
interface nsISHEntry;
|
||||
interface nsILayoutHistoryState;
|
||||
interface nsISecureBrowserUI;
|
||||
|
||||
[scriptable, uuid(BBFDF99E-D675-42FD-B3EA-EA341C2331A6)]
|
||||
[scriptable, uuid(b0228925-9242-467b-842f-dc739a6e478f)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -340,5 +341,35 @@ interface nsIDocShell : nsISupports
|
|||
attribute nsILayoutHistoryState layoutHistoryState;
|
||||
|
||||
readonly attribute boolean shouldSaveLayoutState;
|
||||
|
||||
/**
|
||||
* The SecureBrowserUI object for this docshell. This is set by XUL
|
||||
* <browser> or nsWebBrowser for their root docshell.
|
||||
*/
|
||||
attribute nsISecureBrowserUI securityUI;
|
||||
|
||||
/**
|
||||
* Cancel the XPCOM timers for each meta-refresh URI in this docshell,
|
||||
* and this docshell's children, recursively. The meta-refresh timers can be
|
||||
* restarted using resumeRefreshURIs(). If the timers are already suspended,
|
||||
* this has no effect.
|
||||
*/
|
||||
void suspendRefreshURIs();
|
||||
|
||||
/**
|
||||
* Restart the XPCOM timers for each meta-refresh URI in this docshell,
|
||||
* and this docshell's children, recursively. If the timers are already
|
||||
* running, this has no effect.
|
||||
*/
|
||||
void resumeRefreshURIs();
|
||||
|
||||
/**
|
||||
* Fire the onload and DOMPageRestore events as part of restoring a
|
||||
* presentation from sessino history. The onload event is fired starting
|
||||
* at the chrome event handler; the DOMPageRestore event is fired starting
|
||||
* at the window object. This first recurses into child docshells so that
|
||||
* events fire in a bottom-up order.
|
||||
*/
|
||||
void fireRestoreEvents();
|
||||
};
|
||||
|
||||
|
|
|
@ -124,6 +124,12 @@ public:
|
|||
return !mIsDocumentLoaded || mRunningTimeout;
|
||||
}
|
||||
|
||||
// Check whether a document is currently loading
|
||||
PRBool IsLoading() const
|
||||
{
|
||||
return !mIsDocumentLoaded;
|
||||
}
|
||||
|
||||
PRBool IsHandlingResizeEvent() const
|
||||
{
|
||||
return mIsHandlingResizeEvent;
|
||||
|
@ -139,6 +145,13 @@ public:
|
|||
// Clear all pending timeouts and intervals.
|
||||
virtual void ClearAllTimeouts() = 0;
|
||||
|
||||
// Returns an object containing the window's state. This also suspends
|
||||
// all running timeouts in the window.
|
||||
virtual nsresult SaveWindowState(nsISupports **aState) = 0;
|
||||
|
||||
// Restore the window state from aState.
|
||||
virtual nsresult RestoreWindowState(nsISupports *aState) = 0;
|
||||
|
||||
protected:
|
||||
nsPIDOMWindow()
|
||||
: mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(PR_FALSE),
|
||||
|
|
|
@ -47,9 +47,8 @@
|
|||
*
|
||||
*/
|
||||
#define NS_IDOMLOADLISTENER_IID \
|
||||
{ /* d1810238-14f8-4cab-9b96-96bedb9de7be */ \
|
||||
0xd1810238, 0x14f8, 0x4cab, \
|
||||
{0x9b, 0x96, 0x96, 0xbe, 0xdb, 0x9d, 0xe7, 0xbe} }
|
||||
{0x0f7fa587, 0xaac5, 0x11d9, \
|
||||
{0xba, 0x4e, 0x00, 0x11, 0x24, 0x78, 0xd6, 0x26} }
|
||||
|
||||
class nsIDOMLoadListener : public nsIDOMEventListener {
|
||||
|
||||
|
@ -91,6 +90,13 @@ public:
|
|||
*/
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent) = 0;
|
||||
|
||||
/**
|
||||
* Processes a DOMPageRestore event. This is dispatched when a page's
|
||||
* presentation is restored from session history (onload does not fire
|
||||
* in this case).
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIDOMLoadListener_h__
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
|
||||
#include "nsIBindingManager.h"
|
||||
#include "nsIXBLService.h"
|
||||
#include "nsInt64.h"
|
||||
|
||||
// used for popup blocking, needs to be converted to something
|
||||
// belonging to the back-end like nsIContentPolicy
|
||||
|
@ -171,6 +172,10 @@ static PRInt32 gRunningTimeoutDepth = 0;
|
|||
PRInt32 gTimeoutCnt = 0;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_bryner
|
||||
#define DEBUG_PAGE_CACHE
|
||||
#endif
|
||||
|
||||
#define DOM_MIN_TIMEOUT_VALUE 10 // 10ms
|
||||
|
||||
// CIDs
|
||||
|
@ -4301,10 +4306,12 @@ nsGlobalWindow::GetPrivateRoot()
|
|||
nsIDocument* doc = chromeElement->GetDocument();
|
||||
if (doc) {
|
||||
parent = do_QueryInterface(doc->GetScriptGlobalObject());
|
||||
nsCOMPtr<nsIDOMWindow> tempParent;
|
||||
parent->GetTop(getter_AddRefs(tempParent));
|
||||
return NS_STATIC_CAST(nsGlobalWindow *,
|
||||
NS_STATIC_CAST(nsIDOMWindow*, tempParent));
|
||||
if (parent) {
|
||||
nsCOMPtr<nsIDOMWindow> tempParent;
|
||||
parent->GetTop(getter_AddRefs(tempParent));
|
||||
return NS_STATIC_CAST(nsGlobalWindow *,
|
||||
NS_STATIC_CAST(nsIDOMWindow*, tempParent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5797,6 +5804,387 @@ nsGlobalWindow::EnsureSizeUpToDate()
|
|||
}
|
||||
}
|
||||
|
||||
#define WINDOWSTATEHOLDER_IID \
|
||||
{0xae1c7401, 0xcdee, 0x404a, {0xbd, 0x63, 0x05, 0xc0, 0x35, 0x0d, 0xa7, 0x72}}
|
||||
|
||||
class WindowStateHolder : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
WindowStateHolder(JSContext *cx, // The JSContext for the window
|
||||
JSObject *aObject, // An object to save the properties onto
|
||||
nsGlobalWindow *aWindow); // The window to operate on
|
||||
|
||||
// This is the property store object that holds the window properties.
|
||||
JSObject* GetObject() { return mJSObj; }
|
||||
|
||||
// Get the listener manager, which holds all event handlers for the window.
|
||||
nsIEventListenerManager* GetListenerManager() { return mListenerManager; }
|
||||
|
||||
// Get the contents of focus memory when the state was saved
|
||||
// (if the focus was inside of this window).
|
||||
nsIDOMElement* GetFocusedElement() { return mFocusedElement; }
|
||||
nsIDOMWindowInternal* GetFocusedWindow() { return mFocusedWindow; }
|
||||
|
||||
// Manage the list of saved timeouts for the window.
|
||||
nsTimeout* GetSavedTimeouts() { return mSavedTimeouts; }
|
||||
nsTimeout** GetTimeoutInsertionPoint() { return mTimeoutInsertionPoint; }
|
||||
void ClearSavedTimeouts() { mSavedTimeouts = nsnull; }
|
||||
|
||||
private:
|
||||
~WindowStateHolder();
|
||||
|
||||
JSRuntime *mRuntime;
|
||||
JSObject *mJSObj;
|
||||
nsCOMPtr<nsIEventListenerManager> mListenerManager;
|
||||
nsCOMPtr<nsIDOMElement> mFocusedElement;
|
||||
nsCOMPtr<nsIDOMWindowInternal> mFocusedWindow;
|
||||
nsTimeout *mSavedTimeouts;
|
||||
nsTimeout **mTimeoutInsertionPoint;
|
||||
};
|
||||
|
||||
WindowStateHolder::WindowStateHolder(JSContext *cx, JSObject *aObject,
|
||||
nsGlobalWindow *aWindow)
|
||||
: mRuntime(::JS_GetRuntime(cx)), mJSObj(aObject)
|
||||
{
|
||||
NS_ASSERTION(aWindow, "null window");
|
||||
|
||||
aWindow->GetListenerManager(getter_AddRefs(mListenerManager));
|
||||
|
||||
nsIFocusController *fc = aWindow->GetRootFocusController();
|
||||
NS_ASSERTION(fc, "null focus controller");
|
||||
|
||||
// We want to save the focused element/window only if they are inside of
|
||||
// this window.
|
||||
|
||||
nsCOMPtr<nsIDOMWindowInternal> focusWinInternal;
|
||||
fc->GetFocusedWindow(getter_AddRefs(focusWinInternal));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> focusedWindow = do_QueryInterface(focusWinInternal);
|
||||
|
||||
while (focusedWindow) {
|
||||
if (focusedWindow == aWindow) {
|
||||
fc->GetFocusedWindow(getter_AddRefs(mFocusedWindow));
|
||||
fc->GetFocusedElement(getter_AddRefs(mFocusedElement));
|
||||
break;
|
||||
}
|
||||
|
||||
focusedWindow =
|
||||
NS_STATIC_CAST(nsGlobalWindow*,
|
||||
NS_STATIC_CAST(nsPIDOMWindow*,
|
||||
focusedWindow))->GetPrivateParent();
|
||||
}
|
||||
|
||||
aWindow->SuspendTimeouts();
|
||||
|
||||
// Clear the timeout list for aWindow (but we don't need to for children)
|
||||
mSavedTimeouts = aWindow->mTimeouts;
|
||||
mTimeoutInsertionPoint = aWindow->mTimeoutInsertionPoint;
|
||||
|
||||
aWindow->mTimeouts = nsnull;
|
||||
aWindow->mTimeoutInsertionPoint = &aWindow->mTimeouts;
|
||||
|
||||
::JS_AddNamedRoot(cx, &mJSObj, "WindowStateHolder::mJSObj");
|
||||
}
|
||||
|
||||
WindowStateHolder::~WindowStateHolder()
|
||||
{
|
||||
::JS_RemoveRootRT(mRuntime, &mJSObj);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(WindowStateHolder, WindowStateHolder)
|
||||
|
||||
static JSClass sWindowStateClass = {
|
||||
"window state", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
static nsresult
|
||||
CopyJSPropertyArray(JSContext *cx, JSObject *aSource, JSObject *aDest,
|
||||
JSIdArray *props)
|
||||
{
|
||||
jsint length = props->length;
|
||||
for (jsint i = 0; i < length; ++i) {
|
||||
jsval propname_value;
|
||||
|
||||
if (!::JS_IdToValue(cx, props->vector[i], &propname_value) ||
|
||||
!JSVAL_IS_STRING(propname_value)) {
|
||||
NS_WARNING("Failed to copy non-string-named window property");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSString *propname = JSVAL_TO_STRING(propname_value);
|
||||
jschar *propname_str = ::JS_GetStringChars(propname);
|
||||
NS_ENSURE_TRUE(propname_str, NS_ERROR_FAILURE);
|
||||
|
||||
// We exclude the "location" property because restoring it this way is
|
||||
// problematic. It will "just work" without us explicitly saving or
|
||||
// restoring the value.
|
||||
|
||||
if (!nsCRT::strcmp(NS_STATIC_CAST(PRUnichar*, propname_str),
|
||||
NS_LITERAL_STRING("location").get())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t propname_len = ::JS_GetStringLength(propname);
|
||||
|
||||
JSPropertyOp getter, setter;
|
||||
uintN attrs;
|
||||
JSBool found;
|
||||
if (!::JS_GetUCPropertyAttrsGetterAndSetter(cx, aSource, propname_str,
|
||||
propname_len, &attrs, &found,
|
||||
&getter, &setter))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_UNEXPECTED);
|
||||
|
||||
jsval propvalue;
|
||||
if (!::JS_LookupUCProperty(cx, aSource, propname_str,
|
||||
propname_len, &propvalue))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool res = ::JS_DefineUCProperty(cx, aDest, propname_str, propname_len,
|
||||
propvalue, getter, setter, attrs);
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
if (res)
|
||||
printf("Copied window property: %s\n",
|
||||
NS_ConvertUTF16toUTF8(NS_STATIC_CAST(PRUnichar*,
|
||||
propname_str)).get());
|
||||
#endif
|
||||
|
||||
if (!res) {
|
||||
#ifdef DEBUG
|
||||
printf("failed to copy property: %s\n",
|
||||
NS_ConvertUTF16toUTF8(NS_STATIC_CAST(PRUnichar*,
|
||||
propname_str)).get());
|
||||
#endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
CopyJSProperties(JSContext *cx, JSObject *aSource, JSObject *aDest)
|
||||
{
|
||||
// Enumerate all of the properties on aSource and install them on aDest.
|
||||
|
||||
JSIdArray *props = ::JS_Enumerate(cx, aSource);
|
||||
if (!props) {
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("[no properties]\n");
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("props length = %d\n", props->length);
|
||||
#endif
|
||||
|
||||
nsresult rv = CopyJSPropertyArray(cx, aSource, aDest, props);
|
||||
::JS_DestroyIdArray(cx, props);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::SaveWindowState(nsISupports **aState)
|
||||
{
|
||||
*aState = nsnull;
|
||||
|
||||
if (!mContext || !mJSObject) {
|
||||
// The window may be getting torn down; don't bother saving state.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSContext *cx = NS_STATIC_CAST(JSContext*, mContext->GetNativeContext());
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
|
||||
|
||||
JSObject *stateObj = ::JS_NewObject(cx, &sWindowStateClass, NULL, NULL);
|
||||
NS_ENSURE_TRUE(stateObj, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// The window state object will root the JSObject.
|
||||
*aState = new WindowStateHolder(cx, stateObj, this);
|
||||
NS_ENSURE_TRUE(*aState, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("saving window state, stateObj = %p\n", stateObj);
|
||||
#endif
|
||||
nsresult rv = CopyJSProperties(cx, mJSObject, stateObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ADDREF(*aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::RestoreWindowState(nsISupports *aState)
|
||||
{
|
||||
if (!mContext || !mJSObject) {
|
||||
// The window may be getting torn down; don't bother restoring state.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSContext *cx = NS_STATIC_CAST(JSContext*, mContext->GetNativeContext());
|
||||
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
|
||||
|
||||
// Note that we don't need to call JS_ClearScope here. The scope is already
|
||||
// cleared by SetNewDocument(), and calling it again here would remove the
|
||||
// XPConnect properties.
|
||||
|
||||
nsCOMPtr<WindowStateHolder> holder = do_QueryInterface(aState);
|
||||
NS_ENSURE_TRUE(holder, NS_ERROR_FAILURE);
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
printf("restoring window state, stateObj = %p\n", holder->GetObject());
|
||||
#endif
|
||||
nsresult rv = CopyJSProperties(cx, holder->GetObject(), mJSObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mListenerManager = holder->GetListenerManager();
|
||||
|
||||
nsIDOMElement *focusedElement = holder->GetFocusedElement();
|
||||
nsIDOMWindowInternal *focusedWindow = holder->GetFocusedWindow();
|
||||
|
||||
// If the toplevel window isn't focused, just update the focus controller.
|
||||
nsIFocusController *fc = nsGlobalWindow::GetRootFocusController();
|
||||
NS_ENSURE_TRUE(fc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRBool active;
|
||||
fc->GetActive(&active);
|
||||
if (active) {
|
||||
PRBool didFocusContent = PR_FALSE;
|
||||
nsCOMPtr<nsIContent> focusedContent = do_QueryInterface(focusedElement);
|
||||
|
||||
if (focusedContent) {
|
||||
// We don't bother checking whether the element or frame is focusable.
|
||||
// If it was focusable when we stored the presentation, it must be
|
||||
// focusable now.
|
||||
PRBool didFocusContent = PR_FALSE;
|
||||
nsIDocument *doc = focusedContent->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsIPresShell *shell = doc->GetShellAt(0);
|
||||
if (shell) {
|
||||
nsPresContext *pc = shell->GetPresContext();
|
||||
if (pc) {
|
||||
pc->EventStateManager()->SetContentState(focusedContent,
|
||||
NS_EVENT_STATE_FOCUS);
|
||||
didFocusContent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!didFocusContent && focusedWindow)
|
||||
focusedWindow->Focus();
|
||||
} else if (focusedWindow) {
|
||||
// Just update the saved focus memory.
|
||||
fc->SetFocusedWindow(focusedWindow);
|
||||
fc->SetFocusedElement(focusedElement);
|
||||
}
|
||||
|
||||
mTimeouts = holder->GetSavedTimeouts();
|
||||
mTimeoutInsertionPoint = holder->GetTimeoutInsertionPoint();
|
||||
|
||||
holder->ClearSavedTimeouts();
|
||||
|
||||
// If our state is being restored from history, we won't be getting an onload
|
||||
// event. Make sure we're marked as being completely loaded.
|
||||
mIsDocumentLoaded = PR_TRUE;
|
||||
|
||||
return ResumeTimeouts();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::SuspendTimeouts()
|
||||
{
|
||||
nsInt64 now = PR_IntervalNow();
|
||||
for (nsTimeout *t = mTimeouts; t; t = t->mNext) {
|
||||
// Change mWhen to be the time remaining for this timer.
|
||||
t->mWhen = PR_MAX(nsInt64(0), nsInt64(t->mWhen) - now);
|
||||
|
||||
// Drop the XPCOM timer; we'll reschedule when restoring the state.
|
||||
if (t->mTimer) {
|
||||
t->mTimer->Cancel();
|
||||
t->mTimer = nsnull;
|
||||
}
|
||||
|
||||
// We don't Release() the timeout because we still need it.
|
||||
}
|
||||
|
||||
// Suspend our children as well.
|
||||
nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(mDocShell);
|
||||
if (node) {
|
||||
PRInt32 childCount = 0;
|
||||
node->GetChildCount(&childCount);
|
||||
|
||||
for (PRInt32 i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> childShell;
|
||||
node->GetChildAt(i, getter_AddRefs(childShell));
|
||||
NS_ASSERTION(childShell, "null child shell");
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> pWin = do_GetInterface(childShell);
|
||||
if (pWin) {
|
||||
nsGlobalWindow *win =
|
||||
NS_STATIC_CAST(nsGlobalWindow*,
|
||||
NS_STATIC_CAST(nsPIDOMWindow*, pWin));
|
||||
|
||||
win->SuspendTimeouts();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::ResumeTimeouts()
|
||||
{
|
||||
// Restore all of the timeouts, using the stored time remaining.
|
||||
|
||||
nsInt64 now = PR_IntervalNow();
|
||||
nsresult rv;
|
||||
|
||||
for (nsTimeout *t = mTimeouts; t; t = t->mNext) {
|
||||
PRInt32 interval = PR_MAX(t->mWhen, DOM_MIN_TIMEOUT_VALUE);
|
||||
t->mWhen = now + nsInt64(t->mWhen);
|
||||
|
||||
t->mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
NS_ENSURE_TRUE(t->mTimer, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = t->mTimer->InitWithFuncCallback(TimerCallback, t, interval,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Resume our children as well.
|
||||
nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(mDocShell);
|
||||
if (node) {
|
||||
PRInt32 childCount = 0;
|
||||
node->GetChildCount(&childCount);
|
||||
|
||||
for (PRInt32 i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> childShell;
|
||||
node->GetChildAt(i, getter_AddRefs(childShell));
|
||||
NS_ASSERTION(childShell, "null child shell");
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> pWin = do_GetInterface(childShell);
|
||||
if (pWin) {
|
||||
nsGlobalWindow *win =
|
||||
NS_STATIC_CAST(nsGlobalWindow*,
|
||||
NS_STATIC_CAST(nsPIDOMWindow*, pWin));
|
||||
|
||||
rv = win->ResumeTimeouts();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// QueryInterface implementation for nsGlobalChromeWindow
|
||||
NS_INTERFACE_MAP_BEGIN(nsGlobalChromeWindow)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
|
||||
|
|
|
@ -105,6 +105,7 @@ class nsNavigator;
|
|||
class nsScreen;
|
||||
class nsHistory;
|
||||
class nsIDocShellLoadInfo;
|
||||
class WindowStateHolder;
|
||||
|
||||
//*****************************************************************************
|
||||
// nsGlobalWindow: Global Object for Scripting
|
||||
|
@ -204,6 +205,8 @@ public:
|
|||
virtual NS_HIDDEN_(OpenAllowValue) GetOpenAllow(const nsAString &aName);
|
||||
|
||||
virtual NS_HIDDEN_(void) ClearAllTimeouts();
|
||||
virtual NS_HIDDEN_(nsresult) SaveWindowState(nsISupports **aState);
|
||||
virtual NS_HIDDEN_(nsresult) RestoreWindowState(nsISupports *aState);
|
||||
|
||||
// nsIDOMViewCSS
|
||||
NS_DECL_NSIDOMVIEWCSS
|
||||
|
@ -220,6 +223,8 @@ public:
|
|||
static void ShutDown();
|
||||
static PRBool IsCallerChrome();
|
||||
|
||||
friend class WindowStateHolder;
|
||||
|
||||
protected:
|
||||
// Object Management
|
||||
virtual ~nsGlobalWindow();
|
||||
|
@ -304,6 +309,9 @@ protected:
|
|||
|
||||
already_AddRefed<nsIWidget> GetMainWidget();
|
||||
|
||||
void SuspendTimeouts();
|
||||
nsresult ResumeTimeouts();
|
||||
|
||||
// When adding new member variables, be careful not to create cycles
|
||||
// through JavaScript. If there is any chance that a member variable
|
||||
// could own objects that are implemented in JavaScript, then those
|
||||
|
|
|
@ -203,28 +203,30 @@ CHClickListener::MouseDown(nsIDOMEvent* aEvent)
|
|||
nsCOMPtr<nsIScriptGlobalObject> sgo;
|
||||
doc->GetScriptGlobalObject(getter_AddRefs(sgo));
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(sgo);
|
||||
PRInt32 scrollX, scrollY;
|
||||
window->GetScrollX(&scrollX);
|
||||
window->GetScrollY(&scrollY);
|
||||
xDelta += scrollX; // Normal direction.
|
||||
yDelta -= scrollY; // Remember, y is flipped.
|
||||
if (window) {
|
||||
PRInt32 scrollX, scrollY;
|
||||
window->GetScrollX(&scrollX);
|
||||
window->GetScrollY(&scrollY);
|
||||
xDelta += scrollX; // Normal direction.
|
||||
yDelta -= scrollY; // Remember, y is flipped.
|
||||
|
||||
#define XMENUOFFSET 20
|
||||
#define MENUHEIGHT 20
|
||||
|
||||
xDelta += XMENUOFFSET;
|
||||
yDelta -= MENUHEIGHT*(selIndex+1);
|
||||
xDelta += XMENUOFFSET;
|
||||
yDelta -= MENUHEIGHT*(selIndex+1);
|
||||
|
||||
NSEvent* event = [NSApp currentEvent];
|
||||
NSPoint point = [event locationInWindow];
|
||||
point.x -= xDelta;
|
||||
point.y -= yDelta;
|
||||
NSEvent* event = [NSApp currentEvent];
|
||||
NSPoint point = [event locationInWindow];
|
||||
point.x -= xDelta;
|
||||
point.y -= yDelta;
|
||||
|
||||
NSEvent* mouseEvent = [NSEvent mouseEventWithType: NSLeftMouseDown location: point
|
||||
modifierFlags: 0 timestamp: [event timestamp]
|
||||
windowNumber: [event windowNumber] context: [event context]
|
||||
eventNumber: [event eventNumber] clickCount: [event clickCount] pressure: [event pressure]];
|
||||
[NSMenu popUpContextMenu: menu withEvent: mouseEvent forView: [[event window] contentView]];
|
||||
NSEvent* mouseEvent = [NSEvent mouseEventWithType: NSLeftMouseDown location: point
|
||||
modifierFlags: 0 timestamp: [event timestamp]
|
||||
windowNumber: [event windowNumber] context: [event context]
|
||||
eventNumber: [event eventNumber] clickCount: [event clickCount] pressure: [event pressure]];
|
||||
[NSMenu popUpContextMenu: menu withEvent: mouseEvent forView: [[event window] contentView]];
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1215,8 +1215,9 @@ NS_IMETHODIMP nsWebBrowser::Create()
|
|||
rv = GetContentDOMWindow(getter_AddRefs(domWindow));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
mSecurityUI = do_CreateInstance(NS_SECURE_BROWSER_UI_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv))mSecurityUI->Init(domWindow);
|
||||
nsCOMPtr<nsISecureBrowserUI> securityUI =
|
||||
do_CreateInstance(NS_SECURE_BROWSER_UI_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) securityUI->Init(domWindow);
|
||||
}
|
||||
|
||||
mDocShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0)
|
||||
|
|
|
@ -168,7 +168,6 @@ protected:
|
|||
nativeWindow mParentNativeWindow;
|
||||
nsIWebProgressListener *mProgressListener;
|
||||
nsCOMPtr<nsIWebProgress> mWebProgress;
|
||||
nsCOMPtr<nsISecureBrowserUI> mSecurityUI;
|
||||
|
||||
nsCOMPtr<nsIPrintSettings> mPrintSettings;
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@
|
|||
#include "nsIEmbeddingSiteWindow2.h"
|
||||
#include "nsIWebBrowserFind.h"
|
||||
#include "nsIWebBrowserFocus.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
// Printer Includes
|
||||
#include "nsIWebBrowserPrint.h"
|
||||
|
|
|
@ -333,6 +333,12 @@ nsDOMParser::Error(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMParser::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMParser::nsDOMParser()
|
||||
: mLoopingForSyncLoad(PR_FALSE)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
|
|
|
@ -121,3 +121,15 @@ nsLoadListenerProxy::Error(nsIDOMEvent* aEvent)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLoadListenerProxy::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMLoadListener> listener(do_QueryReferent(mParent));
|
||||
|
||||
if (listener) {
|
||||
return listener->PageRestore(aEvent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
protected:
|
||||
nsWeakPtr mParent;
|
||||
|
|
|
@ -1743,6 +1743,12 @@ nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast,
|
||||
PRBool aClearEventListeners)
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
// nsIStreamListener
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
virtual nsresult Unload(nsIDOMEvent* aEvent) {printf("Unload\n"); return NS_OK;}
|
||||
virtual nsresult Abort(nsIDOMEvent* aEvent) {printf("Abort\n"); return NS_OK;}
|
||||
virtual nsresult Error(nsIDOMEvent* aEvent) {printf("Error\n"); return NS_OK;}
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent) {printf("PageRestore\n"); return NS_OK;}
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(nsMyListener)
|
||||
|
|
|
@ -73,6 +73,7 @@ REQUIRES = xpcom \
|
|||
util \
|
||||
windowwatcher \
|
||||
accessibility \
|
||||
shistory \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
|
|
@ -148,7 +148,6 @@
|
|||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
// PrintOptions is now implemented by PrintSettingsService
|
||||
static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1";
|
||||
static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1";
|
||||
|
||||
// Printing Events
|
||||
|
@ -189,6 +188,10 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
|
|||
#include "nsISelectionController.h"
|
||||
|
||||
#include "nsBidiUtils.h"
|
||||
#include "nsISHEntry.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsISHistoryInternal.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
|
||||
//paint forcing
|
||||
#include "prenv.h"
|
||||
|
@ -346,7 +349,6 @@ protected:
|
|||
virtual ~DocumentViewerImpl();
|
||||
|
||||
private:
|
||||
void ForceRefresh(void);
|
||||
nsresult MakeWindow(nsIWidget* aParentWidget,
|
||||
const nsRect& aBounds);
|
||||
nsresult InitInternal(nsIWidget* aParentWidget,
|
||||
|
@ -398,30 +400,37 @@ protected:
|
|||
nsCOMPtr<nsIDOMFocusListener> mFocusListener;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> mPreviousViewer;
|
||||
|
||||
PRPackedBool mEnableRendering;
|
||||
PRPackedBool mStopped;
|
||||
PRPackedBool mLoaded;
|
||||
PRPackedBool mDeferredWindowClose;
|
||||
PRInt16 mNumURLStarts;
|
||||
PRInt16 mDestroyRefCount; // a second "refcount" for the document viewer's "destroy"
|
||||
nsCOMPtr<nsISHEntry> mSHEntry;
|
||||
|
||||
nsIWidget* mParentWidget; // purposely won't be ref counted
|
||||
|
||||
PRPackedBool mInPermitUnload;
|
||||
PRInt16 mNumURLStarts;
|
||||
PRInt16 mDestroyRefCount; // a second "refcount" for the document viewer's "destroy"
|
||||
|
||||
unsigned mEnableRendering : 1;
|
||||
unsigned mStopped : 1;
|
||||
unsigned mLoaded : 1;
|
||||
unsigned mDeferredWindowClose : 1;
|
||||
// document management data
|
||||
// these items are specific to markup documents (html and xml)
|
||||
// may consider splitting these out into a subclass
|
||||
unsigned mIsSticky : 1;
|
||||
unsigned mInPermitUnload : 1;
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
PRPackedBool mClosingWhilePrinting;
|
||||
nsPrintEngine* mPrintEngine;
|
||||
nsCOMPtr<nsIDOMWindowInternal> mDialogParentWin;
|
||||
unsigned mClosingWhilePrinting : 1;
|
||||
|
||||
#if NS_PRINT_PREVIEW
|
||||
// These data member support delayed printing when the document is loading
|
||||
// These data members support delayed printing when the document is loading
|
||||
unsigned mPrintIsPending : 1;
|
||||
unsigned mPrintDocIsFullyLoaded : 1;
|
||||
nsCOMPtr<nsIPrintSettings> mCachedPrintSettings;
|
||||
nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
|
||||
PRPackedBool mPrintIsPending;
|
||||
PRPackedBool mPrintDocIsFullyLoaded;
|
||||
#endif // NS_PRINT_PREVIEW
|
||||
|
||||
nsPrintEngine* mPrintEngine;
|
||||
nsCOMPtr<nsIDOMWindowInternal> mDialogParentWin;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
FILE* mDebugFile;
|
||||
#endif // NS_DEBUG
|
||||
|
@ -434,10 +443,6 @@ protected:
|
|||
nsCString mForceCharacterSet;
|
||||
nsCString mPrevDocCharacterSet;
|
||||
|
||||
// document management data
|
||||
// these items are specific to markup documents (html and xml)
|
||||
// may consider splitting these out into a subclass
|
||||
PRPackedBool mIsSticky;
|
||||
|
||||
};
|
||||
|
||||
|
@ -494,8 +499,8 @@ void DocumentViewerImpl::PrepareToStartLoad()
|
|||
// Note: operator new zeros our memory, so no need to init things to null.
|
||||
DocumentViewerImpl::DocumentViewerImpl(nsPresContext* aPresContext)
|
||||
: mPresContext(aPresContext),
|
||||
mHintCharsetSource(kCharsetUninitialized),
|
||||
mIsSticky(PR_TRUE)
|
||||
mIsSticky(PR_TRUE),
|
||||
mHintCharsetSource(kCharsetUninitialized)
|
||||
{
|
||||
PrepareToStartLoad();
|
||||
}
|
||||
|
@ -511,9 +516,9 @@ NS_IMPL_ISUPPORTS7(DocumentViewerImpl,
|
|||
|
||||
DocumentViewerImpl::~DocumentViewerImpl()
|
||||
{
|
||||
NS_ASSERTION(!mDocument, "User did not call nsIContentViewer::Close");
|
||||
if (mDocument) {
|
||||
Close();
|
||||
mDocument->Destroy();
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mPresShell && !mPresContext,
|
||||
|
@ -795,19 +800,19 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
|
|||
makeCX = PR_TRUE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (aDoCreation && mPresContext) {
|
||||
// Create the ViewManager and Root View...
|
||||
if (mPresContext) {
|
||||
// Create the ViewManager and Root View...
|
||||
|
||||
// We must do this before we tell the script global object about
|
||||
// this new document since doing that will cause us to re-enter
|
||||
// into nsSubDocumentFrame code through reflows caused by
|
||||
// FlushPendingNotifications() calls down the road...
|
||||
// We must do this before we tell the script global object about
|
||||
// this new document since doing that will cause us to re-enter
|
||||
// into nsSubDocumentFrame code through reflows caused by
|
||||
// FlushPendingNotifications() calls down the road...
|
||||
|
||||
rv = MakeWindow(aParentWidget, aBounds);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
Hide();
|
||||
rv = MakeWindow(aParentWidget, aBounds);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryInterface(mContainer));
|
||||
|
@ -1170,6 +1175,28 @@ DocumentViewerImpl::Unload()
|
|||
NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Open()
|
||||
{
|
||||
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsRect bounds;
|
||||
mWindow->GetBounds(bounds);
|
||||
|
||||
nsresult rv = InitInternal(mParentWidget, mDeviceContext, bounds,
|
||||
PR_FALSE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mDocument)
|
||||
mDocument->SetContainer(mContainer);
|
||||
|
||||
SyncParentSubDocMap();
|
||||
|
||||
// XXX re-enable image animations once that works correctly
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Close()
|
||||
{
|
||||
|
@ -1184,66 +1211,59 @@ DocumentViewerImpl::Close()
|
|||
// for an object that can be switched in and out so that we don't need
|
||||
// to disable scripts during paint suppression.
|
||||
|
||||
if (mDocument) {
|
||||
if (!mDocument)
|
||||
return NS_OK;
|
||||
|
||||
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
|
||||
// Turn scripting back on
|
||||
// after PrintPreview had turned it off
|
||||
if (GetIsPrintPreview() && mPrintEngine) {
|
||||
mPrintEngine->TurnScriptingOn(PR_TRUE);
|
||||
}
|
||||
// Turn scripting back on
|
||||
// after PrintPreview had turned it off
|
||||
if (GetIsPrintPreview() && mPrintEngine) {
|
||||
mPrintEngine->TurnScriptingOn(PR_TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Break global object circular reference on the document created
|
||||
// in the DocViewer Init
|
||||
nsIScriptGlobalObject* globalObject = mDocument->GetScriptGlobalObject();
|
||||
// Break global object circular reference on the document created
|
||||
// in the DocViewer Init
|
||||
nsIScriptGlobalObject* globalObject = mDocument->GetScriptGlobalObject();
|
||||
|
||||
if (globalObject) {
|
||||
globalObject->SetNewDocument(nsnull, PR_TRUE, PR_TRUE);
|
||||
}
|
||||
if (globalObject) {
|
||||
globalObject->SetNewDocument(nsnull, PR_TRUE, PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
// A Close was called while we were printing
|
||||
// so don't clear the ScriptGlobalObject
|
||||
// or clear the mDocument below
|
||||
// Also, do an extra addref to keep the viewer from going away.
|
||||
if (mPrintEngine && !mClosingWhilePrinting) {
|
||||
mClosingWhilePrinting = PR_TRUE;
|
||||
NS_ADDREF_THIS();
|
||||
} else {
|
||||
// A Close was called while we were printing
|
||||
// so don't clear the ScriptGlobalObject
|
||||
// or clear the mDocument below
|
||||
// Also, do an extra addref to keep the viewer from going away.
|
||||
if (mPrintEngine && !mClosingWhilePrinting) {
|
||||
mClosingWhilePrinting = PR_TRUE;
|
||||
NS_ADDREF_THIS();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// out of band cleanup of webshell
|
||||
mDocument->SetScriptGlobalObject(nsnull);
|
||||
}
|
||||
#else
|
||||
mDocument->SetScriptGlobalObject(nsnull);
|
||||
#endif
|
||||
|
||||
if (mFocusListener) {
|
||||
// get the DOM event receiver
|
||||
nsCOMPtr<nsIDOMEventReceiver> erP(do_QueryInterface(mDocument));
|
||||
NS_WARN_IF_FALSE(erP, "No event receiver in document!");
|
||||
if (mFocusListener) {
|
||||
// get the DOM event receiver
|
||||
nsCOMPtr<nsIDOMEventReceiver> erP(do_QueryInterface(mDocument));
|
||||
NS_WARN_IF_FALSE(erP, "No event receiver in document!");
|
||||
|
||||
if (erP) {
|
||||
erP->RemoveEventListenerByIID(mFocusListener,
|
||||
NS_GET_IID(nsIDOMFocusListener));
|
||||
}
|
||||
if (erP) {
|
||||
erP->RemoveEventListenerByIID(mFocusListener,
|
||||
NS_GET_IID(nsIDOMFocusListener));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
// Don't clear the document if we are printing.
|
||||
if (!mClosingWhilePrinting) {
|
||||
mDocument = nsnull;
|
||||
}
|
||||
#else
|
||||
mDocument = nsnull;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Destroy()
|
||||
{
|
||||
NS_ASSERTION(mDocument, "No document in Destroy()!");
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
// Here is where we check to see if the docment was still being prepared
|
||||
// for printing when it was asked to be destroy from someone externally
|
||||
|
@ -1258,13 +1278,93 @@ DocumentViewerImpl::Destroy()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Don't let the document get unloaded while we are printing
|
||||
// this could happen if we hit the back button during printing
|
||||
// Don't let the document get unloaded while we are printing.
|
||||
// this could happen if we hit the back button during printing.
|
||||
// We also keep the viewer from being cached in session history, since
|
||||
// we require all documents there to be sanitized.
|
||||
if (mDestroyRefCount != 0) {
|
||||
--mDestroyRefCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we were told to put ourselves into session history instead of destroy
|
||||
// the presentation, do that now.
|
||||
PRBool updateHistory = (mSHEntry != nsnull);
|
||||
|
||||
if (mSHEntry) {
|
||||
if (mPresShell)
|
||||
mPresShell->Freeze();
|
||||
|
||||
// Make sure the presentation isn't torn down by Hide().
|
||||
mSHEntry->SetSticky(mIsSticky);
|
||||
mIsSticky = PR_TRUE;
|
||||
|
||||
mSHEntry->SetContentViewer(this);
|
||||
|
||||
// Remove our root view from the view hierarchy.
|
||||
if (mPresShell) {
|
||||
nsIViewManager *vm = mPresShell->GetViewManager();
|
||||
if (vm) {
|
||||
nsIView *rootView = nsnull;
|
||||
vm->GetRootView(rootView);
|
||||
|
||||
if (rootView) {
|
||||
nsIView *rootViewParent = rootView->GetParent();
|
||||
if (rootViewParent) {
|
||||
nsIViewManager *parentVM = rootViewParent->GetViewManager();
|
||||
if (parentVM) {
|
||||
parentVM->RemoveChild(rootView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hide();
|
||||
|
||||
// This is after Hide() so that the user doesn't see the inputs clear.
|
||||
if (mDocument) {
|
||||
nsresult rv = mDocument->Sanitize();
|
||||
if (NS_FAILED(rv)) {
|
||||
// If we failed to sanitize, remove the document immediately.
|
||||
mSHEntry->SetContentViewer(nsnull);
|
||||
mSHEntry->SyncPresentationState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mSHEntry = nsnull;
|
||||
|
||||
// If we put ourselves into session history, make sure there aren't
|
||||
// too many content viewers around. Note: if max_viewers is set to 0,
|
||||
// this can reenter Destroy() and dispose of this content viewer!
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mContainer);
|
||||
if (webNav) {
|
||||
nsCOMPtr<nsISHistory> history;
|
||||
webNav->GetSessionHistory(getter_AddRefs(history));
|
||||
nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
|
||||
if (historyInt) {
|
||||
historyInt->EvictContentViewers();
|
||||
}
|
||||
}
|
||||
|
||||
// Break the link from the document/presentation to the docshell, so that
|
||||
// link traversals cannot affect the currently-loaded document.
|
||||
// When the presentation is restored, Open() and InitInternal() will reset
|
||||
// these pointers to their original values.
|
||||
|
||||
if (mDocument)
|
||||
mDocument->SetContainer(nsnull);
|
||||
if (mPresContext)
|
||||
mPresContext->SetLinkHandler(nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mDocument->Destroy();
|
||||
mDocument = nsnull;
|
||||
|
||||
// All callers are supposed to call destroy to break circular
|
||||
// references. If we do this stuff in the destructor, the
|
||||
// destructor might never be called (especially if we're being
|
||||
|
@ -1323,7 +1423,7 @@ DocumentViewerImpl::Stop(void)
|
|||
mDocument->StopDocumentLoad();
|
||||
}
|
||||
|
||||
if (mEnableRendering && (mLoaded || mStopped) && mPresContext)
|
||||
if (mEnableRendering && (mLoaded || mStopped) && mPresContext && !mSHEntry)
|
||||
mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
|
||||
|
||||
mStopped = PR_TRUE;
|
||||
|
@ -1669,7 +1769,6 @@ DocumentViewerImpl::Hide(void)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_FALSE);
|
||||
|
@ -1786,6 +1885,13 @@ DocumentViewerImpl::SetSticky(PRBool aSticky)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetHistoryEntry(nsISHEntry *aEntry)
|
||||
{
|
||||
mSHEntry = aEntry;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetEnableRendering(PRBool* aResult)
|
||||
{
|
||||
|
@ -1811,13 +1917,6 @@ DocumentViewerImpl::RequestWindowClose(PRBool* aCanClose)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DocumentViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
NS_DEFINE_CID(kCSSLoaderCID, NS_CSS_LOADER_CID);
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
|
|
|
@ -45,7 +45,7 @@ class nsIPresShell;
|
|||
class nsIStyleSheet;
|
||||
|
||||
#define NS_IDOCUMENT_VIEWER_IID \
|
||||
{ 0xa6cf9057, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
|
||||
{ 0x09ad1126, 0xb397, 0x11d9,{0xa5, 0x2c, 0x00, 0x11, 0x24, 0x78, 0xd6, 0x26}}
|
||||
|
||||
/**
|
||||
* A document viewer is a kind of content viewer that uses NGLayout
|
||||
|
|
|
@ -89,8 +89,8 @@ class nsIStyleSheet;
|
|||
class nsCSSFrameConstructor;
|
||||
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0x3b864134, 0x4e25, 0x4cd0, \
|
||||
{0xa6, 0x9e, 0x34, 0x14, 0x13, 0x18, 0x39, 0x58} }
|
||||
{ 0x3861ee48, 0xb397, 0x11d9, \
|
||||
{0x86, 0x9e, 0x00, 0x11, 0x24, 0x78, 0xd6, 0x26} }
|
||||
|
||||
// Constants uses for ScrollFrameIntoView() function
|
||||
#define NS_PRESSHELL_SCROLL_TOP 0
|
||||
|
@ -679,6 +679,19 @@ public:
|
|||
|
||||
PRBool IsAccessibilityActive() { return mIsAccessibilityActive; }
|
||||
|
||||
/**
|
||||
* Stop all active elements (plugins and the caret) in this presentation and
|
||||
* in the presentations of subdocuments.
|
||||
* XXX this should include image animations
|
||||
*/
|
||||
virtual void Freeze() = 0;
|
||||
|
||||
/**
|
||||
* Restarts active elements (plugins) in this presentation and in the
|
||||
* presentations of subdocuments.
|
||||
*/
|
||||
virtual void Thaw() = 0;
|
||||
|
||||
protected:
|
||||
// IMPORTANT: The ownership implicit in the following member variables
|
||||
// has been explicitly checked. If you add any members to this class,
|
||||
|
|
|
@ -164,6 +164,7 @@ LAYOUT_ATOM(oncontextmenu, "oncontextmenu")
|
|||
LAYOUT_ATOM(onDOMActivate, "onDOMActivate")
|
||||
LAYOUT_ATOM(onDOMFocusIn, "onDOMFocusIn")
|
||||
LAYOUT_ATOM(onDOMFocusOut, "onDOMFocusOut")
|
||||
LAYOUT_ATOM(onDOMPageRestore, "onDOMPageRestore")
|
||||
LAYOUT_ATOM(ondblclick, "ondblclick")
|
||||
LAYOUT_ATOM(ondragdrop, "ondragdrop")
|
||||
LAYOUT_ATOM(ondragenter, "ondragenter")
|
||||
|
|
|
@ -151,6 +151,9 @@
|
|||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsIPluginHost.h"
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
#include "nsWidgetsCID.h"
|
||||
|
@ -1204,6 +1207,8 @@ public:
|
|||
NS_IMETHOD IsReflowLocked(PRBool* aIsLocked);
|
||||
|
||||
virtual nsresult ReconstructFrames(void);
|
||||
virtual void Freeze();
|
||||
virtual void Thaw();
|
||||
|
||||
#ifdef IBMBIDI
|
||||
NS_IMETHOD SetCaretBidiLevel(PRUint8 aLevel);
|
||||
|
@ -1513,6 +1518,11 @@ private:
|
|||
void FireResizeEvent();
|
||||
static void sResizeEventCallback(nsITimer* aTimer, void* aPresShell) ;
|
||||
nsCOMPtr<nsITimer> mResizeEventTimer;
|
||||
|
||||
typedef void (*nsPluginEnumCallback)(PresShell*, nsIContent*);
|
||||
void EnumeratePlugins(nsIDOMDocument *aDocument,
|
||||
const nsString &aPluginTag,
|
||||
nsPluginEnumCallback aCallback);
|
||||
};
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
@ -6482,6 +6492,103 @@ PresShell::RemoveOverrideStyleSheet(nsIStyleSheet *aSheet)
|
|||
return mStyleSet->RemoveStyleSheet(nsStyleSet::eOverrideSheet, aSheet);
|
||||
}
|
||||
|
||||
static void
|
||||
StopPluginInstance(PresShell *aShell, nsIContent *aContent)
|
||||
{
|
||||
nsIFrame *frame = aShell->FrameManager()->GetPrimaryFrameFor(aContent);
|
||||
|
||||
nsIObjectFrame *objectFrame = nsnull;
|
||||
if (frame)
|
||||
CallQueryInterface(frame, &objectFrame);
|
||||
if (!objectFrame)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIPluginInstance> instance;
|
||||
objectFrame->GetPluginInstance(*getter_AddRefs(instance));
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
// Check whether the plugin wants SetWindow to be called before or after
|
||||
// Stop/Destroy. This is similar to nsObjectFrame::Destroy(), but we
|
||||
// don't want to destroy the frame just yet.
|
||||
|
||||
PRBool callSetWindowLast = PR_FALSE;
|
||||
instance->GetValue(nsPluginInstanceVariable_CallSetWindowAfterDestroyBool,
|
||||
(void *) &callSetWindowLast);
|
||||
if (callSetWindowLast) {
|
||||
instance->Stop();
|
||||
instance->Destroy();
|
||||
instance->SetWindow(nsnull);
|
||||
} else {
|
||||
instance->SetWindow(nsnull);
|
||||
instance->Stop();
|
||||
instance->Destroy();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPluginHost> pluginHost =
|
||||
do_GetService("@mozilla.org/plugin/host;1");
|
||||
if (pluginHost)
|
||||
pluginHost->StopPluginInstance(instance);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
FreezeSubDocument(nsIDocument *aDocument, void *aData)
|
||||
{
|
||||
nsIPresShell *shell = aDocument->GetShellAt(0);
|
||||
if (shell)
|
||||
shell->Freeze();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::Freeze()
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
||||
if (domDoc) {
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("object"), StopPluginInstance);
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("applet"), StopPluginInstance);
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("embed"), StopPluginInstance);
|
||||
}
|
||||
|
||||
if (mCaret)
|
||||
mCaret->SetCaretVisible(PR_FALSE);
|
||||
|
||||
if (mDocument)
|
||||
mDocument->EnumerateSubDocuments(FreezeSubDocument, nsnull);
|
||||
}
|
||||
|
||||
static void
|
||||
StartPluginInstance(PresShell *aShell, nsIContent *aContent)
|
||||
{
|
||||
// For now we just reconstruct the frame.
|
||||
aShell->RecreateFramesFor(aContent);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
ThawSubDocument(nsIDocument *aDocument, void *aData)
|
||||
{
|
||||
nsIPresShell *shell = aDocument->GetShellAt(0);
|
||||
if (shell)
|
||||
shell->Thaw();
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::Thaw()
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
|
||||
if (domDoc) {
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("object"), StartPluginInstance);
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("applet"), StartPluginInstance);
|
||||
EnumeratePlugins(domDoc, NS_LITERAL_STRING("embed"), StartPluginInstance);
|
||||
}
|
||||
|
||||
if (mDocument)
|
||||
mDocument->EnumerateSubDocuments(ThawSubDocument, nsnull);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Start of protected and private methods on the PresShell
|
||||
//--------------------------------------------------------
|
||||
|
@ -7050,6 +7157,29 @@ PresShell::Observe(nsISupports* aSubject,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::EnumeratePlugins(nsIDOMDocument *aDocument,
|
||||
const nsString &aPluginTag,
|
||||
nsPluginEnumCallback aCallback)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
aDocument->GetElementsByTagName(aPluginTag, getter_AddRefs(nodes));
|
||||
if (!nodes)
|
||||
return;
|
||||
|
||||
PRUint32 length;
|
||||
nodes->GetLength(&length);
|
||||
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nodes->Item(i, getter_AddRefs(node));
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
if (content)
|
||||
aCallback(this, content);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// End of protected and private methods on the PresShell
|
||||
//------------------------------------------------------
|
||||
|
|
|
@ -4435,10 +4435,11 @@ nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn)
|
|||
|
||||
// get the script global object
|
||||
nsIScriptGlobalObject *scriptGlobalObj = mDocument->GetScriptGlobalObject();
|
||||
NS_ASSERTION(scriptGlobalObj, "Can't get nsIScriptGlobalObject");
|
||||
nsIScriptContext *scx = scriptGlobalObj->GetContext();
|
||||
NS_ASSERTION(scx, "Can't get nsIScriptContext");
|
||||
scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE);
|
||||
if (scriptGlobalObj) {
|
||||
nsIScriptContext *scx = scriptGlobalObj->GetContext();
|
||||
NS_ASSERTION(scx, "Can't get nsIScriptContext");
|
||||
scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
|
|
@ -840,6 +840,9 @@ nsMenuPopupFrame::SyncViewWithFrame(nsPresContext* aPresContext,
|
|||
// the left or top sides of the screen may be in negative space (main monitor is on the
|
||||
// right, etc). We need to be sure to do the right thing.
|
||||
nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(document->GetScriptGlobalObject()));
|
||||
if (!window)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMScreen> screen;
|
||||
window->GetScreen(getter_AddRefs(screen));
|
||||
PRInt32 screenWidth = 0, screenHeight = 0;
|
||||
|
|
|
@ -169,15 +169,10 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
|
|||
nsCOMPtr<nsIDOMWindowInternal>
|
||||
window(do_QueryInterface(aPresContext->PresShell()->GetDocument()->GetScriptGlobalObject()));
|
||||
|
||||
|
||||
|
||||
nsPoint nsMoveBy;
|
||||
nsMoveBy = aEvent->refPoint - mLastPoint;
|
||||
|
||||
|
||||
window->MoveBy(nsMoveBy.x,nsMoveBy.y);
|
||||
|
||||
|
||||
if (window) {
|
||||
nsPoint nsMoveBy = aEvent->refPoint - mLastPoint;
|
||||
window->MoveBy(nsMoveBy.x,nsMoveBy.y);
|
||||
}
|
||||
|
||||
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
|
|
|
@ -41,15 +41,23 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMElement;
|
||||
|
||||
[scriptable, uuid(081e31e0-a144-11d3-8c7c-00609792278c)]
|
||||
[scriptable, uuid(c5ca429c-b5c2-11d9-8547-00112478d626)]
|
||||
interface nsISecureBrowserUI : nsISupports
|
||||
{
|
||||
void init(in nsIDOMWindow window);
|
||||
|
||||
readonly attribute unsigned long state;
|
||||
readonly attribute AString tooltipText;
|
||||
|
||||
/* Returns an object that encapsulates the current security state. */
|
||||
nsISupports captureState();
|
||||
|
||||
/**
|
||||
* Restore the state captured by captureState(), firing transition
|
||||
* notifications as necessary.
|
||||
*/
|
||||
void transitionToState(in nsISupports state);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -206,12 +206,20 @@ nsSecureBrowserUIImpl::Init(nsIDOMWindow *window)
|
|||
rv = svc->AddObserver(this, NS_FORMSUBMIT_SUBJECT, PR_TRUE);
|
||||
}
|
||||
|
||||
/* GetWebProgress(mWindow) */
|
||||
// hook up to the webprogress notifications.
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(mWindow));
|
||||
if (!sgo) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIWebProgress> wp(do_GetInterface(sgo->GetDocShell()));
|
||||
|
||||
nsIDocShell *docShell = sgo->GetDocShell();
|
||||
|
||||
// The Docshell will own the SecureBrowserUI object
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
docShell->SetSecurityUI(this);
|
||||
|
||||
/* GetWebProgress(mWindow) */
|
||||
// hook up to the webprogress notifications.
|
||||
nsCOMPtr<nsIWebProgress> wp(do_GetInterface(docShell));
|
||||
if (!wp) return NS_ERROR_FAILURE;
|
||||
/* end GetWebProgress */
|
||||
|
||||
|
@ -982,12 +990,19 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)
|
|||
newSecurityState = lis_no_security;
|
||||
}
|
||||
|
||||
return UpdateSecurityState(newSecurityState, aRequest);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSecureBrowserUIImpl::UpdateSecurityState(lockIconState aNewState,
|
||||
nsIRequest *aRequest)
|
||||
{
|
||||
PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
|
||||
("SecureUI:%p: UpdateSecurityState: old-new %d - %d\n", this,
|
||||
mPreviousSecurityState, newSecurityState
|
||||
mPreviousSecurityState, aNewState
|
||||
));
|
||||
|
||||
if (mPreviousSecurityState != newSecurityState)
|
||||
if (mPreviousSecurityState != aNewState)
|
||||
{
|
||||
// must show alert
|
||||
|
||||
|
@ -1032,7 +1047,7 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)
|
|||
{
|
||||
case lis_no_security:
|
||||
case lis_broken_security:
|
||||
switch (newSecurityState)
|
||||
switch (aNewState)
|
||||
{
|
||||
case lis_no_security:
|
||||
case lis_broken_security:
|
||||
|
@ -1049,7 +1064,7 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)
|
|||
|
||||
if (showWarning)
|
||||
{
|
||||
switch (newSecurityState)
|
||||
switch (aNewState)
|
||||
{
|
||||
case lis_no_security:
|
||||
case lis_broken_security:
|
||||
|
@ -1070,9 +1085,9 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)
|
|||
}
|
||||
}
|
||||
|
||||
mPreviousSecurityState = newSecurityState;
|
||||
mPreviousSecurityState = aNewState;
|
||||
|
||||
if (lis_no_security == newSecurityState)
|
||||
if (lis_no_security == aNewState)
|
||||
{
|
||||
mSSLStatus = nsnull;
|
||||
mInfoTooltip.Truncate();
|
||||
|
@ -1083,7 +1098,7 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest)
|
|||
{
|
||||
PRUint32 newState = STATE_IS_INSECURE;
|
||||
|
||||
switch (newSecurityState)
|
||||
switch (aNewState)
|
||||
{
|
||||
case lis_broken_security:
|
||||
newState = STATE_IS_BROKEN;
|
||||
|
@ -1483,3 +1498,50 @@ ConfirmPostToInsecureFromSecure()
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define NS_SECUREBROWSERUISTATE_IID \
|
||||
{0x086c5daf, 0xbb0a, 0x45cb, {0x98, 0x2b, 0xf1, 0x62, 0x49, 0xd5, 0x0e, 0x28}}
|
||||
|
||||
class nsSecureBrowserUIImpl::State : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_SECUREBROWSERUISTATE_IID)
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
State(lockIconState aState, nsISupports *aSSLStatus);
|
||||
|
||||
lockIconState GetState() const { return mState; }
|
||||
nsISupports* GetSSLStatus() { return mSSLStatus; }
|
||||
|
||||
private:
|
||||
lockIconState mState;
|
||||
nsCOMPtr<nsISupports> mSSLStatus;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSecureBrowserUIImpl::State, nsSecureBrowserUIImpl::State)
|
||||
|
||||
nsSecureBrowserUIImpl::State::State(lockIconState aState,
|
||||
nsISupports *aSSLStatus)
|
||||
: mState(aState), mSSLStatus(aSSLStatus)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSecureBrowserUIImpl::CaptureState(nsISupports **aState)
|
||||
{
|
||||
*aState = new State(mPreviousSecurityState, mSSLStatus);
|
||||
NS_ENSURE_TRUE(aState, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSecureBrowserUIImpl::TransitionToState(nsISupports *aState)
|
||||
{
|
||||
nsCOMPtr<nsSecureBrowserUIImpl::State> state = do_QueryInterface(aState);
|
||||
NS_ENSURE_TRUE(state, NS_ERROR_NULL_POINTER);
|
||||
|
||||
mSSLStatus = state->GetSSLStatus();
|
||||
return UpdateSecurityState(state->GetState(), nsnull);
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ protected:
|
|||
PRInt32 mSubRequestsNoSecurity;
|
||||
|
||||
nsresult UpdateSecurityState(nsIRequest* aRequest);
|
||||
nsresult UpdateSecurityState(lockIconState aNewState, nsIRequest *aRequest);
|
||||
nsresult EvaluateAndUpdateSecurityState(nsIRequest *aRequest);
|
||||
void UpdateSubrequestMembers(nsIRequest *aRequest);
|
||||
|
||||
|
@ -144,6 +145,7 @@ protected:
|
|||
nsresult GetNSSDialogs(nsISecurityWarningDialogs **);
|
||||
|
||||
PLDHashTable mTransferringRequests;
|
||||
class State;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@
|
|||
#include "nsIAutoCompleteResult.h"
|
||||
#include "nsIPK11TokenDB.h"
|
||||
#include "nsIPK11Token.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
|
||||
static const char kPMPropertiesURL[] = "chrome://passwordmgr/locale/passwordmgr.properties";
|
||||
static PRBool sRememberPasswords = PR_FALSE;
|
||||
|
@ -263,6 +266,37 @@ nsPasswordManager::Init()
|
|||
|
||||
progress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
||||
|
||||
// Listen for "domwindowopened", this will let us attach our DOMPageRestore
|
||||
// event listener.
|
||||
|
||||
obsService->AddObserver(this, "domwindowopened", PR_FALSE);
|
||||
obsService->AddObserver(this, "domwindowclosed", PR_FALSE);
|
||||
|
||||
// Also register on any open windows that already exist, since we don't
|
||||
// get notifications for those.
|
||||
|
||||
nsCOMPtr<nsIWindowWatcher> watcher =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
|
||||
if (watcher) {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
watcher->GetWindowEnumerator(getter_AddRefs(enumerator));
|
||||
if (enumerator) {
|
||||
PRBool hasMore;
|
||||
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> item;
|
||||
enumerator->GetNext(getter_AddRefs(item));
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(item);
|
||||
if (targ) {
|
||||
targ->AddEventListener(NS_LITERAL_STRING("DOMPageRestore"),
|
||||
NS_STATIC_CAST(nsIDOMLoadListener*, this),
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now read in the signon file
|
||||
nsXPIDLCString signonFile;
|
||||
mPrefBranch->GetCharPref("SignonFileName", getter_Copies(signonFile));
|
||||
|
@ -747,6 +781,20 @@ nsPasswordManager::Observe(nsISupports* aSubject,
|
|||
NS_ASSERTION(branch == mPrefBranch, "unexpected pref change notification");
|
||||
|
||||
branch->GetBoolPref("rememberSignons", &sRememberPasswords);
|
||||
} else if (!strcmp(aTopic, "domwindowopened")) {
|
||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(aSubject);
|
||||
if (targ) {
|
||||
targ->AddEventListener(NS_LITERAL_STRING("DOMPageRestore"),
|
||||
NS_STATIC_CAST(nsIDOMLoadListener*, this),
|
||||
PR_FALSE);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "domwindowclosed")) {
|
||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(aSubject);
|
||||
if (targ) {
|
||||
targ->RemoveEventListener(NS_LITERAL_STRING("DOMPageRestore"),
|
||||
NS_STATIC_CAST(nsIDOMLoadListener*, this),
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -765,16 +813,22 @@ nsPasswordManager::OnStateChange(nsIWebProgress* aWebProgress,
|
|||
!(aStateFlags & nsIWebProgressListener::STATE_STOP))
|
||||
return NS_OK;
|
||||
|
||||
// Don't do anything if the global signon pref is disabled
|
||||
if (!SingleSignonEnabled())
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWin;
|
||||
nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return DoPrefill(domWin);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPasswordManager::DoPrefill(nsIDOMWindow *aDOMWindow)
|
||||
{
|
||||
// Don't do anything if the global signon pref is disabled
|
||||
if (!SingleSignonEnabled())
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
domWin->GetDocument(getter_AddRefs(domDoc));
|
||||
aDOMWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
NS_ASSERTION(domDoc, "DOM window should always have a document!");
|
||||
|
||||
// For now, only prefill forms in HTML documents.
|
||||
|
@ -1568,6 +1622,32 @@ nsPasswordManager::Error(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPasswordManager::PageRestore(nsIDOMEvent* aEvent)
|
||||
{
|
||||
// Only autofill for trusted events.
|
||||
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(aEvent);
|
||||
PRBool trusted = PR_FALSE;
|
||||
if (nsevent)
|
||||
nsevent->GetIsTrusted(&trusted);
|
||||
if (!trusted)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIDOMWindow> win =
|
||||
do_QueryInterface(doc->GetScriptGlobalObject());
|
||||
if (win) {
|
||||
return DoPrefill(win);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// internal methods
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ public:
|
|||
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aEvent);
|
||||
|
||||
// Autocomplete
|
||||
PRBool AutoCompleteSearch(const nsAString& aSearchString,
|
||||
|
@ -157,6 +158,7 @@ protected:
|
|||
nsresult FillPassword(nsIDOMEvent* aEvent);
|
||||
void AttachToInput(nsIDOMHTMLInputElement* aElement);
|
||||
PRBool GetPasswordRealm(nsIURI* aURI, nsACString& aRealm);
|
||||
nsresult DoPrefill(nsIDOMWindow *aDOMWindw);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK FindEntryEnumerator(const nsACString& aKey,
|
||||
SignonHashEntry* aEntry,
|
||||
|
|
|
@ -880,6 +880,12 @@ nsFormFillController::Error(nsIDOMEvent *aLoadEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFillController::PageRestore(nsIDOMEvent *aLoadEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsFormFillController
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ public:
|
|||
NS_IMETHOD Unload(nsIDOMEvent *aLoadEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent *aLoadEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent *aLoadEvent);
|
||||
NS_IMETHOD PageRestore(nsIDOMEvent* aLoadEvent);
|
||||
|
||||
nsFormFillController();
|
||||
virtual ~nsFormFillController();
|
||||
|
|
|
@ -104,6 +104,7 @@ NS_INTERFACE_MAP_BEGIN(nsTypeAheadFind)
|
|||
NS_INTERFACE_MAP_ENTRY(nsITypeAheadFind)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITypeAheadFind)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsTypeAheadFind)
|
||||
|
|
|
@ -484,9 +484,9 @@
|
|||
null
|
||||
</field>
|
||||
|
||||
<field name="securityUI">
|
||||
null
|
||||
</field>
|
||||
<property name="securityUI"
|
||||
onget="return this.docShell.securityUI;"
|
||||
onset="this.docShell.securityUI = val;"/>
|
||||
|
||||
<field name="userTypedClear">
|
||||
true
|
||||
|
@ -544,8 +544,8 @@
|
|||
const SECUREBROWSERUI_CONTRACTID = "@mozilla.org/secure_browser_ui;1";
|
||||
if (!this.hasAttribute("disablesecurity") &&
|
||||
SECUREBROWSERUI_CONTRACTID in Components.classes) {
|
||||
this.securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID].createInstance(Components.interfaces.nsISecureBrowserUI);
|
||||
this.securityUI.init(this.contentWindow);
|
||||
var securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID].createInstance(Components.interfaces.nsISecureBrowserUI);
|
||||
securityUI.init(this.contentWindow);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
|
|
|
@ -491,6 +491,15 @@ NS_IMETHODIMP nsView::SetFloating(PRBool aFloatingView)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsView::InvalidateHierarchy()
|
||||
{
|
||||
if (mViewManager->GetRootView() == this)
|
||||
mViewManager->InvalidateHierarchy();
|
||||
|
||||
for (nsView *child = mFirstChild; child; child = child->GetNextSibling())
|
||||
child->InvalidateHierarchy();
|
||||
}
|
||||
|
||||
void nsView::InsertChild(nsView *aChild, nsView *aSibling)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aChild, "null ptr");
|
||||
|
@ -512,6 +521,15 @@ void nsView::InsertChild(nsView *aChild, nsView *aSibling)
|
|||
mFirstChild = aChild;
|
||||
}
|
||||
aChild->SetParent(this);
|
||||
|
||||
// If we just inserted a root view, then update the RootViewManager
|
||||
// on all view managers in the new subtree.
|
||||
|
||||
nsViewManager *vm = aChild->GetViewManager();
|
||||
if (vm->GetRootView() == aChild)
|
||||
{
|
||||
aChild->InvalidateHierarchy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,6 +558,15 @@ void nsView::RemoveChild(nsView *child)
|
|||
kid = kid->GetNextSibling();
|
||||
}
|
||||
NS_ASSERTION(found, "tried to remove non child");
|
||||
|
||||
// If we just removed a root view, then update the RootViewManager
|
||||
// on all view managers in the removed subtree.
|
||||
|
||||
nsViewManager *vm = child->GetViewManager();
|
||||
if (vm->GetRootView() == child)
|
||||
{
|
||||
child->InvalidateHierarchy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,9 @@ public:
|
|||
void SetPositionIgnoringChildWidgets(nscoord aX, nscoord aY);
|
||||
nsresult LoadWidget(const nsCID &aClassIID);
|
||||
|
||||
// Update the cached RootViewManager for all view manager descendents.
|
||||
void InvalidateHierarchy();
|
||||
|
||||
virtual ~nsView();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -4440,3 +4440,22 @@ nsViewManager::ProcessSynthMouseMoveEvent(PRBool aFromScroll)
|
|||
if (!aFromScroll)
|
||||
mSynthMouseMoveEventQueue = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsViewManager::InvalidateHierarchy()
|
||||
{
|
||||
if (mRootView) {
|
||||
if (mRootViewManager != this) {
|
||||
NS_IF_RELEASE(mRootViewManager);
|
||||
}
|
||||
nsView *parent = mRootView->GetParent();
|
||||
if (parent) {
|
||||
mRootViewManager = parent->GetViewManager()->RootViewManager();
|
||||
NS_ADDREF(mRootViewManager);
|
||||
NS_ASSERTION(mRootViewManager != this,
|
||||
"Root view had a parent, but it has the same view manager");
|
||||
} else {
|
||||
mRootViewManager = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,6 +267,9 @@ public:
|
|||
NS_IMETHOD SynthesizeMouseMove(PRBool aFromScroll);
|
||||
void ProcessSynthMouseMoveEvent(PRBool aFromScroll);
|
||||
|
||||
/* Update the cached RootViewManager pointer on this view manager. */
|
||||
void InvalidateHierarchy();
|
||||
|
||||
protected:
|
||||
virtual ~nsViewManager();
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ class nsIURI;
|
|||
#define NS_IMAGE_ERROR (NS_STREAM_EVENT_START + 4)
|
||||
#define NS_SCRIPT_LOAD (NS_STREAM_EVENT_START + 5)
|
||||
#define NS_BEFORE_PAGE_UNLOAD (NS_STREAM_EVENT_START + 6)
|
||||
#define NS_PAGE_RESTORE (NS_STREAM_EVENT_START + 7)
|
||||
|
||||
#define NS_FORM_EVENT_START 1200
|
||||
#define NS_FORM_SUBMIT (NS_FORM_EVENT_START)
|
||||
|
|
|
@ -43,12 +43,12 @@ interface nsIObserver;
|
|||
|
||||
%{C++
|
||||
/**
|
||||
* The signature of the timer callback function passed to initWithCallback. This
|
||||
* is the function that will get called when the timer expires if the timer is
|
||||
* initialized via initWithCallback.
|
||||
* The signature of the timer callback function passed to initWithFuncCallback.
|
||||
* This is the function that will get called when the timer expires if the
|
||||
* timer is initialized via initWithFuncCallback.
|
||||
*
|
||||
* @param aTimer the timer which has expired
|
||||
* @param aClosure opaque parameter passed to initWithCallback
|
||||
* @param aClosure opaque parameter passed to initWithFuncCallback
|
||||
*
|
||||
* Implementers should return the following:
|
||||
*
|
||||
|
@ -82,7 +82,7 @@ interface nsITimerCallback : nsISupports
|
|||
* delay to avoid the overhead of destroying and creating a timer. It is not
|
||||
* necessary to cancel the timer in that case.
|
||||
*/
|
||||
[scriptable, uuid(29ee628e-a3ea-471f-965d-dc9f11d1c183)]
|
||||
[scriptable, uuid(436a83fa-b396-11d9-bcfa-00112478d626)]
|
||||
interface nsITimer : nsISupports
|
||||
{
|
||||
/* Timer types */
|
||||
|
@ -179,9 +179,14 @@ interface nsITimer : nsISupports
|
|||
attribute unsigned long type;
|
||||
|
||||
/**
|
||||
* The opaque pointer pass to initWithCallback.
|
||||
* The opaque pointer pass to initWithFuncCallback.
|
||||
*/
|
||||
[noscript] readonly attribute voidPtr closure;
|
||||
|
||||
/**
|
||||
* The nsITimerCallback object passed to initWithCallback.
|
||||
*/
|
||||
readonly attribute nsITimerCallback callback;
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -331,6 +331,17 @@ NS_IMETHODIMP nsTimerImpl::GetClosure(void** aClosure)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsTimerImpl::GetCallback(nsITimerCallback **aCallback)
|
||||
{
|
||||
if (mCallbackType == CALLBACK_TYPE_INTERFACE)
|
||||
NS_IF_ADDREF(*aCallback = mCallback.i);
|
||||
else
|
||||
*aCallback = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsTimerImpl::GetIdle(PRBool *aIdle)
|
||||
{
|
||||
*aIdle = mIdle;
|
||||
|
|
|
@ -53,30 +53,30 @@ interface nsIURI;
|
|||
interface nsIHistoryEntry : 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 URI
|
||||
* of the current entry. The object returned is
|
||||
* of type nsIURI
|
||||
*/
|
||||
readonly attribute nsIURI URI;
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -42,88 +42,145 @@
|
|||
* hold all information required to recreate the document from history
|
||||
*
|
||||
*/
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIURI.idl"
|
||||
#include "nsIInputStream.idl"
|
||||
#include "nsIHistoryEntry.idl"
|
||||
|
||||
interface nsILayoutHistoryState;
|
||||
interface nsIDOMDocument;
|
||||
interface nsIContentViewer;
|
||||
interface nsIURI;
|
||||
interface nsIInputStream;
|
||||
interface nsIDocShellTreeItem;
|
||||
interface nsISecureBrowserUIState;
|
||||
interface nsISupportsArray;
|
||||
%{C++
|
||||
struct nsRect;
|
||||
%}
|
||||
[ref] native nsRect(nsRect);
|
||||
|
||||
[scriptable, uuid(6b596e1f-a3bd-40f9-a7ee-ab3edc7f9960)]
|
||||
interface nsISHEntry : nsISupports
|
||||
[scriptable, uuid(e47bf412-3bc2-4306-a82f-ea2bdf950432)]
|
||||
interface nsISHEntry : nsIHistoryEntry
|
||||
{
|
||||
/** URI for the document */
|
||||
void setURI(in nsIURI aURI);
|
||||
|
||||
/** URI for the document */
|
||||
void SetURI(in nsIURI aURI);
|
||||
/** Referrer URI */
|
||||
attribute nsIURI referrerURI;
|
||||
|
||||
/** Referrer URI */
|
||||
attribute nsIURI referrerURI;
|
||||
/** Content viewer, for fast restoration of presentation */
|
||||
attribute nsIContentViewer contentViewer;
|
||||
|
||||
/** DOM Document */
|
||||
attribute nsIDOMDocument document;
|
||||
/** Whether the content viewer is marked "sticky" */
|
||||
attribute boolean sticky;
|
||||
|
||||
/** Title for the document */
|
||||
void SetTitle(in wstring aTitle);
|
||||
/** Saved state of the global window object */
|
||||
attribute nsISupports windowState;
|
||||
|
||||
/** Post Data for the document */
|
||||
attribute nsIInputStream postData;
|
||||
/**
|
||||
* 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 nsRect bounds);
|
||||
[noscript] void setViewerBounds([const] in nsRect bounds);
|
||||
|
||||
/** LayoutHistoryState for scroll position and form values */
|
||||
attribute nsILayoutHistoryState layoutHistoryState;
|
||||
/**
|
||||
* Saved child docshells corresponding to contentViewer. There are weak
|
||||
* references since it's assumed that the content viewer's document has
|
||||
* an owning reference to the subdocument for each shell. The child shells
|
||||
* are restored as children of the parent docshell, in this order, when the
|
||||
* parent docshell restores a saved presentation.
|
||||
*/
|
||||
|
||||
/** parent of this entry */
|
||||
attribute nsISHEntry parent;
|
||||
/** Append a child shell to the end of our list. */
|
||||
void addChildShell(in nsIDocShellTreeItem shell);
|
||||
|
||||
/**
|
||||
* The loadType for this entry. This is typically loadHistory except
|
||||
* when reload is pressed, it has the appropriate reload flag
|
||||
*/
|
||||
attribute unsigned long loadType;
|
||||
/**
|
||||
* Get the child shell at |index|; returns null if |index| is out of bounds.
|
||||
*/
|
||||
nsIDocShellTreeItem childShellAt(in long index);
|
||||
|
||||
/**
|
||||
* An ID to help identify this entry from others during
|
||||
* subframe navigation
|
||||
*/
|
||||
attribute unsigned long ID;
|
||||
/**
|
||||
* Clear the child shell list.
|
||||
*/
|
||||
void clearChildShells();
|
||||
|
||||
/**
|
||||
* pageIdentifier is an integer that should be the same for two entries
|
||||
* attached to the same docshell only if the two entries are entries for the
|
||||
* same page in the sense that one could go from the state represented by one
|
||||
* to the state represented by the other simply by scrolling (so the entries
|
||||
* are separated by an anchor traversal or a subframe navigation in some other
|
||||
* frame).
|
||||
*/
|
||||
attribute unsigned long pageIdentifier;
|
||||
/** Saved security state for the content viewer */
|
||||
attribute nsISupports securityState;
|
||||
|
||||
/** attribute to set and get the cache key for the entry */
|
||||
attribute nsISupports cacheKey;
|
||||
/** Saved refresh URI list for the content viewer */
|
||||
attribute nsISupportsArray refreshURIList;
|
||||
|
||||
/** attribute to indicate whether layoutHistoryState should be saved */
|
||||
attribute boolean saveLayoutStateFlag;
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/** attribute to indicate whether the page is already expired in cache */
|
||||
attribute boolean expirationStatus;
|
||||
/** Title for the document */
|
||||
void setTitle(in AString aTitle);
|
||||
|
||||
/** attribute to indicate the content-type of the document that this
|
||||
is a session history entry for */
|
||||
attribute ACString contentType;
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
* pageIdentifier is an integer that should be the same for two entries
|
||||
* attached to the same docshell only if the two entries are entries for
|
||||
* the same page in the sense that one could go from the state represented
|
||||
* by one to the state represented by the other simply by scrolling (so the
|
||||
* entries are separated by an anchor traversal or a subframe navigation in
|
||||
* some other frame).
|
||||
*/
|
||||
attribute unsigned long pageIdentifier;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Set/Get scrollers' positon in anchored pages */
|
||||
void setScrollPosition(in PRInt32 x, in PRInt32 y);
|
||||
void getScrollPosition(out PRInt32 x, out PRInt32 y);
|
||||
/** 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 */
|
||||
void create(in nsIURI aURI, in wstring aTitle, in nsIDOMDocument aDocument,
|
||||
in nsIInputStream aInputStream, in nsILayoutHistoryState aHistoryLayoutState,
|
||||
in nsISupports aCacheKey, in ACString aContentType);
|
||||
|
||||
nsISHEntry clone();
|
||||
|
||||
/** Attribute that indicates if this entry is for a subframe navigation */
|
||||
void SetIsSubFrame(in boolean aFlag);
|
||||
/** Additional ways to create an entry */
|
||||
void create(in nsIURI URI, in AString title,
|
||||
in nsIInputStream inputStream,
|
||||
in nsILayoutHistoryState layoutHistoryState,
|
||||
in nsISupports cacheKey, in ACString contentType);
|
||||
|
||||
nsISHEntry clone();
|
||||
|
||||
/** Attribute that indicates if this entry is for a subframe navigation */
|
||||
void setIsSubFrame(in boolean aFlag);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ interface nsIDocShell;
|
|||
|
||||
%{C++
|
||||
#define NS_SHISTORY_INTERNAL_CID \
|
||||
{0xdd335422, 0xb8b8, 0x11d3, {0xbd, 0xc8, 0x00, 0x50, 0x04, 0x0a, 0x9b, 0x44}}
|
||||
{0x5b4cba4c, 0xbf67, 0x499a, {0xae, 0x2c, 0x3f, 0x76, 0x65, 0x6f, 0x4a, 0x4e}}
|
||||
|
||||
#define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1"
|
||||
%}
|
||||
|
@ -90,4 +90,11 @@ interface nsISHistoryInternal: nsISupports
|
|||
*/
|
||||
readonly attribute nsISHistoryListener listener;
|
||||
|
||||
/**
|
||||
* Evict content viewers until the number of content viewers is no more than
|
||||
* browser.sessionhistory.max_viewers. This is done automatically by
|
||||
* updateIndex(), but should be called explicitly if a new history entry
|
||||
* is added and later has a content viewer set.
|
||||
*/
|
||||
void evictContentViewers();
|
||||
};
|
||||
|
|
|
@ -55,6 +55,7 @@ REQUIRES = xpcom \
|
|||
layout \
|
||||
docshell \
|
||||
pref \
|
||||
gfx \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsSHEntry.cpp \
|
||||
|
|
|
@ -37,11 +37,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef DEBUG_bryner
|
||||
#define DEBUG_PAGE_CACHE
|
||||
#endif
|
||||
|
||||
// Local Includes
|
||||
#include "nsSHEntry.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
|
||||
static PRUint32 gEntryID = 0;
|
||||
|
||||
|
@ -58,7 +63,9 @@ nsSHEntry::nsSHEntry()
|
|||
, mIsFrameNavigation(PR_FALSE)
|
||||
, mSaveLayoutState(PR_TRUE)
|
||||
, mExpired(PR_FALSE)
|
||||
, mSticky(PR_TRUE)
|
||||
, mParent(nsnull)
|
||||
, mViewerBounds(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -77,12 +84,21 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
|||
, mIsFrameNavigation(other.mIsFrameNavigation)
|
||||
, mSaveLayoutState(other.mSaveLayoutState)
|
||||
, mExpired(other.mExpired)
|
||||
, mSticky(PR_TRUE)
|
||||
// XXX why not copy mContentType?
|
||||
, mCacheKey(other.mCacheKey)
|
||||
, mParent(other.mParent)
|
||||
, mViewerBounds(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
nsSHEntry::~nsSHEntry()
|
||||
{
|
||||
mChildren.Clear();
|
||||
if (mContentViewer)
|
||||
mContentViewer->Destroy();
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsISupports
|
||||
//*****************************************************************************
|
||||
|
@ -133,19 +149,35 @@ NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::SetDocument(nsIDOMDocument* aDocument)
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
|
||||
{
|
||||
mDocument = aDocument;
|
||||
mContentViewer = aViewer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::GetDocument(nsIDOMDocument** aResult)
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetContentViewer(nsIContentViewer **aResult)
|
||||
{
|
||||
*aResult = mDocument;
|
||||
*aResult = mContentViewer;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetSticky(PRBool aSticky)
|
||||
{
|
||||
mSticky = aSticky;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetSticky(PRBool *aSticky)
|
||||
{
|
||||
*aSticky = mSticky;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::GetTitle(PRUnichar** aTitle)
|
||||
{
|
||||
// Check for empty title...
|
||||
|
@ -160,7 +192,7 @@ NS_IMETHODIMP nsSHEntry::GetTitle(PRUnichar** aTitle)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSHEntry::SetTitle(const PRUnichar* aTitle)
|
||||
NS_IMETHODIMP nsSHEntry::SetTitle(const nsAString &aTitle)
|
||||
{
|
||||
mTitle = aTitle;
|
||||
return NS_OK;
|
||||
|
@ -297,14 +329,13 @@ NS_IMETHODIMP nsSHEntry::SetContentType(const nsACString& aContentType)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::Create(nsIURI * aURI, const PRUnichar * aTitle,
|
||||
nsIDOMDocument * aDOMDocument, nsIInputStream * aInputStream,
|
||||
nsILayoutHistoryState * aHistoryLayoutState,
|
||||
nsSHEntry::Create(nsIURI * aURI, const nsAString &aTitle,
|
||||
nsIInputStream * aInputStream,
|
||||
nsILayoutHistoryState * aLayoutHistoryState,
|
||||
nsISupports * aCacheKey, const nsACString& aContentType)
|
||||
{
|
||||
mURI = aURI;
|
||||
mTitle = aTitle;
|
||||
mDocument = aDOMDocument;
|
||||
mPostData = aInputStream;
|
||||
mCacheKey = aCacheKey;
|
||||
mContentType = aContentType;
|
||||
|
@ -317,9 +348,9 @@ nsSHEntry::Create(nsIURI * aURI, const PRUnichar * aTitle,
|
|||
// all subframe navigations, sets the flag to true.
|
||||
mIsFrameNavigation = PR_FALSE;
|
||||
|
||||
// By default we save HistoryLayoutState
|
||||
// By default we save LayoutHistoryState
|
||||
mSaveLayoutState = PR_TRUE;
|
||||
mLayoutHistoryState = aHistoryLayoutState;
|
||||
mLayoutHistoryState = aLayoutHistoryState;
|
||||
|
||||
//By default the page is not expired
|
||||
mExpired = PR_FALSE;
|
||||
|
@ -358,6 +389,34 @@ nsSHEntry::SetParent(nsISHEntry * aParent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetWindowState(nsISupports *aState)
|
||||
{
|
||||
mWindowState = aState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetWindowState(nsISupports **aState)
|
||||
{
|
||||
NS_IF_ADDREF(*aState = mWindowState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetViewerBounds(const nsRect &aBounds)
|
||||
{
|
||||
mViewerBounds = aBounds;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetViewerBounds(nsRect &aBounds)
|
||||
{
|
||||
aBounds = mViewerBounds;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsISHContainer
|
||||
//*****************************************************************************
|
||||
|
@ -416,3 +475,77 @@ nsSHEntry::GetChildAt(PRInt32 aIndex, nsISHEntry ** aResult)
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::AddChildShell(nsIDocShellTreeItem *aShell)
|
||||
{
|
||||
NS_ASSERTION(aShell, "Null child shell added to history entry");
|
||||
mChildShells.AppendElement(aShell);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::ChildShellAt(PRInt32 aIndex, nsIDocShellTreeItem **aShell)
|
||||
{
|
||||
NS_IF_ADDREF(*aShell =
|
||||
NS_STATIC_CAST(nsIDocShellTreeItem*,
|
||||
mChildShells.SafeElementAt(aIndex)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::ClearChildShells()
|
||||
{
|
||||
mChildShells.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetSecurityState(nsISupports **aState)
|
||||
{
|
||||
NS_IF_ADDREF(*aState = mSecurityState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetSecurityState(nsISupports *aState)
|
||||
{
|
||||
mSecurityState = aState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetRefreshURIList(nsISupportsArray **aList)
|
||||
{
|
||||
NS_IF_ADDREF(*aList = mRefreshURIList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetRefreshURIList(nsISupportsArray *aList)
|
||||
{
|
||||
mRefreshURIList = aList;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SyncPresentationState()
|
||||
{
|
||||
if (mContentViewer && mWindowState) {
|
||||
// If we have a content viewer and a window state, we should be ok.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If not, then nuke all of the presentation-related members.
|
||||
if (mContentViewer)
|
||||
mContentViewer->SetHistoryEntry(nsnull);
|
||||
|
||||
mContentViewer = nsnull;
|
||||
mSticky = PR_TRUE;
|
||||
mWindowState = nsnull;
|
||||
mViewerBounds.SetRect(0, 0, 0, 0);
|
||||
mChildShells.Clear();
|
||||
mSecurityState = nsnull;
|
||||
mRefreshURIList = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
// Interfaces needed
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsISHEntry.h"
|
||||
|
@ -54,9 +55,10 @@
|
|||
#include "nsIURI.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIHistoryEntry.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsSupportsArray.h"
|
||||
|
||||
class nsSHEntry : public nsIHistoryEntry,
|
||||
public nsISHEntry,
|
||||
class nsSHEntry : public nsISHEntry,
|
||||
public nsISHContainer
|
||||
{
|
||||
public:
|
||||
|
@ -69,11 +71,11 @@ public:
|
|||
NS_DECL_NSISHCONTAINER
|
||||
|
||||
private:
|
||||
~nsSHEntry() { mChildren.Clear(); }
|
||||
~nsSHEntry();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIContentViewer> mContentViewer;
|
||||
nsString mTitle;
|
||||
nsCOMPtr<nsIInputStream> mPostData;
|
||||
nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
|
||||
|
@ -86,9 +88,15 @@ private:
|
|||
PRPackedBool mIsFrameNavigation;
|
||||
PRPackedBool mSaveLayoutState;
|
||||
PRPackedBool mExpired;
|
||||
PRPackedBool mSticky;
|
||||
nsCString mContentType;
|
||||
nsCOMPtr<nsISupports> mCacheKey;
|
||||
nsISHEntry * mParent; // weak reference
|
||||
nsCOMPtr<nsISupports> mWindowState;
|
||||
nsRect mViewerBounds;
|
||||
nsVoidArray mChildShells;
|
||||
nsCOMPtr<nsISupports> mSecurityState;
|
||||
nsCOMPtr<nsISupportsArray> mRefreshURIList;
|
||||
};
|
||||
|
||||
#endif /* nsSHEntry_h */
|
||||
|
|
|
@ -54,9 +54,14 @@
|
|||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIContentViewer.h"
|
||||
|
||||
#define PREF_SHISTORY_SIZE "browser.sessionhistory.max_entries"
|
||||
#define PREF_SHISTORY_VIEWERS "browser.sessionhistory.max_viewers"
|
||||
|
||||
static PRInt32 gHistoryMaxSize = 50;
|
||||
static PRInt32 gHistoryMaxViewers = 0;
|
||||
|
||||
enum HistCmd{
|
||||
HIST_CMD_BACK,
|
||||
|
@ -104,11 +109,21 @@ nsSHistory::Init()
|
|||
{
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
// Session history size is only taken from the default prefs branch.
|
||||
// This means that it's only configurable on a per-application basis.
|
||||
// The goal of this is to unbreak users who have inadvertently set their
|
||||
// session history size to -1.
|
||||
nsCOMPtr<nsIPrefBranch> defaultBranch;
|
||||
prefs->GetDefaultBranch(nsnull, getter_AddRefs(defaultBranch));
|
||||
if (defaultBranch) {
|
||||
defaultBranch->GetIntPref(PREF_SHISTORY_SIZE, &gHistoryMaxSize);
|
||||
}
|
||||
|
||||
// The size of the content viewer cache does not suffer from this problem,
|
||||
// so we allow it to be overridden by user prefs.
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
if (branch)
|
||||
branch->GetIntPref(PREF_SHISTORY_VIEWERS, &gHistoryMaxViewers);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -207,6 +222,7 @@ nsSHistory::GetEntryAtIndex(PRInt32 aIndex, PRBool aModifyIndex, nsISHEntry** aR
|
|||
if (NS_SUCCEEDED(rv) && (*aResult)) {
|
||||
// Set mIndex to the requested index, if asked to do so..
|
||||
if (aModifyIndex) {
|
||||
EvictContentViewers(mIndex, aIndex);
|
||||
mIndex = aIndex;
|
||||
}
|
||||
} //entry
|
||||
|
@ -476,6 +492,14 @@ nsSHistory::GetListener(nsISHistoryListener ** aListener)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::EvictContentViewers()
|
||||
{
|
||||
// This is called after a new entry has been appended to the end of the list.
|
||||
EvictContentViewers(mIndex - 1, mIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHistory: nsIWebNavigation
|
||||
//*****************************************************************************
|
||||
|
@ -583,12 +607,63 @@ nsSHistory::Reload(PRUint32 aReloadFlags)
|
|||
return LoadEntry(mIndex, loadType, HIST_CMD_RELOAD);
|
||||
}
|
||||
|
||||
void
|
||||
nsSHistory::EvictContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex)
|
||||
{
|
||||
// To enforce the limit on cached content viewers, we need to release all
|
||||
// of the content viewers that are no longer in the "window" that now
|
||||
// ends/begins at aToIndex.
|
||||
|
||||
PRInt32 startIndex, endIndex;
|
||||
if (aToIndex > aFromIndex) { // going forward
|
||||
startIndex = PR_MAX(0, aFromIndex - gHistoryMaxViewers);
|
||||
endIndex = PR_MAX(0, aToIndex - gHistoryMaxViewers);
|
||||
} else { // going backward
|
||||
startIndex = PR_MIN(mLength - 1, aToIndex + gHistoryMaxViewers);
|
||||
endIndex = PR_MIN(mLength - 1, aFromIndex + gHistoryMaxViewers);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHTransaction> trans;
|
||||
GetTransactionAtIndex(startIndex, getter_AddRefs(trans));
|
||||
|
||||
for (PRInt32 i = startIndex; trans && i < endIndex; ++i) {
|
||||
nsCOMPtr<nsISHEntry> entry;
|
||||
trans->GetSHEntry(getter_AddRefs(entry));
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
entry->GetContentViewer(getter_AddRefs(viewer));
|
||||
if (viewer) {
|
||||
#ifdef DEBUG_PAGE_CACHE
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
entry->GetURI(getter_AddRefs(uri));
|
||||
nsCAutoString spec;
|
||||
if (uri)
|
||||
uri->GetSpec(spec);
|
||||
|
||||
printf("Evicting content viewer: %s\n", spec.get());
|
||||
#endif
|
||||
|
||||
viewer->Destroy();
|
||||
entry->SetContentViewer(nsnull);
|
||||
entry->SyncPresentationState();
|
||||
}
|
||||
|
||||
nsISHTransaction *temp = trans;
|
||||
temp->GetNext(getter_AddRefs(trans));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::UpdateIndex()
|
||||
{
|
||||
// Update the actual index with the right value.
|
||||
if (mIndex != mRequestedIndex && mRequestedIndex != -1)
|
||||
if (mIndex != mRequestedIndex && mRequestedIndex != -1) {
|
||||
// We've just finished a history navigation (back or forward), so enforce
|
||||
// the max number of content viewers.
|
||||
|
||||
EvictContentViewers(mIndex, mRequestedIndex);
|
||||
mIndex = mRequestedIndex;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ protected:
|
|||
nsresult PrintHistory();
|
||||
#endif
|
||||
|
||||
void EvictContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISHTransaction> mListRoot;
|
||||
PRInt32 mIndex;
|
||||
|
|
|
@ -305,9 +305,9 @@
|
|||
null
|
||||
</field>
|
||||
|
||||
<field name="securityUI">
|
||||
null
|
||||
</field>
|
||||
<property name="securityUI"
|
||||
onget="return this.docShell.securityUI;"
|
||||
onset="this.docShell.securityUI = val;"/>
|
||||
|
||||
<field name="userTypedClear">
|
||||
1
|
||||
|
@ -356,8 +356,8 @@
|
|||
const SECUREBROWSERUI_CONTRACTID = "@mozilla.org/secure_browser_ui;1";
|
||||
if (!this.hasAttribute("disablesecurity") &&
|
||||
SECUREBROWSERUI_CONTRACTID in Components.classes) {
|
||||
this.securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID].createInstance(Components.interfaces.nsISecureBrowserUI);
|
||||
this.securityUI.init(this.contentWindow);
|
||||
var securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID].createInstance(Components.interfaces.nsISecureBrowserUI);
|
||||
securityUI.init(this.contentWindow);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче