From 01f2446de3c1e20484fd0593cc3b6c15e9ce20f0 Mon Sep 17 00:00:00 2001 From: "brettw%gmail.com" Date: Mon, 6 Feb 2006 20:52:18 +0000 Subject: [PATCH] Bug 317843 r=darin, sr=bzbarsky: Better redirect tracking for global history. git-svn-id: svn://10.0.0.236/trunk@189041 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/Makefile.in | 1 + mozilla/docshell/base/nsDocShell.cpp | 61 +++++++++++------- mozilla/docshell/base/nsDocShell.h | 7 ++ mozilla/docshell/base/nsIGlobalHistory3.idl | 71 +++++++++++++++++++++ mozilla/uriloader/base/nsDocLoader.cpp | 1 + mozilla/uriloader/base/nsDocLoader.h | 23 +++++-- 6 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 mozilla/docshell/base/nsIGlobalHistory3.idl diff --git a/mozilla/docshell/base/Makefile.in b/mozilla/docshell/base/Makefile.in index 521264486d5..fc2e07b8d74 100644 --- a/mozilla/docshell/base/Makefile.in +++ b/mozilla/docshell/base/Makefile.in @@ -100,6 +100,7 @@ XPIDLSRCS = \ nsIDocShellTreeOwner.idl \ nsIDocShellHistory.idl \ nsIGlobalHistory2.idl \ + nsIGlobalHistory3.idl \ nsIMarkupDocumentViewer.idl \ nsIScrollable.idl \ nsITextScroll.idl \ diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index f3c1fb6580a..d231ca0a8e7 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -157,6 +157,7 @@ #include "nsISelectionDisplay.h" #include "nsIGlobalHistory2.h" +#include "nsIGlobalHistory3.h" #ifdef DEBUG_DOCSHELL_FOCUS #include "nsIEventStateManager.h" @@ -4753,30 +4754,9 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest, EndPageLoad(aProgress, channel, aStatus); } } - else if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_REDIRECTING)) == 0) { - // XXX Is it enough if I check just for the above 2 flags for redirection - nsCOMPtr webProgress = - do_QueryInterface(GetAsSupports(this)); - - // Is the document stop notification for this document? - if (aProgress == webProgress.get()) { - nsCOMPtr channel(do_QueryInterface(aRequest)); - if (channel) { - // Get the uri from the channel - nsCOMPtr uri; - nsCOMPtr referrer; - channel->GetURI(getter_AddRefs(uri)); - // Get the referrer uri from the channel - nsCOMPtr httpchannel(do_QueryInterface(aRequest)); - if (httpchannel) - httpchannel->GetReferrer(getter_AddRefs(referrer)); - // Add the original url to global History so that - // visited url color changes happen. - if (uri) - AddToGlobalHistory(uri, PR_TRUE, referrer); - } // channel - } // aProgress - } + // note that redirect state changes will go through here as well, but it + // is better to handle those in OnRedirectStateChange where more + // information is available. return NS_OK; } @@ -4788,6 +4768,39 @@ nsDocShell::OnLocationChange(nsIWebProgress * aProgress, return NS_OK; } +void +nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel, + nsIChannel* aNewChannel, + PRUint32 aRedirectFlags, + PRUint32 aStateFlags) +{ + NS_ASSERTION(aStateFlags & STATE_REDIRECTING, + "Calling OnRedirectStateChange when there is no redirect"); + if (!(aStateFlags & STATE_IS_DOCUMENT)) + return; // not a toplevel document + + nsCOMPtr history3(do_QueryInterface(mGlobalHistory)); + if (history3) { + // notify global history of this redirect + history3->AddToplevelRedirect(aOldChannel, aNewChannel, + aRedirectFlags); + } else { + // when there is no GlobalHistory3, we fall back to GlobalHistory2. + // Just notify that the redirecting page was a redirect so it will + // be link colored but not visible. + nsCOMPtr oldURI; + aOldChannel->GetURI(getter_AddRefs(oldURI)); + if (! oldURI) + return; // nothing to tell anybody about + + nsCOMPtr httpchannel(do_QueryInterface(aOldChannel)); + nsCOMPtr referrer; + if (httpchannel) + httpchannel->GetReferrer(getter_AddRefs(referrer)); + AddToGlobalHistory(oldURI, PR_TRUE, referrer); + } +} + NS_IMETHODIMP nsDocShell::OnStatusChange(nsIWebProgress * aWebProgress, nsIRequest * aRequest, diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index 2f171c98010..1c831d5d98b 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -395,6 +395,13 @@ protected: WalkHistoryEntriesFunc aCallback, void *aData); + // overridden from nsDocLoader, this provides more information than the + // normal OnStateChange with flags STATE_REDIRECTING + virtual void OnRedirectStateChange(nsIChannel* aOldChannel, + nsIChannel* aNewChannel, + PRUint32 aRedirectFlags, + PRUint32 aStateFlags); + // Global History nsresult AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect, nsIURI * aReferrer); diff --git a/mozilla/docshell/base/nsIGlobalHistory3.idl b/mozilla/docshell/base/nsIGlobalHistory3.idl new file mode 100644 index 00000000000..0b1e094364d --- /dev/null +++ b/mozilla/docshell/base/nsIGlobalHistory3.idl @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla gecko engine. + * + * The Initial Developer of the Original Code is + * Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brett Wilson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIGlobalHistory2.idl" +interface nsIChannel; + +/** + * Provides information about global history to gecko, extending GlobalHistory2 + */ +[scriptable, uuid(40e9613e-1742-4b4d-a858-053e6237d04d)] +interface nsIGlobalHistory3 : nsIGlobalHistory2 +{ + /** + * Notifies the history system that the page loading via aOldChannel + * redirected to aNewChannel. Implementations should generally add the URI for + * aOldChannel to history for link coloring, but are advised not to expose it + * in the history user interface. This function is preferred if + * nsIGlobalHistory3 is available. Otherwise, nsIGlobalHistory2.addURI should + * be called with redirect=true. + * + * This function is preferred to nsIGlobalHistory2.addURI because it provides + * more information (including the redirect destination, channels involved, + * and redirect flags) to the history implementation. + * + * For implementors of nsIGlobalHistory3: The history implementation is + * responsible for sending NS_LINK_VISITED_EVENT_TOPIC to observers for + * redirect pages. This will be sent by the docshell for all non-redirect + * pages (see nsDocShell::AddToGlobalHistory). + * + * This function takes the same arguments as + * nsIChannelEventSink::OnChannelRedirect + */ + void addToplevelRedirect(in nsIChannel aOldChannel, in nsIChannel aNewChannel, + in PRInt32 aFlags); +}; diff --git a/mozilla/uriloader/base/nsDocLoader.cpp b/mozilla/uriloader/base/nsDocLoader.cpp index 4732042ac9f..e7d7fd9c973 100644 --- a/mozilla/uriloader/base/nsDocLoader.cpp +++ b/mozilla/uriloader/base/nsDocLoader.cpp @@ -1432,6 +1432,7 @@ NS_IMETHODIMP nsDocLoader::OnChannelRedirect(nsIChannel *aOldChannel, #endif /* DEBUG */ } + OnRedirectStateChange(aOldChannel, aNewChannel, aFlags, stateFlags); FireOnStateChange(this, aOldChannel, stateFlags, NS_OK); } diff --git a/mozilla/uriloader/base/nsDocLoader.h b/mozilla/uriloader/base/nsDocLoader.h index a2dcb45ce88..92a3fa793a6 100644 --- a/mozilla/uriloader/base/nsDocLoader.h +++ b/mozilla/uriloader/base/nsDocLoader.h @@ -68,12 +68,12 @@ struct nsListenerInfo; * nsDocLoader implementation... ****************************************************************************/ -#define NS_THIS_DOCLOADER_IMPL_CID \ - { /* 2f7f940d-d67e-40bc-b1ba-8c46de2b4cec */ \ - 0x2f7f940d, \ - 0xd67e, \ - 0x40bc, \ - {0xb1, 0xba, 0x8c, 0x46, 0xde, 0x2b, 0x4c, 0xec} \ +#define NS_THIS_DOCLOADER_IMPL_CID \ + { /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */ \ + 0xb4ec8387, \ + 0x98aa, \ + 0x4c08, \ + {0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \ } class nsDocLoader : public nsIDocumentLoader, @@ -173,6 +173,17 @@ protected: nsIRequest* aRequest, nsIURI *aUri); + // this function is overridden by the docshell, it is provided so that we + // can pass more information about redirect state (the normal OnStateChange + // doesn't get the new channel). + // @param aRedirectFlags The flags being sent to OnStateChange that + // indicate the type of redirect. + // @param aStateFlags The channel flags normally sent to OnStateChange. + virtual void OnRedirectStateChange(nsIChannel* aOldChannel, + nsIChannel* aNewChannel, + PRUint32 aRedirectFlags, + PRUint32 aStateFlags) {} + void doStartDocumentLoad(); void doStartURLLoad(nsIRequest *request); void doStopURLLoad(nsIRequest *request, nsresult aStatus);