Bug 203960: Make bookmark groups replace existing tabs instead of appending. r=jkeiser, varga, adamlock, sr=jst, hewitt

This commit is contained in:
jaggernaut%netscape.com 2003-05-30 00:21:01 +00:00
parent 542950e60a
commit 756d8ef907
25 changed files with 563 additions and 575 deletions

View File

@ -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,

View File

@ -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)
{

View File

@ -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;

View File

@ -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);

View File

@ -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);
NS_ENSURE_SUCCESS(rv, rv);
if (!*aHistory) {
return NS_OK;
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

View File

@ -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

View File

@ -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)
return NS_OK;
nsCOMPtr<nsIPresShell> shell;
PRBool shouldSave;
GetShouldSaveLayoutState(&shouldSave);
if (!shouldSave)
return NS_OK;
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
//*****************************************************************************

View File

@ -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:

View File

@ -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;
};

View File

@ -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);
//----------------------------------------------------------------------
//----------------------------------------------------------------------

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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,11 +721,18 @@ function gotoHistoryIndex(aEvent)
var index = aEvent.target.getAttribute("index");
if (!index)
return false;
try {
getWebNavigation().gotoIndex(index);
}
catch(ex) {
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);
}
}

View File

@ -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

View File

@ -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");
}

View File

@ -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);
@ -981,20 +1046,99 @@
]]>
</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>