/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Mozilla browser. * * The Initial Developer of the Original Code is Netscape * Communications, Inc. Portions created by Netscape are * Copyright (C) 1999, Mozilla. All Rights Reserved. * * Contributor(s): * Radha Kulkarni */ // Local Includes #include "nsSHEntry.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" #include "nsIDocShellLoadInfo.h" PRUint32 gEntryID=0; //***************************************************************************** //*** nsSHEntry: Object Management //***************************************************************************** nsSHEntry::nsSHEntry() { mParent = nsnull; mID = gEntryID++; mSaveLayoutState = PR_TRUE; } nsSHEntry::~nsSHEntry() { mChildren.Clear(); } //***************************************************************************** // nsSHEntry: nsISupports //***************************************************************************** NS_IMPL_ADDREF(nsSHEntry) NS_IMPL_RELEASE(nsSHEntry) NS_INTERFACE_MAP_BEGIN(nsSHEntry) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISHEntry) NS_INTERFACE_MAP_ENTRY(nsISHContainer) NS_INTERFACE_MAP_ENTRY(nsISHEntry) NS_INTERFACE_MAP_ENTRY(nsIHistoryEntry) NS_INTERFACE_MAP_END //***************************************************************************** // nsSHEntry: nsISHEntry //***************************************************************************** NS_IMETHODIMP nsSHEntry::SetScrollPosition(PRInt32 x, PRInt32 y) { mScrollPositionX = x; mScrollPositionY = y; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetScrollPosition(PRInt32 *x, PRInt32 *y) { if (x && y) { *x = mScrollPositionX; *y = mScrollPositionY; } return NS_OK; } NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** aURI) { NS_ENSURE_ARG_POINTER(aURI); *aURI = mURI; NS_IF_ADDREF(*aURI); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI) { mURI = aURI; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI) { NS_ENSURE_ARG_POINTER(aReferrerURI); *aReferrerURI = mReferrerURI; NS_IF_ADDREF(*aReferrerURI); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI) { mReferrerURI = aReferrerURI; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetDocument(nsIDOMDocument* aDocument) { mDocument = aDocument; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetDocument(nsIDOMDocument** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mDocument; NS_IF_ADDREF(*aResult); return NS_OK; } NS_IMETHODIMP nsSHEntry::GetTitle(PRUnichar** aTitle) { NS_ENSURE_ARG_POINTER(aTitle); // Check for empty title... if ( mTitle.IsEmpty() && mURI ) { // Default title is the URL. nsCAutoString spec; if ( NS_SUCCEEDED( mURI->GetSpec( spec ) ) ) { mTitle = NS_ConvertUTF8toUCS2( spec ); } } *aTitle = ToNewUnicode(mTitle); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetTitle(const PRUnichar* aTitle) { mTitle = aTitle; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetPostData(nsIInputStream** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mPostData; NS_IF_ADDREF(*aResult); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetPostData(nsIInputStream* aPostData) { mPostData = aPostData; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mLayoutHistoryState; NS_IF_ADDREF(*aResult); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState) { NS_ENSURE_STATE(mSaveLayoutState || !aState); mLayoutHistoryState = aState; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetLoadType(PRUint32 * aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mLoadType; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetLoadType(PRUint32 aLoadType) { mLoadType = aLoadType; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetID(PRUint32 * aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mID; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetID(PRUint32 aID) { mID = aID; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetIsSubFrame(PRBool * aFlag) { NS_ENSURE_ARG_POINTER(aFlag); *aFlag = mIsFrameNavigation; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetIsSubFrame(PRBool aFlag) { mIsFrameNavigation = aFlag; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetCacheKey(nsISupports** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mCacheKey; NS_IF_ADDREF(*aResult); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetCacheKey(nsISupports* aCacheKey) { mCacheKey = aCacheKey; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetSaveLayoutStateFlag(PRBool * aFlag) { NS_ENSURE_ARG_POINTER(aFlag); *aFlag = mSaveLayoutState; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetSaveLayoutStateFlag(PRBool aFlag) { mSaveLayoutState = aFlag; // if we are not allowed to hold layout history state, then make sure // that we are not holding it! if (!mSaveLayoutState) mLayoutHistoryState = nsnull; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetExpirationStatus(PRBool * aFlag) { NS_ENSURE_ARG_POINTER(aFlag); *aFlag = mExpired; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetExpirationStatus(PRBool aFlag) { mExpired = aFlag; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetContentType(nsACString& aContentType) { aContentType = mContentType; return NS_OK; } NS_IMETHODIMP nsSHEntry::SetContentType(const nsACString& aContentType) { mContentType = aContentType; return NS_OK; } NS_IMETHODIMP nsSHEntry::Create(nsIURI * aURI, const PRUnichar * aTitle, nsIDOMDocument * aDOMDocument, nsIInputStream * aInputStream, nsILayoutHistoryState * aHistoryLayoutState, nsISupports * aCacheKey, const nsACString& aContentType) { SetURI(aURI); SetTitle(aTitle); SetDocument(aDOMDocument); SetPostData(aInputStream); SetCacheKey(aCacheKey); SetContentType(aContentType); // Set the LoadType by default to loadHistory during creation SetLoadType((PRInt32)nsIDocShellLoadInfo::loadHistory); // By default all entries are set false for subframe flag. // nsDocShell::CloneAndReplace() which creates entries for // all subframe navigations, sets the flag to true. SetIsSubFrame(PR_FALSE); // By default we save HistoryLayoutState SetSaveLayoutStateFlag(PR_TRUE); SetLayoutHistoryState(aHistoryLayoutState); //By default the page is not expired SetExpirationStatus(PR_FALSE); return NS_OK; } NS_IMETHODIMP nsSHEntry::Clone(nsISHEntry ** aResult) { nsresult rv; nsSHEntry *dest; dest = new nsSHEntry(); if (!dest) { return NS_ERROR_OUT_OF_MEMORY; } NS_ADDREF(dest); dest->SetURI(mURI); dest->SetReferrerURI(mReferrerURI); dest->SetPostData(mPostData); dest->SetSaveLayoutStateFlag(mSaveLayoutState); dest->SetLayoutHistoryState(mLayoutHistoryState); dest->SetTitle(mTitle.get()); dest->SetParent(mParent); dest->SetID(mID); dest->SetIsSubFrame(mIsFrameNavigation); dest->SetExpirationStatus(mExpired); dest->SetCacheKey(mCacheKey); rv = dest->QueryInterface(NS_GET_IID(nsISHEntry), (void**) aResult); NS_RELEASE(dest); return rv; } NS_IMETHODIMP nsSHEntry::GetParent(nsISHEntry ** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = mParent; NS_IF_ADDREF(*aResult); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetParent(nsISHEntry * aParent) { /* parent not Addrefed on purpose to avoid cyclic reference * Null parent is OK */ mParent = aParent; return NS_OK; } NS_IMETHODIMP nsSHEntry::GetChildCount(PRInt32 * aCount) { NS_ENSURE_ARG_POINTER(aCount); *aCount = mChildren.Count(); return NS_OK; } NS_IMETHODIMP nsSHEntry::AddChild(nsISHEntry * aChild, PRInt32 aOffset) { NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE); // // Bug 52670: Ensure children are added in order. // // Later frames in the child list may load faster and get appended // before earlier frames, causing session history to be scrambled. // By growing the list here, they are added to the right position. // // Assert that aOffset will not be so high as to grow us a lot. // NS_ASSERTION(aOffset < (mChildren.Count()+1023), "Large frames array!\n"); // This implicitly extends the array to include aOffset mChildren.ReplaceObjectAt(aChild, aOffset); return NS_OK; } NS_IMETHODIMP nsSHEntry::RemoveChild(nsISHEntry * aChild) { NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE); PRBool childRemoved = mChildren.RemoveObject(aChild); if (childRemoved) { aChild->SetParent(nsnull); } return NS_OK; } NS_IMETHODIMP nsSHEntry::GetChildAt(PRInt32 aIndex, nsISHEntry ** aResult) { NS_ENSURE_ARG_POINTER(aResult); *aResult = nsnull; if (aIndex >= 0 && aIndex < mChildren.Count()) { *aResult = mChildren[aIndex]; } NS_IF_ADDREF(*aResult); return NS_OK; }