Bug 317843 r=darin, sr=bzbarsky: Better redirect tracking for global history.
This commit is contained in:
Родитель
07a511e63f
Коммит
b3e8edec7e
|
@ -100,6 +100,7 @@ XPIDLSRCS = \
|
|||
nsIDocShellTreeOwner.idl \
|
||||
nsIDocShellHistory.idl \
|
||||
nsIGlobalHistory2.idl \
|
||||
nsIGlobalHistory3.idl \
|
||||
nsIMarkupDocumentViewer.idl \
|
||||
nsIScrollable.idl \
|
||||
nsITextScroll.idl \
|
||||
|
|
|
@ -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<nsIWebProgress> webProgress =
|
||||
do_QueryInterface(GetAsSupports(this));
|
||||
|
||||
// Is the document stop notification for this document?
|
||||
if (aProgress == webProgress.get()) {
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
|
||||
if (channel) {
|
||||
// Get the uri from the channel
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
// Get the referrer uri from the channel
|
||||
nsCOMPtr<nsIHttpChannel> 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<nsIGlobalHistory3> 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<nsIURI> oldURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
if (! oldURI)
|
||||
return; // nothing to tell anybody about
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpchannel(do_QueryInterface(aOldChannel));
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
if (httpchannel)
|
||||
httpchannel->GetReferrer(getter_AddRefs(referrer));
|
||||
AddToGlobalHistory(oldURI, PR_TRUE, referrer);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::OnStatusChange(nsIWebProgress * aWebProgress,
|
||||
nsIRequest * aRequest,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 <brettw@gmail.com>
|
||||
*
|
||||
* 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);
|
||||
};
|
|
@ -1432,6 +1432,7 @@ NS_IMETHODIMP nsDocLoader::OnChannelRedirect(nsIChannel *aOldChannel,
|
|||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
OnRedirectStateChange(aOldChannel, aNewChannel, aFlags, stateFlags);
|
||||
FireOnStateChange(this, aOldChannel, stateFlags, NS_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче