bug 570341 - Initial implementation of web timing specification

r=jduell sr=biesi
This commit is contained in:
Igor Bazarny
2011-05-23 19:19:24 -07:00
parent a38c136789
commit ae1daf4816
37 changed files with 1611 additions and 33 deletions

View File

@@ -235,6 +235,8 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#include "nsXULAppAPI.h"
#include "nsDOMNavigationTiming.h"
using namespace mozilla;
// Number of documents currently loading
@@ -674,6 +676,45 @@ DispatchPings(nsIContent *content, nsIURI *referrer)
ForEachPing(content, SendPing, &info);
}
static nsDOMPerformanceNavigationType
ConvertLoadTypeToNavigationType(PRUint32 aLoadType)
{
nsDOMPerformanceNavigationType result = nsIDOMPerformanceNavigation::TYPE_RESERVED;
switch (aLoadType) {
case LOAD_NORMAL:
case LOAD_NORMAL_EXTERNAL:
case LOAD_NORMAL_BYPASS_CACHE:
case LOAD_NORMAL_BYPASS_PROXY:
case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
case LOAD_LINK:
result = nsIDOMPerformanceNavigation::TYPE_NAVIGATE;
break;
case LOAD_HISTORY:
result = nsIDOMPerformanceNavigation::TYPE_BACK_FORWARD;
break;
case LOAD_RELOAD_NORMAL:
case LOAD_RELOAD_CHARSET_CHANGE:
case LOAD_RELOAD_BYPASS_CACHE:
case LOAD_RELOAD_BYPASS_PROXY:
case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
result = nsIDOMPerformanceNavigation::TYPE_RELOAD;
break;
case LOAD_NORMAL_REPLACE:
case LOAD_STOP_CONTENT:
case LOAD_STOP_CONTENT_AND_REPLACE:
case LOAD_REFRESH:
case LOAD_BYPASS_HISTORY:
case LOAD_ERROR_PAGE:
case LOAD_PUSHSTATE:
result = nsIDOMPerformanceNavigation::TYPE_RESERVED;
break;
default:
NS_NOTREACHED("Unexpected load type value");
}
return result;
}
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
//*****************************************************************************
@@ -1520,8 +1561,16 @@ nsDocShell::FirePageHideNotification(PRBool aIsUnload)
nsCOMPtr<nsIContentViewer> kungFuDeathGrip(mContentViewer);
mFiredUnloadEvent = PR_TRUE;
if (mTiming) {
mTiming->NotifyUnloadEventStart();
}
mContentViewer->PageHide(aIsUnload);
if (mTiming) {
mTiming->NotifyUnloadEventEnd();
}
nsAutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
PRInt32 i, n = mChildList.Count();
kids.SetCapacity(n);
@@ -1543,6 +1592,23 @@ nsDocShell::FirePageHideNotification(PRBool aIsUnload)
return NS_OK;
}
nsresult
nsDocShell::MaybeInitTiming()
{
if (mTiming) {
return NS_OK;
}
PRBool enabled;
nsresult rv = mPrefs->GetBoolPref("dom.enable_performance", &enabled);
if (NS_SUCCEEDED(rv) && enabled) {
mTiming = new nsDOMNavigationTiming();
mTiming->NotifyNavigationStart();
}
return NS_OK;
}
//
// Bug 13871: Prevent frameset spoofing
//
@@ -5824,15 +5890,22 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest,
nsresult rv;
if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
// Save timing statistics.
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
// Make sure timing is created
rv = MaybeInitTiming();
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
if (mTiming) {
mTiming->NotifyFetchStart(uri, ConvertLoadTypeToNavigationType(mLoadType));
}
nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
nsCOMPtr<nsIWebProgress> webProgress =
do_QueryInterface(GetAsSupports(this));
// Was the wyciwyg document loaded on this docshell?
if (wcwgChannel && !mLSHE && (mItemType == typeContent) && aProgress == webProgress.get()) {
nsCOMPtr<nsIURI> uri;
wcwgChannel->GetURI(getter_AddRefs(uri));
PRBool equalUri = PR_TRUE;
// Store the wyciwyg url in session history, only if it is
// being loaded fresh for the first time. We don't want
@@ -5955,6 +6028,13 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
if (!oldURI || !newURI) {
return;
}
// On session restore we get a redirect from page to itself. Don't count it.
PRBool equals = PR_FALSE;
if (mTiming &&
!(mLoadType == LOAD_HISTORY &&
NS_SUCCEEDED(newURI->Equals(oldURI, &equals)) && equals)) {
mTiming->NotifyRedirect(oldURI, newURI);
}
// Below a URI visit is saved (see AddURIVisit method doc).
// The visit chain looks something like:
@@ -6038,7 +6118,10 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
nsCOMPtr<nsIURI> url;
nsresult rv = aChannel->GetURI(getter_AddRefs(url));
if (NS_FAILED(rv)) return rv;
// Timing is picked up by the window, we don't need it anymore
mTiming = nsnull;
// clean up reload state for meta charset
if (eCharsetReloadRequested == mCharsetReloadState)
mCharsetReloadState = eCharsetReloadStopOrigional;
@@ -6467,6 +6550,13 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
// with about:blank. And also ensure we fire the unload events
// in the current document.
// Make sure timing is created. Unload gets fired first for
// document loaded from the session history.
rv = MaybeInitTiming();
if (mTiming) {
mTiming->NotifyBeforeUnload();
}
PRBool okToUnload;
rv = mContentViewer->PermitUnload(PR_FALSE, &okToUnload);
@@ -6478,6 +6568,10 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
mSavingOldViewer = aTryToSaveOldPresentation &&
CanSavePresentation(LOAD_NORMAL, nsnull, nsnull);
if (mTiming) {
mTiming->NotifyUnloadAccepted(mCurrentURI);
}
// Make sure to blow away our mLoadingURI just in case. No loads
// from inside this pagehide.
mLoadingURI = nsnull;
@@ -7697,6 +7791,12 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
nsIntRect bounds(x, y, cx, cy);
nsCOMPtr<nsIDocumentViewer> docviewer =
do_QueryInterface(mContentViewer);
if (docviewer) {
docviewer->SetNavigationTiming(mTiming);
}
if (NS_FAILED(mContentViewer->Init(widget, bounds))) {
mContentViewer = nsnull;
NS_ERROR("ContentViewer Initialization failed");
@@ -7729,9 +7829,6 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
// Stuff the bgcolor from the old pres shell into the new
// pres shell. This improves page load continuity.
nsCOMPtr<nsIDocumentViewer> docviewer =
do_QueryInterface(mContentViewer);
if (docviewer) {
nsCOMPtr<nsIPresShell> shell;
docviewer->GetPresShell(getter_AddRefs(shell));
@@ -8458,6 +8555,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
// (bug#331040)
nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
rv = MaybeInitTiming();
if (mTiming) {
mTiming->NotifyBeforeUnload();
}
// Check if the page doesn't want to be unloaded. The javascript:
// protocol handler deals with this for javascript: URLs.
if (!bIsJavascript && mContentViewer) {
@@ -8471,6 +8572,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
}
}
if (mTiming) {
mTiming->NotifyUnloadAccepted(mCurrentURI);
}
// Check for saving the presentation here, before calling Stop().
// This is necessary so that we can catch any pending requests.
// Since the new request has not been created yet, we pass null for the
@@ -11681,7 +11786,6 @@ nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
#endif
}
#ifdef DEBUG
unsigned long nsDocShell::gNumberOfDocShells = 0;
#endif