bug 570341 Initial implementation of web timing specification

r=smaug sr=biesi
This commit is contained in:
Igor Bazarny
2011-06-23 12:39:48 +02:00
parent 0eba66e10c
commit c17ceb8b6d
37 changed files with 1620 additions and 28 deletions

View File

@@ -234,6 +234,8 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#include "nsXULAppAPI.h"
#include "nsDOMNavigationTiming.h"
using namespace mozilla;
// Number of documents currently loading
@@ -673,6 +675,47 @@ 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");
result = nsIDOMPerformanceNavigation::TYPE_RESERVED;
break;
}
return result;
}
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
//*****************************************************************************
@@ -695,6 +738,7 @@ nsDocShell::nsDocShell():
mMarginHeight(-1),
mItemType(typeContent),
mPreviousTransIndex(-1),
mLoadType(0),
mLoadedTransIndex(-1),
mAllowSubframes(PR_TRUE),
mAllowPlugins(PR_TRUE),
@@ -1519,8 +1563,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);
@@ -1542,6 +1594,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
//
@@ -5829,15 +5898,30 @@ 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));
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
nsCAutoString aURI;
uri->GetAsciiSpec(aURI);
// If load type is not set, this is not a 'normal' load.
// No need to collect timing.
if (mLoadType == 0) {
mTiming = nsnull;
}
else {
rv = MaybeInitTiming();
}
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
@@ -5960,6 +6044,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:
@@ -6043,7 +6134,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;
@@ -6474,6 +6568,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);
@@ -6485,6 +6586,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;
@@ -7704,6 +7809,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");
@@ -7736,9 +7847,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));
@@ -8519,6 +8627,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) {
@@ -8532,6 +8644,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