зеркало из https://github.com/mozilla/pjs.git
Bug 203960: Make bookmark groups replace existing tabs instead of appending. r=jkeiser, varga, adamlock, sr=jst, hewitt
This commit is contained in:
Родитель
b5da481b47
Коммит
1decc3f74c
|
@ -44,6 +44,7 @@
|
|||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIStatefulFrame.h"
|
||||
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIXPConnect;
|
||||
|
@ -243,6 +244,10 @@ public:
|
|||
return sNameSpaceManager;
|
||||
};
|
||||
|
||||
static nsresult GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aKey);
|
||||
|
||||
private:
|
||||
static nsresult GetDocumentAndPrincipal(nsIDOMNode* aNode,
|
||||
nsIDocument** aDocument,
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
@ -62,6 +65,14 @@
|
|||
#include "nsIParserService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIAttribute.h"
|
||||
#include "nsIContentList.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
|
||||
static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
||||
static NS_DEFINE_IID(kParserServiceCID, NS_PARSERSERVICE_CID);
|
||||
|
@ -1318,6 +1329,206 @@ nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
|
|||
return Substring(start, end);
|
||||
}
|
||||
|
||||
static inline void KeyAppendSep(nsACString& aKey)
|
||||
{
|
||||
if (!aKey.IsEmpty()) {
|
||||
aKey.Append('>');
|
||||
}
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(NS_ConvertUCS2toUTF8(aString));
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(aString);
|
||||
}
|
||||
|
||||
static inline void KeyAppendInt(PRInt32 aInt, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
aKey.Append(nsPrintfCString("%d", aInt));
|
||||
}
|
||||
|
||||
static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
|
||||
{
|
||||
NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
|
||||
|
||||
const char* atomString = nsnull;
|
||||
aAtom->GetUTF8String(&atomString);
|
||||
|
||||
KeyAppendString(nsDependentCString(atomString), aKey);
|
||||
}
|
||||
|
||||
static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement)
|
||||
{
|
||||
nsAutoString autocomplete;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
|
||||
return autocomplete.Equals(NS_LITERAL_STRING("off"),
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
|
||||
/*static*/ nsresult
|
||||
nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aKey)
|
||||
{
|
||||
aKey.Truncate();
|
||||
|
||||
// SpecialStateID case - e.g. scrollbars around the content window
|
||||
// The key in this case is the special state id (always < min(contentID))
|
||||
if (nsIStatefulFrame::eNoID != aID) {
|
||||
KeyAppendInt(aID, aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We must have content if we're not using a special state id
|
||||
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
|
||||
|
||||
// Don't capture state for anonymous content
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
if (!contentID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aContent));
|
||||
if (element && IsAutocompleteOff(element)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(doc));
|
||||
|
||||
PRBool generatedUniqueKey = PR_FALSE;
|
||||
|
||||
if (htmlDocument) {
|
||||
nsCOMPtr<nsIDOMHTMLDocument> domHtmlDocument(do_QueryInterface(htmlDocument));
|
||||
nsCOMPtr<nsIDOMHTMLCollection> forms;
|
||||
domHtmlDocument->GetForms(getter_AddRefs(forms));
|
||||
nsCOMPtr<nsIContentList> htmlForms(do_QueryInterface(forms));
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> formControls;
|
||||
htmlDocument->GetFormControlElements(getter_AddRefs(formControls));
|
||||
nsCOMPtr<nsIContentList> htmlFormControls(do_QueryInterface(formControls));
|
||||
|
||||
// If we have a form control and can calculate form information, use
|
||||
// that as the key - it is more reliable than contentID.
|
||||
// Important to have a unique key, and tag/type/name may not be.
|
||||
//
|
||||
// If the control has a form, the format of the key is:
|
||||
// type>IndOfFormInDoc>IndOfControlInForm>FormName>name
|
||||
// else:
|
||||
// type>IndOfControlInDoc>name
|
||||
//
|
||||
// XXX We don't need to use index if name is there
|
||||
//
|
||||
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
|
||||
if (control && htmlFormControls && htmlForms) {
|
||||
|
||||
// Append the control type
|
||||
KeyAppendInt(control->GetType(), aKey);
|
||||
|
||||
// If in a form, add form name / index of form / index in form
|
||||
PRInt32 index = -1;
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> formElement;
|
||||
control->GetForm(getter_AddRefs(formElement));
|
||||
if (formElement) {
|
||||
|
||||
if (IsAutocompleteOff(formElement)) {
|
||||
aKey.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Append the index of the form in the document
|
||||
nsCOMPtr<nsIContent> formContent(do_QueryInterface(formElement));
|
||||
htmlForms->IndexOf(formContent, index, PR_FALSE);
|
||||
if (index <= -1) {
|
||||
//
|
||||
// XXX HACK this uses some state that was dumped into the document
|
||||
// specifically to fix bug 138892. What we are trying to do is *guess*
|
||||
// which form this control's state is found in, with the highly likely
|
||||
// guess that the highest form parsed so far is the one.
|
||||
// This code should not be on trunk, only branch.
|
||||
//
|
||||
htmlDocument->GetNumFormsSynchronous(&index);
|
||||
index--;
|
||||
}
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
|
||||
// Append the index of the control in the form
|
||||
nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
|
||||
form->IndexOfControl(control, &index);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find form control index!");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the form name
|
||||
nsAutoString formName;
|
||||
formElement->GetName(formName);
|
||||
KeyAppendString(formName, aKey);
|
||||
|
||||
} else {
|
||||
|
||||
// If not in a form, add index of control in document
|
||||
// Less desirable than indexing by form info.
|
||||
|
||||
// Hash by index of control in doc (we are not in a form)
|
||||
// These are important as they are unique, and type/name may not be.
|
||||
|
||||
// We don't refresh the form control list here (passing PR_TRUE
|
||||
// for aFlush), although we really should. Forcing a flush
|
||||
// causes a signficant pageload performance hit. See bug
|
||||
// 166636. Doing this wrong means you will see the assertion
|
||||
// below being hit.
|
||||
htmlFormControls->IndexOf(aContent, index, PR_FALSE);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find content "
|
||||
"by type! See bug 139568");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the control name
|
||||
nsAutoString name;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
KeyAppendString(name, aKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (!generatedUniqueKey) {
|
||||
|
||||
// Either we didn't have a form control or we aren't in an HTML document
|
||||
// so we can't figure out form info, hash by content ID instead :(
|
||||
KeyAppendInt(contentID, aKey);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsCxPusher::Push(nsISupports *aCurrentTarget)
|
||||
{
|
||||
|
|
|
@ -1509,6 +1509,16 @@ DocumentViewerImpl::Hide(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mContainer));
|
||||
if (docShell) {
|
||||
PRBool saveLayoutState = PR_FALSE;
|
||||
docShell->GetShouldSaveLayoutState(&saveLayoutState);
|
||||
if (saveLayoutState) {
|
||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
mPresShell->Destroy();
|
||||
|
||||
mPresShell = nsnull;
|
||||
|
|
|
@ -2761,7 +2761,8 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink)
|
|||
presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
|
||||
|
||||
// set it on the new pres shell
|
||||
aPO->mPresShell->SetHistoryState(layoutState);
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aPO->mWebShell));
|
||||
docShell->SetLayoutHistoryState(layoutState);
|
||||
|
||||
// turn off animated GIFs
|
||||
if (aPO->mPresContext) {
|
||||
|
@ -2876,7 +2877,6 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink)
|
|||
} else {
|
||||
printf("View is null!\n");
|
||||
}
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aPO->mWebShell));
|
||||
if (docShell) {
|
||||
fprintf(fd, "--------------- All Views ----------------\n");
|
||||
DumpViews(docShell, fd);
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include "nsRange.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -90,6 +91,7 @@
|
|||
|
||||
#include "nsIHTMLContentContainer.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -2679,27 +2681,24 @@ nsGenericHTMLElement::GetLayoutHistoryAndKey(nsIHTMLContent* aContent,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
doc->GetShellAt(0, getter_AddRefs(presShell));
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
||||
|
||||
//
|
||||
// Get the history (don't bother with the key if the history is not there)
|
||||
//
|
||||
rv = presShell->GetHistoryState(aHistory);
|
||||
nsCOMPtr<nsISupports> container;
|
||||
doc->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
rv = docShell->GetLayoutHistoryState(aHistory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!*aHistory) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the state key
|
||||
//
|
||||
nsCOMPtr<nsIFrameManager> frameManager;
|
||||
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
NS_ENSURE_TRUE(frameManager, NS_ERROR_FAILURE);
|
||||
|
||||
rv = frameManager->GenerateStateKey(aContent, nsIStatefulFrame::eNoID, aKey);
|
||||
rv = nsContentUtils::GenerateStateKey(aContent, nsIStatefulFrame::eNoID, aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the state key is blank, this is anonymous content or for
|
||||
|
|
|
@ -150,7 +150,6 @@
|
|||
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsIFrameManager.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "plevent.h"
|
||||
|
||||
|
@ -159,8 +158,6 @@
|
|||
|
||||
#include "nsIElementObserver.h"
|
||||
|
||||
static NS_DEFINE_CID(kLayoutHistoryStateCID, NS_LAYOUT_HISTORY_STATE_CID);
|
||||
|
||||
#ifdef ALLOW_ASYNCH_STYLE_SHEETS
|
||||
const PRBool kBlockByDefault = PR_FALSE;
|
||||
#else
|
||||
|
|
|
@ -4177,19 +4177,9 @@ nsDocShell::Embed(nsIContentViewer * aContentViewer,
|
|||
break;
|
||||
}
|
||||
|
||||
if (mOSHE && updateHistory) {
|
||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||
if (!updateHistory)
|
||||
SetLayoutHistoryState(nsnull);
|
||||
|
||||
rv = mOSHE->GetLayoutHistoryState(getter_AddRefs(layoutState));
|
||||
if (layoutState) {
|
||||
// This is a SH load. That's why there is a LayoutHistoryState in mOSHE
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
rv = GetPresShell(getter_AddRefs(presShell));
|
||||
if (NS_SUCCEEDED(rv) && presShell) {
|
||||
rv = presShell->SetHistoryState(layoutState);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -6270,32 +6260,37 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType)
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::GetShouldSaveLayoutState(PRBool* aShould)
|
||||
{
|
||||
*aShould = PR_FALSE;
|
||||
if (mOSHE) {
|
||||
// Don't capture historystate and save it in history
|
||||
// if the page asked not to do so.
|
||||
mOSHE->GetSaveLayoutStateFlag(aShould);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::PersistLayoutHistoryState()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
||||
if (mOSHE) {
|
||||
PRBool saveHistoryState = PR_TRUE;
|
||||
mOSHE->GetSaveLayoutStateFlag(&saveHistoryState);
|
||||
// Don't capture historystate and save it in history
|
||||
// if the page asked not to do so.
|
||||
if (!saveHistoryState)
|
||||
PRBool shouldSave;
|
||||
GetShouldSaveLayoutState(&shouldSave);
|
||||
if (!shouldSave)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
rv = GetPresShell(getter_AddRefs(shell));
|
||||
if (NS_SUCCEEDED(rv) && shell) {
|
||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||
rv = shell->CaptureHistoryState(getter_AddRefs(layoutState),
|
||||
PR_TRUE);
|
||||
if (NS_SUCCEEDED(rv) && layoutState) {
|
||||
rv = mOSHE->SetLayoutHistoryState(layoutState);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -6933,6 +6928,22 @@ nsDocShell::GetIsExecutingOnLoadHandler(PRBool *aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState **aLayoutHistoryState)
|
||||
{
|
||||
if (mOSHE)
|
||||
mOSHE->GetLayoutHistoryState(aLayoutHistoryState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState *aLayoutHistoryState)
|
||||
{
|
||||
if (mOSHE)
|
||||
mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsRefreshTimer: Object Management
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsISHistory.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
|
@ -397,7 +398,7 @@ protected:
|
|||
nsIDocShellTreeOwner * mTreeOwner; // Weak Reference
|
||||
nsIChromeEventHandler * mChromeEventHandler; //Weak Reference
|
||||
|
||||
// Indivates that a DocShell in this "docshell tree" is printing
|
||||
// Indicates that a DocShell in this "docshell tree" is printing
|
||||
PRBool mIsPrintingOrPP;
|
||||
|
||||
public:
|
||||
|
|
|
@ -46,6 +46,7 @@ interface nsISimpleEnumerator;
|
|||
interface nsIInputStream;
|
||||
interface nsIRequest;
|
||||
interface nsISHEntry;
|
||||
interface nsILayoutHistoryState;
|
||||
|
||||
[scriptable, uuid(69E5DE00-7B8B-11d3-AF61-00A024FFC08C)]
|
||||
interface nsIDocShell : nsISupports
|
||||
|
@ -316,5 +317,9 @@ interface nsIDocShell : nsISupports
|
|||
* Returns true if the docshell is currently executing the onLoad Handler
|
||||
*/
|
||||
readonly attribute boolean isExecutingOnLoadHandler;
|
||||
|
||||
attribute nsILayoutHistoryState layoutHistoryState;
|
||||
|
||||
readonly attribute boolean shouldSaveLayoutState;
|
||||
};
|
||||
|
||||
|
|
|
@ -106,7 +106,6 @@ typedef unsigned long HMTX;
|
|||
#include "nsIPlatformCharset.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsPICommandUpdater.h"
|
||||
|
@ -157,8 +156,6 @@ static PRLogModuleInfo* gLogModule = PR_NewLogModule("webshell");
|
|||
#define WEB_TRACE(_bit,_args)
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -820,7 +820,11 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresContext* aPresCon
|
|||
{
|
||||
aPresContext->GetShell(getter_AddRefs(mPresShell));
|
||||
mPresShell->GetFrameManager(getter_AddRefs(mFrameManager));
|
||||
mPresShell->GetHistoryState(getter_AddRefs(mFrameState));
|
||||
nsCOMPtr<nsISupports> container;
|
||||
aPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell)
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(mFrameState));
|
||||
}
|
||||
|
||||
// Use the first-in-flow of a positioned inline frame in galley mode as the
|
||||
|
|
|
@ -1509,6 +1509,16 @@ DocumentViewerImpl::Hide(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(mContainer));
|
||||
if (docShell) {
|
||||
PRBool saveLayoutState = PR_FALSE;
|
||||
docShell->GetShouldSaveLayoutState(&saveLayoutState);
|
||||
if (saveLayoutState) {
|
||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
mPresShell->Destroy();
|
||||
|
||||
mPresShell = nsnull;
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIContentList.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
@ -368,10 +369,6 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
nsILayoutHistoryState* aState,
|
||||
nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);
|
||||
NS_IMETHOD GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aString);
|
||||
|
||||
// Gets and sets properties on a given frame
|
||||
NS_IMETHOD GetFrameProperty(nsIFrame* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
|
@ -415,8 +412,6 @@ private:
|
|||
UndisplayedMap* mUndisplayedMap;
|
||||
CantRenderReplacedElementEvent* mPostedEvents;
|
||||
PropertyList* mPropertyList;
|
||||
nsCOMPtr<nsIContentList> mHTMLForms;
|
||||
nsCOMPtr<nsIContentList> mHTMLFormControls;
|
||||
PRBool mIsDestroyingFrames;
|
||||
|
||||
void ReResolveStyleContext(nsIPresContext* aPresContext,
|
||||
|
@ -477,23 +472,6 @@ FrameManager::Init(nsIPresShell* aPresShell,
|
|||
mPresShell = aPresShell;
|
||||
mStyleSet = aStyleSet;
|
||||
|
||||
// Force the forms and form control content lists to be added as
|
||||
// document observers *before* us (pres shell) so they will be
|
||||
// up to date when we try to use them.
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
mPresShell->GetDocument(getter_AddRefs(document));
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(document));
|
||||
nsCOMPtr<nsIDOMHTMLDocument> domHtmlDocument(do_QueryInterface(htmlDocument));
|
||||
if (domHtmlDocument) {
|
||||
nsCOMPtr<nsIDOMHTMLCollection> forms;
|
||||
domHtmlDocument->GetForms(getter_AddRefs(forms));
|
||||
mHTMLForms = do_QueryInterface(forms);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> formControls;
|
||||
htmlDocument->GetFormControlElements(getter_AddRefs(formControls));
|
||||
mHTMLFormControls = do_QueryInterface(formControls);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2117,7 +2095,7 @@ FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext,
|
|||
rv = aFrame->GetContent(getter_AddRefs(content));
|
||||
|
||||
nsCAutoString stateKey;
|
||||
rv = GenerateStateKey(content, aID, stateKey);
|
||||
rv = nsContentUtils::GenerateStateKey(content, aID, stateKey);
|
||||
if(NS_FAILED(rv) || stateKey.IsEmpty()) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2181,7 +2159,7 @@ FrameManager::RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFram
|
|||
}
|
||||
|
||||
nsCAutoString stateKey;
|
||||
rv = GenerateStateKey(content, aID, stateKey);
|
||||
rv = nsContentUtils::GenerateStateKey(content, aID, stateKey);
|
||||
if (NS_FAILED(rv) || stateKey.IsEmpty()) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2228,196 +2206,6 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static inline void KeyAppendSep(nsACString& aKey)
|
||||
{
|
||||
if (!aKey.IsEmpty()) {
|
||||
aKey.Append('>');
|
||||
}
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(NS_ConvertUCS2toUTF8(aString));
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(aString);
|
||||
}
|
||||
|
||||
static inline void KeyAppendInt(PRInt32 aInt, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
aKey.Append(nsPrintfCString("%d", aInt));
|
||||
}
|
||||
|
||||
static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
|
||||
{
|
||||
NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
|
||||
|
||||
const char* atomString = nsnull;
|
||||
aAtom->GetUTF8String(&atomString);
|
||||
|
||||
KeyAppendString(nsDependentCString(atomString), aKey);
|
||||
}
|
||||
|
||||
static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement)
|
||||
{
|
||||
nsAutoString autocomplete;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
|
||||
ToLowerCase(autocomplete);
|
||||
return autocomplete.Equals(NS_LITERAL_STRING("off"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aKey)
|
||||
{
|
||||
aKey.Truncate();
|
||||
|
||||
// SpecialStateID case - e.g. scrollbars around the content window
|
||||
// The key in this case is the special state id (always < min(contentID))
|
||||
if (nsIStatefulFrame::eNoID != aID) {
|
||||
KeyAppendInt(aID, aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We must have content if we're not using a special state id
|
||||
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
|
||||
|
||||
// Don't capture state for anonymous content
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
if (!contentID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aContent));
|
||||
if (element && IsAutocompleteOff(element)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we have a form control and can calculate form information, use
|
||||
// that as the key - it is more reliable than contentID.
|
||||
// Important to have a unique key, and tag/type/name may not be.
|
||||
//
|
||||
// If the control has a form, the format of the key is:
|
||||
// type>IndOfFormInDoc>IndOfControlInForm>FormName>name
|
||||
// else:
|
||||
// type>IndOfControlInDoc>name
|
||||
//
|
||||
// XXX We don't need to use index if name is there
|
||||
//
|
||||
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
|
||||
PRBool generatedUniqueKey = PR_FALSE;
|
||||
if (control && mHTMLFormControls && mHTMLForms) {
|
||||
|
||||
// Append the control type
|
||||
KeyAppendInt(control->GetType(), aKey);
|
||||
|
||||
// If in a form, add form name / index of form / index in form
|
||||
PRInt32 index = -1;
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> formElement;
|
||||
control->GetForm(getter_AddRefs(formElement));
|
||||
if (formElement) {
|
||||
|
||||
if (IsAutocompleteOff(formElement)) {
|
||||
aKey.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Append the index of the form in the document
|
||||
nsCOMPtr<nsIContent> formContent(do_QueryInterface(formElement));
|
||||
mHTMLForms->IndexOf(formContent, index, PR_FALSE);
|
||||
if (index <= -1) {
|
||||
//
|
||||
// XXX HACK this uses some state that was dumped into the document
|
||||
// specifically to fix bug 138892. What we are trying to do is *guess*
|
||||
// which form this control's state is found in, with the highly likely
|
||||
// guess that the highest form parsed so far is the one.
|
||||
// This code should not be on trunk, only branch.
|
||||
//
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
formContent->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
|
||||
if (htmlDoc) {
|
||||
htmlDoc->GetNumFormsSynchronous(&index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
|
||||
// Append the index of the control in the form
|
||||
nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
|
||||
form->IndexOfControl(control, &index);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find form control index!");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the form name
|
||||
nsAutoString formName;
|
||||
formElement->GetName(formName);
|
||||
KeyAppendString(formName, aKey);
|
||||
|
||||
} else {
|
||||
|
||||
// If not in a form, add index of control in document
|
||||
// Less desirable than indexing by form info.
|
||||
|
||||
// Hash by index of control in doc (we are not in a form)
|
||||
// These are important as they are unique, and type/name may not be.
|
||||
|
||||
// We don't refresh the form control list here (passing PR_TRUE
|
||||
// for aFlush), although we really should. Forcing a flush
|
||||
// causes a signficant pageload performance hit. See bug
|
||||
// 166636. Doing this wrong means you will see the assertion
|
||||
// below being hit.
|
||||
mHTMLFormControls->IndexOf(aContent, index, PR_FALSE);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find content "
|
||||
"by type! See bug 139568");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the control name
|
||||
nsAutoString name;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
KeyAppendString(name, aKey);
|
||||
}
|
||||
|
||||
if (!generatedUniqueKey) {
|
||||
|
||||
// Either we didn't have a form control or we aren't in an HTML document
|
||||
// so we can't figure out form info, hash by content ID instead :(
|
||||
KeyAppendInt(contentID, aKey);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static PLHashNumber
|
||||
|
|
|
@ -485,8 +485,6 @@ public:
|
|||
*/
|
||||
|
||||
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage = PR_FALSE) = 0;
|
||||
NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState) = 0;
|
||||
NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState) = 0;
|
||||
|
||||
/**
|
||||
* Determine if reflow is currently locked
|
||||
|
|
|
@ -1144,8 +1144,6 @@ public:
|
|||
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue);
|
||||
|
||||
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
|
||||
NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState);
|
||||
NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState);
|
||||
|
||||
NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent,
|
||||
GeneratedContentType aType,
|
||||
|
@ -1308,7 +1306,6 @@ protected:
|
|||
nsCOMPtr<nsIStyleSet> mStyleSet;
|
||||
nsICSSStyleSheet* mPrefStyleSheet; // mStyleSet owns it but we maintaina ref, may be null
|
||||
nsIViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to
|
||||
nsWeakPtr mHistoryState; // [WEAK] session history owns this
|
||||
PRUint32 mUpdateCount;
|
||||
// normal reflow commands
|
||||
nsVoidArray mReflowCommands;
|
||||
|
@ -1661,8 +1658,6 @@ PresShell::Init(nsIDocument* aDocument,
|
|||
// before creating any frames.
|
||||
SetPreferenceStyleRules(PR_FALSE);
|
||||
|
||||
mHistoryState = nsnull;
|
||||
|
||||
nsresult result = nsComponentManager::CreateInstance(kFrameSelectionCID, nsnull,
|
||||
NS_GET_IID(nsIFrameSelection),
|
||||
getter_AddRefs(mSelection));
|
||||
|
@ -1799,9 +1794,6 @@ PresShell::Destroy()
|
|||
|
||||
mIsDestroying = PR_TRUE;
|
||||
|
||||
// Clobber weak leaks in case of re-entrancy during tear down
|
||||
mHistoryState = nsnull;
|
||||
|
||||
// We can't release all the event content in
|
||||
// mCurrentEventContentStack here since there might be code on the
|
||||
// stack that will release the event content too. Double release
|
||||
|
@ -3673,7 +3665,18 @@ PresShell::EndLoad(nsIDocument *aDocument)
|
|||
// Restore frame state for the root scroll frame
|
||||
nsIFrame* rootFrame = nsnull;
|
||||
GetRootFrame(&rootFrame);
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
if (!container)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState;
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
|
||||
|
||||
if (rootFrame && historyState) {
|
||||
nsIFrame* scrollFrame = nsnull;
|
||||
GetRootScrollFrame(mPresContext, rootFrame, &scrollFrame);
|
||||
|
@ -4709,7 +4712,17 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
|
||||
NS_PRECONDITION(nsnull != aState, "null state pointer");
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
if (!container)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState;
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
|
||||
if (!historyState) {
|
||||
// Create the document state object
|
||||
rv = NS_NewLayoutHistoryState(getter_AddRefs(historyState));
|
||||
|
@ -4719,7 +4732,7 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
return rv;
|
||||
}
|
||||
|
||||
mHistoryState = getter_AddRefs(NS_GetWeakReference(historyState));
|
||||
docShell->SetLayoutHistoryState(historyState);
|
||||
}
|
||||
|
||||
*aState = historyState;
|
||||
|
@ -4747,22 +4760,6 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::GetHistoryState(nsILayoutHistoryState** aState)
|
||||
{
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
*aState = historyState;
|
||||
NS_IF_ADDREF(*aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
|
||||
{
|
||||
mHistoryState = getter_AddRefs(NS_GetWeakReference(aLayoutHistoryState));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::GetGeneratedContentIterator(nsIContent* aContent,
|
||||
GeneratedContentType aType,
|
||||
|
|
|
@ -188,10 +188,6 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
nsILayoutHistoryState* aState,
|
||||
nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID) = 0;
|
||||
NS_IMETHOD GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aString) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Gets a property value for a given frame.
|
||||
|
|
|
@ -485,8 +485,6 @@ public:
|
|||
*/
|
||||
|
||||
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage = PR_FALSE) = 0;
|
||||
NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState) = 0;
|
||||
NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState) = 0;
|
||||
|
||||
/**
|
||||
* Determine if reflow is currently locked
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIContentList.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
@ -368,10 +369,6 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
nsILayoutHistoryState* aState,
|
||||
nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);
|
||||
NS_IMETHOD GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aString);
|
||||
|
||||
// Gets and sets properties on a given frame
|
||||
NS_IMETHOD GetFrameProperty(nsIFrame* aFrame,
|
||||
nsIAtom* aPropertyName,
|
||||
|
@ -415,8 +412,6 @@ private:
|
|||
UndisplayedMap* mUndisplayedMap;
|
||||
CantRenderReplacedElementEvent* mPostedEvents;
|
||||
PropertyList* mPropertyList;
|
||||
nsCOMPtr<nsIContentList> mHTMLForms;
|
||||
nsCOMPtr<nsIContentList> mHTMLFormControls;
|
||||
PRBool mIsDestroyingFrames;
|
||||
|
||||
void ReResolveStyleContext(nsIPresContext* aPresContext,
|
||||
|
@ -477,23 +472,6 @@ FrameManager::Init(nsIPresShell* aPresShell,
|
|||
mPresShell = aPresShell;
|
||||
mStyleSet = aStyleSet;
|
||||
|
||||
// Force the forms and form control content lists to be added as
|
||||
// document observers *before* us (pres shell) so they will be
|
||||
// up to date when we try to use them.
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
mPresShell->GetDocument(getter_AddRefs(document));
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(document));
|
||||
nsCOMPtr<nsIDOMHTMLDocument> domHtmlDocument(do_QueryInterface(htmlDocument));
|
||||
if (domHtmlDocument) {
|
||||
nsCOMPtr<nsIDOMHTMLCollection> forms;
|
||||
domHtmlDocument->GetForms(getter_AddRefs(forms));
|
||||
mHTMLForms = do_QueryInterface(forms);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> formControls;
|
||||
htmlDocument->GetFormControlElements(getter_AddRefs(formControls));
|
||||
mHTMLFormControls = do_QueryInterface(formControls);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2117,7 +2095,7 @@ FrameManager::CaptureFrameStateFor(nsIPresContext* aPresContext,
|
|||
rv = aFrame->GetContent(getter_AddRefs(content));
|
||||
|
||||
nsCAutoString stateKey;
|
||||
rv = GenerateStateKey(content, aID, stateKey);
|
||||
rv = nsContentUtils::GenerateStateKey(content, aID, stateKey);
|
||||
if(NS_FAILED(rv) || stateKey.IsEmpty()) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2181,7 +2159,7 @@ FrameManager::RestoreFrameStateFor(nsIPresContext* aPresContext, nsIFrame* aFram
|
|||
}
|
||||
|
||||
nsCAutoString stateKey;
|
||||
rv = GenerateStateKey(content, aID, stateKey);
|
||||
rv = nsContentUtils::GenerateStateKey(content, aID, stateKey);
|
||||
if (NS_FAILED(rv) || stateKey.IsEmpty()) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2228,196 +2206,6 @@ FrameManager::RestoreFrameState(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static inline void KeyAppendSep(nsACString& aKey)
|
||||
{
|
||||
if (!aKey.IsEmpty()) {
|
||||
aKey.Append('>');
|
||||
}
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(NS_ConvertUCS2toUTF8(aString));
|
||||
}
|
||||
|
||||
static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
// Could escape separator here if collisions happen. > is not a legal char
|
||||
// for a name or type attribute, so we should be safe avoiding that extra work.
|
||||
|
||||
aKey.Append(aString);
|
||||
}
|
||||
|
||||
static inline void KeyAppendInt(PRInt32 aInt, nsACString& aKey)
|
||||
{
|
||||
KeyAppendSep(aKey);
|
||||
|
||||
aKey.Append(nsPrintfCString("%d", aInt));
|
||||
}
|
||||
|
||||
static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
|
||||
{
|
||||
NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
|
||||
|
||||
const char* atomString = nsnull;
|
||||
aAtom->GetUTF8String(&atomString);
|
||||
|
||||
KeyAppendString(nsDependentCString(atomString), aKey);
|
||||
}
|
||||
|
||||
static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement)
|
||||
{
|
||||
nsAutoString autocomplete;
|
||||
aElement->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
|
||||
ToLowerCase(autocomplete);
|
||||
return autocomplete.Equals(NS_LITERAL_STRING("off"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GenerateStateKey(nsIContent* aContent,
|
||||
nsIStatefulFrame::SpecialStateID aID,
|
||||
nsACString& aKey)
|
||||
{
|
||||
aKey.Truncate();
|
||||
|
||||
// SpecialStateID case - e.g. scrollbars around the content window
|
||||
// The key in this case is the special state id (always < min(contentID))
|
||||
if (nsIStatefulFrame::eNoID != aID) {
|
||||
KeyAppendInt(aID, aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We must have content if we're not using a special state id
|
||||
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
|
||||
|
||||
// Don't capture state for anonymous content
|
||||
PRUint32 contentID;
|
||||
aContent->GetContentID(&contentID);
|
||||
if (!contentID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aContent));
|
||||
if (element && IsAutocompleteOff(element)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we have a form control and can calculate form information, use
|
||||
// that as the key - it is more reliable than contentID.
|
||||
// Important to have a unique key, and tag/type/name may not be.
|
||||
//
|
||||
// If the control has a form, the format of the key is:
|
||||
// type>IndOfFormInDoc>IndOfControlInForm>FormName>name
|
||||
// else:
|
||||
// type>IndOfControlInDoc>name
|
||||
//
|
||||
// XXX We don't need to use index if name is there
|
||||
//
|
||||
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
|
||||
PRBool generatedUniqueKey = PR_FALSE;
|
||||
if (control && mHTMLFormControls && mHTMLForms) {
|
||||
|
||||
// Append the control type
|
||||
KeyAppendInt(control->GetType(), aKey);
|
||||
|
||||
// If in a form, add form name / index of form / index in form
|
||||
PRInt32 index = -1;
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> formElement;
|
||||
control->GetForm(getter_AddRefs(formElement));
|
||||
if (formElement) {
|
||||
|
||||
if (IsAutocompleteOff(formElement)) {
|
||||
aKey.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Append the index of the form in the document
|
||||
nsCOMPtr<nsIContent> formContent(do_QueryInterface(formElement));
|
||||
mHTMLForms->IndexOf(formContent, index, PR_FALSE);
|
||||
if (index <= -1) {
|
||||
//
|
||||
// XXX HACK this uses some state that was dumped into the document
|
||||
// specifically to fix bug 138892. What we are trying to do is *guess*
|
||||
// which form this control's state is found in, with the highly likely
|
||||
// guess that the highest form parsed so far is the one.
|
||||
// This code should not be on trunk, only branch.
|
||||
//
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
formContent->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
|
||||
if (htmlDoc) {
|
||||
htmlDoc->GetNumFormsSynchronous(&index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
|
||||
// Append the index of the control in the form
|
||||
nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
|
||||
form->IndexOfControl(control, &index);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find form control index!");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the form name
|
||||
nsAutoString formName;
|
||||
formElement->GetName(formName);
|
||||
KeyAppendString(formName, aKey);
|
||||
|
||||
} else {
|
||||
|
||||
// If not in a form, add index of control in document
|
||||
// Less desirable than indexing by form info.
|
||||
|
||||
// Hash by index of control in doc (we are not in a form)
|
||||
// These are important as they are unique, and type/name may not be.
|
||||
|
||||
// We don't refresh the form control list here (passing PR_TRUE
|
||||
// for aFlush), although we really should. Forcing a flush
|
||||
// causes a signficant pageload performance hit. See bug
|
||||
// 166636. Doing this wrong means you will see the assertion
|
||||
// below being hit.
|
||||
mHTMLFormControls->IndexOf(aContent, index, PR_FALSE);
|
||||
NS_ASSERTION(index > -1,
|
||||
"nsFrameManager::GenerateStateKey didn't find content "
|
||||
"by type! See bug 139568");
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
generatedUniqueKey = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the control name
|
||||
nsAutoString name;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
KeyAppendString(name, aKey);
|
||||
}
|
||||
|
||||
if (!generatedUniqueKey) {
|
||||
|
||||
// Either we didn't have a form control or we aren't in an HTML document
|
||||
// so we can't figure out form info, hash by content ID instead :(
|
||||
KeyAppendInt(contentID, aKey);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static PLHashNumber
|
||||
|
|
|
@ -1144,8 +1144,6 @@ public:
|
|||
NS_IMETHOD DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& outValue);
|
||||
|
||||
NS_IMETHOD CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, PRBool aLeavingPage);
|
||||
NS_IMETHOD GetHistoryState(nsILayoutHistoryState** aLayoutHistoryState);
|
||||
NS_IMETHOD SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState);
|
||||
|
||||
NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent,
|
||||
GeneratedContentType aType,
|
||||
|
@ -1308,7 +1306,6 @@ protected:
|
|||
nsCOMPtr<nsIStyleSet> mStyleSet;
|
||||
nsICSSStyleSheet* mPrefStyleSheet; // mStyleSet owns it but we maintaina ref, may be null
|
||||
nsIViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to
|
||||
nsWeakPtr mHistoryState; // [WEAK] session history owns this
|
||||
PRUint32 mUpdateCount;
|
||||
// normal reflow commands
|
||||
nsVoidArray mReflowCommands;
|
||||
|
@ -1661,8 +1658,6 @@ PresShell::Init(nsIDocument* aDocument,
|
|||
// before creating any frames.
|
||||
SetPreferenceStyleRules(PR_FALSE);
|
||||
|
||||
mHistoryState = nsnull;
|
||||
|
||||
nsresult result = nsComponentManager::CreateInstance(kFrameSelectionCID, nsnull,
|
||||
NS_GET_IID(nsIFrameSelection),
|
||||
getter_AddRefs(mSelection));
|
||||
|
@ -1799,9 +1794,6 @@ PresShell::Destroy()
|
|||
|
||||
mIsDestroying = PR_TRUE;
|
||||
|
||||
// Clobber weak leaks in case of re-entrancy during tear down
|
||||
mHistoryState = nsnull;
|
||||
|
||||
// We can't release all the event content in
|
||||
// mCurrentEventContentStack here since there might be code on the
|
||||
// stack that will release the event content too. Double release
|
||||
|
@ -3673,7 +3665,18 @@ PresShell::EndLoad(nsIDocument *aDocument)
|
|||
// Restore frame state for the root scroll frame
|
||||
nsIFrame* rootFrame = nsnull;
|
||||
GetRootFrame(&rootFrame);
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
if (!container)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState;
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
|
||||
|
||||
if (rootFrame && historyState) {
|
||||
nsIFrame* scrollFrame = nsnull;
|
||||
GetRootScrollFrame(mPresContext, rootFrame, &scrollFrame);
|
||||
|
@ -4709,7 +4712,17 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
|
||||
NS_PRECONDITION(nsnull != aState, "null state pointer");
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
if (!container)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (!docShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState;
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(historyState));
|
||||
if (!historyState) {
|
||||
// Create the document state object
|
||||
rv = NS_NewLayoutHistoryState(getter_AddRefs(historyState));
|
||||
|
@ -4719,7 +4732,7 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
return rv;
|
||||
}
|
||||
|
||||
mHistoryState = getter_AddRefs(NS_GetWeakReference(historyState));
|
||||
docShell->SetLayoutHistoryState(historyState);
|
||||
}
|
||||
|
||||
*aState = historyState;
|
||||
|
@ -4747,22 +4760,6 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPa
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::GetHistoryState(nsILayoutHistoryState** aState)
|
||||
{
|
||||
nsCOMPtr<nsILayoutHistoryState> historyState = do_QueryReferent(mHistoryState);
|
||||
*aState = historyState;
|
||||
NS_IF_ADDREF(*aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
|
||||
{
|
||||
mHistoryState = getter_AddRefs(NS_GetWeakReference(aLayoutHistoryState));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::GetGeneratedContentIterator(nsIContent* aContent,
|
||||
GeneratedContentType aType,
|
||||
|
|
|
@ -820,7 +820,11 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresContext* aPresCon
|
|||
{
|
||||
aPresContext->GetShell(getter_AddRefs(mPresShell));
|
||||
mPresShell->GetFrameManager(getter_AddRefs(mFrameManager));
|
||||
mPresShell->GetHistoryState(getter_AddRefs(mFrameState));
|
||||
nsCOMPtr<nsISupports> container;
|
||||
aPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell)
|
||||
docShell->GetLayoutHistoryState(getter_AddRefs(mFrameState));
|
||||
}
|
||||
|
||||
// Use the first-in-flow of a positioned inline frame in galley mode as the
|
||||
|
|
|
@ -2761,7 +2761,8 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink)
|
|||
presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
|
||||
|
||||
// set it on the new pres shell
|
||||
aPO->mPresShell->SetHistoryState(layoutState);
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aPO->mWebShell));
|
||||
docShell->SetLayoutHistoryState(layoutState);
|
||||
|
||||
// turn off animated GIFs
|
||||
if (aPO->mPresContext) {
|
||||
|
@ -2876,7 +2877,6 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink)
|
|||
} else {
|
||||
printf("View is null!\n");
|
||||
}
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aPO->mWebShell));
|
||||
if (docShell) {
|
||||
fprintf(fd, "--------------- All Views ----------------\n");
|
||||
DumpViews(docShell, fd);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const XREMOTESERVICE_CONTRACTID = "@mozilla.org/browser/xremoteservice;1";
|
||||
const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var gURLBar = null;
|
||||
var gProxyButton = null;
|
||||
var gProxyFavIcon = null;
|
||||
|
@ -277,7 +278,6 @@ function contentAreaFrameFocus()
|
|||
|
||||
function updateHomeButtonTooltip()
|
||||
{
|
||||
const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var homePage = getHomePage();
|
||||
var tooltip = document.getElementById("home-button-tooltip-inner");
|
||||
|
||||
|
@ -373,7 +373,7 @@ function UpdateBackForwardButtons()
|
|||
{
|
||||
var backBroadcaster = document.getElementById("canGoBack");
|
||||
var forwardBroadcaster = document.getElementById("canGoForward");
|
||||
var webNavigation = getWebNavigation();
|
||||
var browser = getBrowser();
|
||||
|
||||
// Avoid setting attributes on broadcasters if the value hasn't changed!
|
||||
// Remember, guys, setting attributes on elements is expensive! They
|
||||
|
@ -382,13 +382,13 @@ function UpdateBackForwardButtons()
|
|||
|
||||
var backDisabled = backBroadcaster.hasAttribute("disabled");
|
||||
var forwardDisabled = forwardBroadcaster.hasAttribute("disabled");
|
||||
if (backDisabled == webNavigation.canGoBack) {
|
||||
if (backDisabled == browser.canGoBack) {
|
||||
if (backDisabled)
|
||||
backBroadcaster.removeAttribute("disabled");
|
||||
else
|
||||
backBroadcaster.setAttribute("disabled", true);
|
||||
}
|
||||
if (forwardDisabled == webNavigation.canGoForward) {
|
||||
if (forwardDisabled == browser.canGoForward) {
|
||||
if (forwardDisabled)
|
||||
forwardBroadcaster.removeAttribute("disabled");
|
||||
else
|
||||
|
@ -721,12 +721,19 @@ function gotoHistoryIndex(aEvent)
|
|||
var index = aEvent.target.getAttribute("index");
|
||||
if (!index)
|
||||
return false;
|
||||
|
||||
if (index == "back")
|
||||
gBrowser.goBackGroup();
|
||||
else if (index == "forward")
|
||||
gBrowser.goForwardGroup();
|
||||
else {
|
||||
try {
|
||||
getWebNavigation().gotoIndex(index);
|
||||
}
|
||||
catch(ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -734,7 +741,7 @@ function gotoHistoryIndex(aEvent)
|
|||
function BrowserBack()
|
||||
{
|
||||
try {
|
||||
getWebNavigation().goBack();
|
||||
getBrowser().goBack();
|
||||
}
|
||||
catch(ex) {
|
||||
}
|
||||
|
@ -764,19 +771,41 @@ function BrowserHandleBackspace()
|
|||
function BrowserForward()
|
||||
{
|
||||
try {
|
||||
getWebNavigation().goForward();
|
||||
getBrowser().goForward();
|
||||
}
|
||||
catch(ex) {
|
||||
}
|
||||
}
|
||||
|
||||
function SetGroupHistory(popupMenu, direction)
|
||||
{
|
||||
while (popupMenu.firstChild)
|
||||
popupMenu.removeChild(popupMenu.firstChild);
|
||||
|
||||
var menuItem = document.createElementNS(XUL_NAMESPACE, "menuitem");
|
||||
var label = gNavigatorBundle.getString("tabs.historyItem");
|
||||
menuItem.setAttribute("label", label);
|
||||
menuItem.setAttribute("index", direction);
|
||||
popupMenu.appendChild(menuItem);
|
||||
}
|
||||
|
||||
function BrowserBackMenu(event)
|
||||
{
|
||||
if (gBrowser.backBrowserGroup.length != 0) {
|
||||
SetGroupHistory(event.target, "back");
|
||||
return true;
|
||||
}
|
||||
|
||||
return FillHistoryMenu(event.target, "back");
|
||||
}
|
||||
|
||||
function BrowserForwardMenu(event)
|
||||
{
|
||||
if (gBrowser.forwardBrowserGroup.length != 0) {
|
||||
SetGroupHistory(event.target, "forward");
|
||||
return true;
|
||||
}
|
||||
|
||||
return FillHistoryMenu(event.target, "forward");
|
||||
}
|
||||
|
||||
|
@ -809,8 +838,11 @@ function BrowserHome()
|
|||
if (homePage.length == 1) {
|
||||
loadURI(homePage[0]);
|
||||
} else {
|
||||
var URIs = [];
|
||||
for (var i in homePage)
|
||||
gBrowser.addTab(homePage[i]);
|
||||
URIs.push({URI: homePage[i]});
|
||||
|
||||
gBrowser.loadGroup(URIs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ showskinsdescription=true
|
|||
tabs.closeTab=Close Tab
|
||||
tabs.close=Close
|
||||
|
||||
tabs.historyItem=Group of Tabs
|
||||
|
||||
# urlbarBindings.xml
|
||||
# LOCALIZATION NOTE: This is for the location bar drop-down string:
|
||||
# "Seach " + search_engine_name + " for " + user_input
|
||||
|
|
|
@ -573,25 +573,16 @@ var BookmarksCommand = {
|
|||
var tabPanels = browser.mPanelContainer.childNodes;
|
||||
var tabCount = tabPanels.length;
|
||||
var index = 0;
|
||||
var URIs = [];
|
||||
while (containerChildren.hasMoreElements()) {
|
||||
var res = containerChildren.getNext().QueryInterface(kRDFRSCIID);
|
||||
var target = BMDS.GetTarget(res, urlArc, true);
|
||||
if (target) {
|
||||
var uri = target.QueryInterface(kRDFLITIID).Value;
|
||||
browser.addTab(uri);
|
||||
URIs.push({ URI: target.QueryInterface(kRDFLITIID).Value });
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
// If the bookmark group was completely invalid, just bail.
|
||||
if (index == 0)
|
||||
return;
|
||||
|
||||
// Select the first tab in the group if we aren't loading in the background.
|
||||
if (!PREF.getBoolPref("browser.tabs.loadInBackground")) {
|
||||
var tabs = browser.mTabContainer.childNodes;
|
||||
browser.selectedTab = tabs[tabCount];
|
||||
}
|
||||
browser.loadGroup(URIs);
|
||||
} else {
|
||||
dump("Open Group in new window: not implemented...\n");
|
||||
}
|
||||
|
|
|
@ -232,10 +232,22 @@
|
|||
p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
,
|
||||
},
|
||||
|
||||
// The first location change is gotoIndex called from mInstallSH,
|
||||
// the second one is considered a user action.
|
||||
mLocationChangeCount : 0,
|
||||
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation) {
|
||||
if (this.mLocationChangeCount > 0 ||
|
||||
aLocation.spec != "about:blank")
|
||||
++this.mLocationChangeCount;
|
||||
|
||||
if (this.mLocationChangeCount == 2) {
|
||||
this.mTabBrowser.backBrowserGroup = [];
|
||||
this.mTabBrowser.forwardBrowserGroup = [];
|
||||
}
|
||||
|
||||
if (!this.mBlank && this.mTabBrowser.mCurrentTab == this.mTab) {
|
||||
for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
|
||||
var p = this.mTabBrowser.mProgressListeners[i];
|
||||
|
@ -282,6 +294,58 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<method name="mInstallSH">
|
||||
<parameter name="aBrowser"/>
|
||||
<parameter name="aSH"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return ({
|
||||
mBrowser: aBrowser,
|
||||
mSH: aSH,
|
||||
|
||||
onProgressChange : function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
},
|
||||
|
||||
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
|
||||
if ((aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) &&
|
||||
(aStateFlags & nsIWebProgressListener.STATE_STOP)) {
|
||||
function refresh(closure) {
|
||||
closure.mBrowser.webNavigation.sessionHistory = closure.mSH;
|
||||
closure.mBrowser.webProgress.removeProgressListener(closure);
|
||||
delete closure.mBrowser._SHListener;
|
||||
closure.mSH.QueryInterface(Components.interfaces.nsIWebNavigation)
|
||||
.gotoIndex(closure.mSH.index);
|
||||
}
|
||||
setTimeout(refresh, 0, this);
|
||||
}
|
||||
},
|
||||
|
||||
onLocationChange : function(aWebProgress, aRequest, aLocation) {
|
||||
},
|
||||
|
||||
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {
|
||||
},
|
||||
|
||||
onSecurityChange : function(aWebProgress, aRequest, aState) {
|
||||
},
|
||||
|
||||
QueryInterface : function(aIID)
|
||||
{
|
||||
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
||||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
});
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="buildFavIconString">
|
||||
<parameter name="aURI"/>
|
||||
<body>
|
||||
|
@ -649,16 +713,14 @@
|
|||
<parameter name="aReferrerURI"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var blank = (aURI == "about:blank");
|
||||
|
||||
if (!this.mTabbedMode)
|
||||
this.enterTabbedMode();
|
||||
|
||||
var b = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"browser");
|
||||
var t = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"tab");
|
||||
|
||||
var blank = (aURI == "about:blank");
|
||||
|
||||
if (blank)
|
||||
t.setAttribute("label", this.mStringBundle.getString("tabs.untitled"));
|
||||
else
|
||||
|
@ -673,9 +735,12 @@
|
|||
t.setAttribute("onerror", "this.parentNode.parentNode.parentNode.parentNode.addToMissedIconCache(this.getAttribute('image')); this.removeAttribute('image');");
|
||||
this.mTabContainer.appendChild(t);
|
||||
|
||||
var b = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"browser");
|
||||
b.setAttribute("type", "content");
|
||||
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
|
||||
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
|
||||
//b.setAttribute("src", "");
|
||||
|
||||
this.mPanelContainer.appendChild(b);
|
||||
|
||||
|
@ -982,19 +1047,98 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<field name="backBrowserGroup">
|
||||
[]
|
||||
</field>
|
||||
|
||||
<field name="forwardBrowserGroup">
|
||||
[]
|
||||
</field>
|
||||
|
||||
<method name="replaceGroup">
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var oldBrowserGroup = [];
|
||||
var oldCount = this.mPanelContainer.childNodes.length;
|
||||
var newCount = aGroup.length;
|
||||
var n = Math.max(oldCount, newCount);
|
||||
for (var i = 0; i < n; ++i) {
|
||||
if (i < newCount) {
|
||||
var data = aGroup[i];
|
||||
if ("sessionHistory" in data) {
|
||||
this.addTab("about:blank", null);
|
||||
var browser = this.mPanelContainer.lastChild;
|
||||
// need to hold on to the listener so it won't go away
|
||||
// addProgressListener only has a weak pointer to it
|
||||
browser._SHListener =
|
||||
this.mInstallSH(browser, aGroup[i].sessionHistory);
|
||||
browser.webProgress.addProgressListener(browser._SHListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||
} else {
|
||||
var referrerURI = "referrerURI" in data ? data.referrerURI : null;
|
||||
this.addTab(data.URI, referrerURI);
|
||||
}
|
||||
}
|
||||
if (i < oldCount) {
|
||||
var browserData = {
|
||||
sessionHistory : this.mPanelContainer.firstChild.sessionHistory
|
||||
}
|
||||
oldBrowserGroup.push(browserData);
|
||||
this.removeTab(this.mTabContainer.firstChild);
|
||||
}
|
||||
}
|
||||
return oldBrowserGroup;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="loadGroup">
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aGroup.length == 0)
|
||||
return;
|
||||
|
||||
this.backBrowserGroup = this.replaceGroup(aGroup);
|
||||
this.forwardBrowserGroup = [];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="goBackGroup">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.forwardBrowserGroup = this.replaceGroup(this.backBrowserGroup);
|
||||
this.backBrowserGroup = [];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="goForwardGroup">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.backBrowserGroup = this.replaceGroup(this.forwardBrowserGroup);
|
||||
this.forwardBrowserGroup = [];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
|
||||
MAKE SURE TO ADD IT HERE AS WELL. -->
|
||||
<property name="canGoBack"
|
||||
onget="return this.mCurrentBrowser.canGoBack;"
|
||||
onget="return this.backBrowserGroup.length != 0 || this.mCurrentBrowser.canGoBack;"
|
||||
readonly="true"/>
|
||||
|
||||
<property name="canGoForward"
|
||||
onget="return this.mCurrentBrowser.canGoForward;"
|
||||
onget="return this.forwardBrowserGroup.length != 0 || this.mCurrentBrowser.canGoForward;"
|
||||
readonly="true"/>
|
||||
|
||||
<method name="goBack">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.backBrowserGroup.length != 0)
|
||||
return this.goBackGroup();
|
||||
|
||||
return this.mCurrentBrowser.goBack();
|
||||
]]>
|
||||
</body>
|
||||
|
@ -1003,6 +1147,9 @@
|
|||
<method name="goForward">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.forwardBrowserGroup.length != 0)
|
||||
return this.goForwardGroup();
|
||||
|
||||
return this.mCurrentBrowser.goForward();
|
||||
]]>
|
||||
</body>
|
||||
|
|
Загрузка…
Ссылка в новой задаче