diff -r 385684ad7eed content/base/public/nsIDocument.h --- a/content/base/public/nsIDocument.h Tue Apr 05 09:19:34 2011 -0700 +++ b/content/base/public/nsIDocument.h Wed Apr 06 15:14:13 2011 +0200 @@ -104,16 +104,17 @@ class nsIDocumentObserver; class nsBindingManager; class nsIDOMNodeList; class mozAutoSubtreeModified; struct JSObject; class nsFrameLoader; class nsIBoxObject; class imgIRequest; class nsISHEntry; +class nsIDOMPerformanceTiming; namespace mozilla { namespace css { class Loader; } // namespace css namespace dom { class Link; @@ -1511,16 +1512,21 @@ public: virtual nsresult AddImage(imgIRequest* aImage) = 0; virtual nsresult RemoveImage(imgIRequest* aImage) = 0; // Makes the images on this document locked/unlocked. By default, the locking // state is unlocked/false. virtual nsresult SetImageLockingState(PRBool aLocked) = 0; virtual nsresult GetMozCurrentStateObject(nsIVariant** aResult) = 0; + + virtual nsresult GetNavigationTiming(nsIDOMPerformanceTiming** aResult) const = 0; + + virtual nsresult SetNavigationTiming(nsIDOMPerformanceTiming* aTiming) = 0; + protected: ~nsIDocument() { // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and // releasing it) happens in the nsDocument destructor. We'd prefer to // do it here but nsNodeInfoManager is a concrete class that we don't // want to expose to users of the nsIDocument API outside of Gecko. @@ -1686,16 +1692,17 @@ protected: // document. nsCOMPtr mOriginalDocument; // The bidi options for this document. What this bitfield means is // defined in nsBidiUtils.h PRUint32 mBidiOptions; nsCString mContentLanguage; + private: nsCString mContentType; protected: // The document's security info nsCOMPtr mSecurityInfo; // if this document is part of a multipart document, diff -r 385684ad7eed content/base/src/nsDocument.cpp --- a/content/base/src/nsDocument.cpp Tue Apr 05 09:19:34 2011 -0700 +++ b/content/base/src/nsDocument.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -181,16 +181,17 @@ static NS_DEFINE_CID(kDOMEventGroupCID, #include "nsEscape.h" #ifdef MOZ_MEDIA #include "nsHTMLMediaElement.h" #endif // MOZ_MEDIA #include "mozAutoDocUpdate.h" #include "nsGlobalWindow.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "nsDOMNavigationTiming.h" #ifdef MOZ_SMIL #include "nsSMILAnimationController.h" #include "imgIContainer.h" #include "nsSVGUtils.h" #endif // MOZ_SMIL #include "nsRefreshDriver.h" @@ -4155,24 +4156,32 @@ void nsDocument::DispatchContentLoadedEvents() { NS_TIME_FUNCTION; // If you add early returns from this method, make sure you're // calling UnblockOnload properly. // Unpin references to preloaded images mPreloadingImages.Clear(); + + if (mTiming) { + mTiming->NotifyDOMContentLoadedStart(nsIDocument::GetDocumentURI()); + } // Fire a DOM event notifying listeners that this document has been // loaded (excluding images and other loads initiated by this // document). nsContentUtils::DispatchTrustedEvent(this, static_cast(this), NS_LITERAL_STRING("DOMContentLoaded"), PR_TRUE, PR_TRUE); + if (mTiming) { + mTiming->NotifyDOMContentLoadedEnd(nsIDocument::GetDocumentURI()); + } + // If this document is a [i]frame, fire a DOMFrameContentLoaded // event on all parent documents notifying that the HTML (excluding // other external files such as images and stylesheets) in a frame // has finished loading. // target_frame is the [i]frame element that will be used as the // target for the event. It's the [i]frame whose content is done // loading. @@ -4221,17 +4230,17 @@ nsDocument::DispatchContentLoadedEvents( if (context) { nsEventDispatcher::Dispatch(parent, context, innerEvent, event, &status); } } } } - + parent = parent->GetParentDocument(); } while (parent); } // If the document has a manifest attribute, fire a MozApplicationManifest // event. Element* root = GetRootElement(); if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::manifest)) { @@ -7758,16 +7767,36 @@ nsDocument::CloneDocHelper(nsDocument* c clone->mBaseTarget = mBaseTarget; return NS_OK; } void nsDocument::SetReadyStateInternal(ReadyState rs) { mReadyState = rs; + if (mTiming) { + switch (rs) { + case READYSTATE_LOADING: + mTiming->NotifyDOMLoading(nsIDocument::GetDocumentURI()); + break; + case READYSTATE_INTERACTIVE: + mTiming->NotifyDOMInteractive(nsIDocument::GetDocumentURI()); + break; + case READYSTATE_COMPLETE: + mTiming->NotifyDOMComplete(nsIDocument::GetDocumentURI()); + break; + default: + NS_WARNING("Unexpected ReadyState value"); + break; + } + } + // At the time of loading start, we don't have timing object, record time. + if (READYSTATE_LOADING == rs) { + mLoadingTime = PR_Now() / PR_USEC_PER_MSEC; + } nsRefPtr plevent = new nsPLDOMEvent(this, NS_LITERAL_STRING("readystatechange"), PR_FALSE, PR_FALSE); if (plevent) { plevent->RunDOMEventWhenSafe(); } } @@ -8252,16 +8281,31 @@ nsDocument::GetMozCurrentStateObject(nsI } NS_IF_ADDREF(*aState = mCurrentStateObjectCached); return NS_OK; } nsresult +nsDocument::GetNavigationTiming(nsIDOMPerformanceTiming** aResult) const { + NS_IF_ADDREF(*aResult = mTiming); + return NS_OK; +} + +nsresult +nsDocument::SetNavigationTiming(nsIDOMPerformanceTiming* aTiming) { + mTiming = static_cast(aTiming); + if (mLoadingTime) { + mTiming->SetDOMLoading(nsIDocument::GetDocumentURI(), mLoadingTime); + } + return NS_OK; +} + +nsresult nsDocument::AddImage(imgIRequest* aImage) { NS_ENSURE_ARG_POINTER(aImage); // See if the image is already in the hashtable. If it is, get the old count. PRUint32 oldCount = 0; mImageTracker.Get(aImage, &oldCount); diff -r 385684ad7eed content/base/src/nsDocument.h --- a/content/base/src/nsDocument.h Tue Apr 05 09:19:34 2011 -0700 +++ b/content/base/src/nsDocument.h Wed Apr 06 15:14:13 2011 +0200 @@ -126,16 +126,18 @@ class nsIRadioVisitor; class nsIFormControl; struct nsRadioGroupStruct; class nsOnloadBlocker; class nsUnblockOnloadEvent; class nsChildContentList; class nsXMLEventsManager; class nsHTMLStyleSheet; class nsHTMLCSSStyleSheet; +class nsIDOMNavigationTiming; +class nsDOMNavigationTiming; /** * Right now our identifier map entries contain information for 'name' * and 'id' mappings of a given string. This is so that * nsHTMLDocument::ResolveName only has to do one hash lookup instead * of two. It's not clear whether this still matters for performance. * * We also store the document.all result list here. This is mainly so that @@ -982,16 +984,20 @@ public: virtual Element *LookupImageElement(const nsAString& aElementId); virtual NS_HIDDEN_(nsresult) AddImage(imgIRequest* aImage); virtual NS_HIDDEN_(nsresult) RemoveImage(imgIRequest* aImage); virtual NS_HIDDEN_(nsresult) SetImageLockingState(PRBool aLocked); virtual nsresult GetMozCurrentStateObject(nsIVariant** aResult); + virtual nsresult GetNavigationTiming(nsIDOMPerformanceTiming** aResult) const; + + virtual nsresult SetNavigationTiming(nsIDOMPerformanceTiming* aTiming); + protected: friend class nsNodeUtils; /** * Check that aId is not empty and log a message to the console * service if it is. * @returns PR_TRUE if aId looks correct, PR_FALSE otherwise. */ @@ -1116,16 +1122,19 @@ protected: * 2) Removals from the DOM affect the table immediately * 3) Additions to the DOM always update existing entries for names, and add * new ones for IDs. */ nsTHashtable mIdentifierMap; nsClassHashtable mRadioGroups; + // Recorded time of change to 'loading' state. + DOMTimeMilliSec mLoadingTime; + // True if the document has been detached from its content viewer. PRPackedBool mIsGoingAway:1; // True if the document is being destroyed. PRPackedBool mInDestructor:1; // True if this document has ever had an HTML or SVG element // bound to it PRPackedBool mMayHaveTitleElement:1; @@ -1174,16 +1183,17 @@ protected: // any. This can change during the lifetime of the document. nsCOMPtr<nsIApplicationCache> mApplicationCache; nsCOMPtr<nsIContent> mFirstBaseNodeWithHref; nsEventStates mDocumentState; nsEventStates mGotDocumentState; + nsRefPtr<nsDOMNavigationTiming> mTiming; private: friend class nsUnblockOnloadEvent; void PostUnblockOnloadEvent(); void DoUnblockOnload(); nsresult CheckFrameOptions(); nsresult InitCSP(); diff -r 385684ad7eed docshell/base/Makefile.in --- a/docshell/base/Makefile.in Tue Apr 05 09:19:34 2011 -0700 +++ b/docshell/base/Makefile.in Wed Apr 06 15:14:13 2011 +0200 @@ -113,10 +113,11 @@ CPPSRCS = \ # we don't want the shared lib, but we want to force the creation of a # static lib. FORCE_STATIC_LIB = 1 include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ -I$(srcdir)/../shistory/src \ + -I$(topsrcdir)/dom/base \ -I$(topsrcdir)/layout/base \ $(NULL) diff -r 385684ad7eed docshell/base/nsDocShell.cpp --- a/docshell/base/nsDocShell.cpp Tue Apr 05 09:19:34 2011 -0700 +++ b/docshell/base/nsDocShell.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -228,16 +228,18 @@ static NS_DEFINE_CID(kAppShellCID, NS_AP #include "nsContentErrors.h" #include "nsIChannelPolicy.h" #include "nsIContentSecurityPolicy.h" #ifdef MOZ_IPC #include "nsXULAppAPI.h" #endif +#include "nsDOMNavigationTiming.h" + using namespace mozilla; // Number of documents currently loading static PRInt32 gNumberOfDocumentsLoading = 0; // Global count of existing docshells. static PRInt32 gDocShellCount = 0; @@ -669,16 +671,55 @@ DispatchPings(nsIContent *content, nsIUR return; info.numPings = 0; info.referrer = 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); //***************************************************************************** //*** nsDocShell: Object Management //***************************************************************************** static PRUint64 gDocshellIDCounter = 0; @@ -1533,16 +1574,30 @@ nsDocShell::FirePageHideNotification(PRB // Now make sure our editor, if any, is detached before we go // any farther. DetachEditorFromWindow(); } return NS_OK; } +nsresult +nsDocShell::InitTiming() +{ + if (mTiming) { + return NS_OK; + } + mTiming = new nsDOMNavigationTiming(); + NS_ENSURE_TRUE(mTiming, NS_ERROR_OUT_OF_MEMORY); + + mTiming->NotifyNavigationStart(); + return NS_OK; +} + + // // Bug 13871: Prevent frameset spoofing // // This routine answers: 'Is origin's document from same domain as // target's document?' // // file: uris are considered the same domain for the purpose of // frame navigation regardless of script accessibility (bug 420425) @@ -5839,25 +5894,33 @@ nsDocShell::OnProgressChange(nsIWebProgr NS_IMETHODIMP nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest, PRUint32 aStateFlags, nsresult aStatus) { 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 = InitTiming(); + NS_ENSURE_SUCCESS(rv, rv); + 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 // multiple entries for successive loads if (mCurrentURI && NS_SUCCEEDED(uri->Equals(mCurrentURI, &equalUri)) && !equalUri) { @@ -5967,19 +6030,27 @@ nsDocShell::OnRedirectStateChange(nsICha NS_ASSERTION(aStateFlags & STATE_REDIRECTING, "Calling OnRedirectStateChange when there is no redirect"); if (!(aStateFlags & STATE_IS_DOCUMENT)) return; // not a toplevel document nsCOMPtr<nsIURI> oldURI, newURI; aOldChannel->GetURI(getter_AddRefs(oldURI)); aNewChannel->GetURI(getter_AddRefs(newURI)); + 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: // ... // Site N - 1 // => Site N // (redirect to =>) Site N + 1 (we are here!) @@ -6055,17 +6126,20 @@ nsDocShell::EndPageLoad(nsIWebProgress * nsIChannel * aChannel, nsresult aStatus) { if(!aChannel) return NS_ERROR_NULL_POINTER; 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; else mCharsetReloadState = eCharsetReloadInit; // Save a pointer to the currently-loading history entry. // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history @@ -6091,16 +6165,17 @@ nsDocShell::EndPageLoad(nsIWebProgress * // If all documents have completed their loading // favor native event dispatch priorities // over performance if (--gNumberOfDocumentsLoading == 0) { // Hint to use normal native event dispatch priorities FavorPerformanceHint(PR_FALSE, NS_EVENT_STARVATION_DELAY_HINT); } } + /* Check if the httpChannel has any cache-control related response headers, * like no-store, no-cache. If so, update SHEntry so that * when a user goes back/forward to this page, we appropriately do * form value restoration or load from server. */ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); if (!httpChannel) // HttpChannel could be hiding underneath a Multipart channel. GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); @@ -6484,27 +6559,37 @@ nsDocShell::CreateAboutBlankContentViewe nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); if (mContentViewer) { // We've got a content viewer already. Make sure the user // permits us to discard the current document and replace it // 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 = InitTiming(); + if (mTiming) { + mTiming->NotifyBeforeUnload(); + } + PRBool okToUnload; rv = mContentViewer->PermitUnload(PR_FALSE, &okToUnload); if (NS_SUCCEEDED(rv) && !okToUnload) { // The user chose not to unload the page, interrupt the load. return NS_ERROR_FAILURE; } 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; // Notify the current document that it is about to be unloaded!! // // It is important to fire the unload() notification *before* any state // is changed within the DocShell - otherwise, javascript will get the @@ -7759,16 +7844,19 @@ nsDocShell::SetupNewViewer(nsIContentVie if (docviewer) { nsCOMPtr<nsIPresShell> shell; docviewer->GetPresShell(getter_AddRefs(shell)); if (shell) { shell->SetCanvasBackground(bgcolor); } + docviewer->SetNavigationTiming(mTiming); + // Now timing is held and notified by viewer and doc, we don't need it. + // mTiming = nsnull; } // XXX: It looks like the LayoutState gets restored again in Embed() // right after the call to SetupNewViewer(...) // We don't show the mContentViewer yet, since we want to draw the old page // until we have enough of the new page to show. Just return with the new // viewer still set to hidden. @@ -8462,30 +8550,38 @@ nsDocShell::InternalLoad(nsIURI * aURI, } } // mContentViewer->PermitUnload can destroy |this| docShell, which // causes the next call of CanSavePresentation to crash. // Hold onto |this| until we return, to prevent a crash from happening. // (bug#331040) nsCOMPtr<nsIDocShell> kungFuDeathGrip(this); - + + rv = InitTiming(); + 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) { PRBool okToUnload; rv = mContentViewer->PermitUnload(PR_FALSE, &okToUnload); if (NS_SUCCEEDED(rv) && !okToUnload) { // The user chose not to unload the page, interrupt the // load. return NS_OK; } } + 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 // new request parameter. // Also pass nsnull for the document, since it doesn't affect the return // value for our purposes here. PRBool savePresentation = CanSavePresentation(aLoadType, nsnull, nsnull); @@ -11765,16 +11861,23 @@ nsDocShell::GetPrintPreview(nsIWebBrowse nsCOMPtr<nsIWebBrowserPrint> result = do_QueryInterface(print); result.forget(aPrintPreview); return NS_OK; #else return NS_ERROR_NOT_IMPLEMENTED; #endif } +NS_IMETHODIMP +nsDocShell::GetNavigationTiming(nsIDOMPerformanceTiming** aNavigationTiming) +{ + NS_IF_ADDREF(*aNavigationTiming = mTiming); + return NS_OK; +} + #ifdef DEBUG unsigned long nsDocShell::gNumberOfDocShells = 0; #endif NS_IMETHODIMP nsDocShell::GetCanExecuteScripts(PRBool *aResult) { diff -r 385684ad7eed docshell/base/nsDocShell.h --- a/docshell/base/nsDocShell.h Tue Apr 05 09:19:34 2011 -0700 +++ b/docshell/base/nsDocShell.h Wed Apr 06 15:14:13 2011 +0200 @@ -115,16 +115,17 @@ #include "nsIClipboardCommands.h" #include "nsICommandManager.h" #include "nsCRT.h" class nsDocShell; class nsIController; class OnLinkClickEvent; class nsIScrollableFrame; +class nsDOMNavigationTiming; /* load commands were moved to nsIDocShell.h */ /* load types were moved to nsDocShellLoadTypes.h */ /* internally used ViewMode types */ enum ViewMode { viewNormal = 0x0, viewSource = 0x1 @@ -680,16 +681,18 @@ protected: nsIChannel* GetCurrentDocChannel(); protected: // Override the parent setter from nsDocLoader virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); void ClearFrameHistory(nsISHEntry* aEntry); + nsresult InitTiming(); + // Event type dispatched by RestorePresentation class RestorePresentationEvent : public nsRunnable { public: NS_DECL_NSIRUNNABLE RestorePresentationEvent(nsDocShell *ds) : mDocShell(ds) {} void Revoke() { mDocShell = nsnull; } private: nsRefPtr<nsDocShell> mDocShell; @@ -833,16 +836,18 @@ protected: PRPackedBool mDynamicallyCreated; #ifdef DEBUG PRPackedBool mInEnsureScriptEnv; #endif PRUint64 mHistoryID; static nsIURIFixup *sURIFixup; + nsRefPtr<nsDOMNavigationTiming> mTiming; + #ifdef DEBUG private: // We're counting the number of |nsDocShells| to help find leaks static unsigned long gNumberOfDocShells; #endif /* DEBUG */ public: class InterfaceRequestorProxy : public nsIInterfaceRequestor { diff -r 385684ad7eed docshell/base/nsIDocShell.idl --- a/docshell/base/nsIDocShell.idl Tue Apr 05 09:19:34 2011 -0700 +++ b/docshell/base/nsIDocShell.idl Wed Apr 06 15:14:13 2011 +0200 @@ -66,16 +66,17 @@ interface nsIInputStream; interface nsIRequest; interface nsISHEntry; interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; +interface nsIDOMPerformanceTiming; [scriptable, uuid(f77271a1-0b22-4581-af6d-529125f1901d)] interface nsIDocShell : nsISupports { /** * Loads a given URI. This will give priority to loading the requested URI * in the object implementing this interface. If it can't be loaded here * however, the URL dispatcher will go through its normal process of content @@ -543,9 +544,14 @@ interface nsIDocShell : nsISupports */ attribute boolean isAppTab; /** * Create a new about:blank document and content viewer. * @param aPrincipal the principal to use for the new document. */ void createAboutBlankContentViewer(in nsIPrincipal aPrincipal); + + /** + * Time statistics been collected during last navigations. + */ + readonly attribute nsIDOMPerformanceTiming navigationTiming; }; diff -r 385684ad7eed docshell/test/Makefile.in --- a/docshell/test/Makefile.in Tue Apr 05 09:19:34 2011 -0700 +++ b/docshell/test/Makefile.in Wed Apr 06 15:14:13 2011 +0200 @@ -95,16 +95,18 @@ _TEST_FILES = \ file_bug590573_2.html \ test_bug598895.html \ test_bug634834.html \ file_bug634834.html \ test_bug637644.html \ test_framedhistoryframes.html \ test_windowedhistoryframes.html \ historyframes.html \ + test_bug570341.html \ + bug570341_recordevents.html \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) _TEST_FILES += \ test_bug511449.html \ file_bug511449.html \ $(NULL) endif diff -r 385684ad7eed docshell/test/bug570341_recordevents.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docshell/test/bug570341_recordevents.html Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,30 @@ +<html> +<head> +<script> + window._testing_start = Date.now(); + window._testing_readyStateAtStart = document.readyState; + document.addEventListener('DOMContentLoaded', + function () { + window._testing_domContentLoaded = Date.now(); + }, true); + document.addEventListener('readystatechange', function(){ + switch (document.readyState) { + case 'loading': + window._testing_domLoading = Date.now(); + break; + case 'interactive': + window._testing_domInteractive = Date.now(); + break; + case 'complete': + window._testing_domComplete = Date.now(); + break; + } + }, true); + function recordLoad() { + window._testing_load = Date.now(); + } +</script> +</head> +<body onload="recordLoad()">This document collects time +for events related to the page load progress.<div style="position: fixed; bottom: 10px; right: 10px; background-color: #f0f0f0; border: 1px solid #ccc; padding: 10px; z - index: 9999; color: red;"> <a href="https://indexloc.com/forum.php?mod=forumdisplay&fid=7"> 点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载 </a> </div></body> +</html> diff -r 385684ad7eed docshell/test/test_bug570341.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docshell/test/test_bug570341.html Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,128 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=570341 +--> +<head> + <title>Test for Bug 570341 + + + + + + +Mozilla Bug 570341 +
+ +
+

+ +
+
+
+ + diff -r 385684ad7eed dom/base/Makefile.in --- a/dom/base/Makefile.in Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/base/Makefile.in Wed Apr 06 15:14:13 2011 +0200 @@ -101,16 +101,18 @@ CPPSRCS = \ nsHistory.cpp \ nsMimeTypeArray.cpp \ nsPluginArray.cpp \ nsWindowRoot.cpp \ nsDOMClassInfo.cpp \ nsScriptNameSpaceManager.cpp \ nsDOMScriptObjectFactory.cpp \ nsQueryContentEventResult.cpp \ + nsDOMNavigationTiming.cpp \ + nsPerformance.cpp \ $(NULL) ifdef MOZ_IPC EXPORTS += \ nsContentPermissionHelper.h \ $(NULL) CPPSRCS += \ nsContentPermissionHelper.cpp \ diff -r 385684ad7eed dom/base/nsDOMClassInfo.cpp --- a/dom/base/nsDOMClassInfo.cpp Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/base/nsDOMClassInfo.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -113,16 +113,19 @@ #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" #include "nsIDOMJSWindow.h" #include "nsIDOMWindowCollection.h" #include "nsIDOMHistory.h" #include "nsIDOMMediaList.h" #include "nsIDOMChromeWindow.h" #include "nsIDOMConstructor.h" +#include "nsIDOMPerformanceTiming.h" +#include "nsIDOMPerformanceNavigation.h" +#include "nsIDOMPerformance.h" #include "nsClientRect.h" // DOM core includes #include "nsDOMError.h" #include "nsIDOMDOMException.h" #include "nsIDOMNode.h" #include "nsIDOM3Node.h" #include "nsIDOM3Attr.h" @@ -662,16 +665,22 @@ static nsDOMClassInfoData sClassInfoData DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MimeTypeArray, nsMimeTypeArraySH, ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(BarProp, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(History, nsHistorySH, ARRAY_SCRIPTABLE_FLAGS | nsIXPCScriptable::WANT_PRECREATE) + NS_DEFINE_CLASSINFO_DATA(PerformanceTiming, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(PerformanceNavigation, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(Performance, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(Screen, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH, DOM_BASE_SCRIPTABLE_FLAGS | nsIXPCScriptable::WANT_PRECREATE | nsIXPCScriptable::WANT_HASINSTANCE | nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE) NS_DEFINE_CLASSINFO_DATA(DOMConstructor, nsDOMConstructorSH, @@ -2326,16 +2335,30 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(BarProp, nsIDOMBarProp) DOM_CLASSINFO_MAP_ENTRY(nsIDOMBarProp) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(History, nsIDOMHistory) DOM_CLASSINFO_MAP_ENTRY(nsIDOMHistory) DOM_CLASSINFO_MAP_END + // if (nsGlobalWindow::HasPerformanceSupport()) { + DOM_CLASSINFO_MAP_BEGIN(PerformanceTiming, nsIDOMPerformanceTiming) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMPerformanceTiming) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(PerformanceNavigation, nsIDOMPerformanceNavigation) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMPerformanceNavigation) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(Performance, nsIDOMPerformance) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMPerformance) + DOM_CLASSINFO_MAP_END + // } + DOM_CLASSINFO_MAP_BEGIN(Screen, nsIDOMScreen) DOM_CLASSINFO_MAP_ENTRY(nsIDOMScreen) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor) DOM_CLASSINFO_MAP_END diff -r 385684ad7eed dom/base/nsDOMClassInfoClasses.h --- a/dom/base/nsDOMClassInfoClasses.h Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/base/nsDOMClassInfoClasses.h Wed Apr 06 15:14:13 2011 +0200 @@ -40,16 +40,19 @@ DOMCI_CLASS(Window) DOMCI_CLASS(Location) DOMCI_CLASS(Navigator) DOMCI_CLASS(Plugin) DOMCI_CLASS(PluginArray) DOMCI_CLASS(MimeType) DOMCI_CLASS(MimeTypeArray) DOMCI_CLASS(BarProp) DOMCI_CLASS(History) +DOMCI_CLASS(PerformanceTiming) +DOMCI_CLASS(PerformanceNavigation) +DOMCI_CLASS(Performance) DOMCI_CLASS(Screen) DOMCI_CLASS(DOMPrototype) DOMCI_CLASS(DOMConstructor) // Core classes DOMCI_CLASS(XMLDocument) DOMCI_CLASS(DocumentType) DOMCI_CLASS(DOMImplementation) diff -r 385684ad7eed dom/base/nsDOMNavigationTiming.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/base/nsDOMNavigationTiming.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,409 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (lots of improvements) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "nsDOMNavigationTiming.h" +#include "nsCOMPtr.h" +#include "nscore.h" +#include "prinrval.h" +#include "nsContentUtils.h" + +#include "nsIDOMEventTarget.h" +#include "nsIDocument.h" +#include "nsIScriptSecurityManager.h" + +nsDOMNavigationTiming::nsDOMNavigationTiming() +{ + Clear(); +} + +nsDOMNavigationTiming::~nsDOMNavigationTiming() +{ +} + +void +nsDOMNavigationTiming::Clear() +{ + mNavigationType = nsIDOMPerformanceNavigation::TYPE_RESERVED; + mNavigationStart = 0; + mFetchStart = 0; + mRedirectStart = 0; + mRedirectEnd = 0; + mUnloadAttempt = 0; + mUnloadStart = 0; + mLastUnload = 0; + mLoadEventStart = 0; + mLoadEventEnd = 0; + mDOMLoading = 0; + mDOMInteractive = 0; + mDOMContentLoadedEventStart = 0; + mDOMContentLoadedEventEnd = 0; + mDOMComplete = 0; + mRedirectCheck = NOT_CHECKED; +} + +void +nsDOMNavigationTiming::NotifyNavigationStart() +{ + mNavigationStart = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, nsDOMPerformanceNavigationType aNavigationType) +{ + mFetchStart = PR_Now() / PR_USEC_PER_MSEC; + mNavigationType = aNavigationType; + // At the unload event time we don't really know the loading uri. + // Need it for later check for unload timing access. + mLoadedURI = aURI; +} + +void +nsDOMNavigationTiming::NotifyRedirect(nsIURI* aOldURI, nsIURI* aNewURI) +{ + if (mRedirects.Count() == 0) { + mRedirectStart = mFetchStart; + } + mFetchStart = PR_Now() / PR_USEC_PER_MSEC; + mRedirectEnd = mFetchStart; + + // At the unload event time we don't really know the loading uri. + // Need it for later check for unload timing access. + mLoadedURI = aNewURI; + + mRedirects.AppendObject(aOldURI); +} + +void +nsDOMNavigationTiming::NotifyBeforeUnload() +{ + mUnloadAttempt = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI) +{ + mUnloadStart = mUnloadAttempt; + mLastUnload = PR_Now() / PR_USEC_PER_MSEC; + mUnloadedURI = aOldURI; +} + +void +nsDOMNavigationTiming::NotifyLastUnload() +{ + mLastUnload = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyLoadEventStart() +{ + mLoadEventStart = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyLoadEventEnd() +{ + mLoadEventEnd = PR_Now() / PR_USEC_PER_MSEC; +} + +PRBool +nsDOMNavigationTiming::ReportRedirects() +{ + if (mRedirectCheck == NOT_CHECKED) { + if (mRedirects.Count() == 0) { + mRedirectCheck = NO_REDIRECTS; + } else { + mRedirectCheck = CHECK_PASSED; + nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); + for (int i = mRedirects.Count() - 1; i >= 0; --i) { + nsIURI * curr = mRedirects[i]; + nsresult rv = ssm->CheckSameOriginURI(curr, mLoadedURI, PR_FALSE); + if (!NS_SUCCEEDED(rv)) { + mRedirectCheck = CHECK_FAILED; + break; + } + } + // All we need to know is in mRedirectCheck now. Clear history. + mRedirects.Clear(); + } + } + return mRedirectCheck == CHECK_PASSED; +} + +void +nsDOMNavigationTiming::SetDOMLoading(nsIURI* aURI, DOMTimeMilliSec aValue) +{ + mLoadedURI = aURI; + mDOMLoading = aValue; +} + +void +nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI) +{ + mLoadedURI = aURI; + mDOMLoading = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI) +{ + mLoadedURI = aURI; + mDOMInteractive = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI) +{ + mLoadedURI = aURI; + mDOMComplete = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI) +{ + mLoadedURI = aURI; + mDOMContentLoadedEventStart = PR_Now() / PR_USEC_PER_MSEC; +} + +void +nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI) +{ + mLoadedURI = aURI; + mDOMContentLoadedEventEnd = PR_Now() / PR_USEC_PER_MSEC; +} + + +NS_IMPL_ADDREF(nsDOMNavigationTiming) +NS_IMPL_RELEASE(nsDOMNavigationTiming) + +// QueryInterface implementation for nsDOMNavigationTiming +NS_INTERFACE_MAP_BEGIN(nsDOMNavigationTiming) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformanceNavigation) + NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceNavigation) + NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceTiming) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +nsDOMNavigationTiming::GetType( + nsDOMPerformanceNavigationType* aNavigationType) +{ + *aNavigationType = mNavigationType; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetRedirectCount(PRUint16* aRedirectCount) +{ + *aRedirectCount = 0; + if (ReportRedirects()) { + *aRedirectCount = mRedirects.Count(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetRedirectStart(DOMTimeMilliSec* aRedirectStart) +{ + *aRedirectStart = 0; + if (ReportRedirects()) { + *aRedirectStart = mRedirectStart; + } + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetRedirectEnd(DOMTimeMilliSec* aEnd) +{ + *aEnd = 0; + if (ReportRedirects()) { + *aEnd = mRedirectEnd; + } + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetNavigationStart(DOMTimeMilliSec* aNavigationStart) +{ + *aNavigationStart = mNavigationStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetUnloadEventStart(DOMTimeMilliSec* aStart) +{ + *aStart = 0; + nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); + nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, PR_FALSE); + if (NS_SUCCEEDED(rv)) { + *aStart = mUnloadStart; + } + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetUnloadEventEnd(DOMTimeMilliSec* aEnd) +{ + *aEnd = 0; + nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); + nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, PR_FALSE); + if (NS_SUCCEEDED(rv)) { + *aEnd = mLastUnload; + } + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetFetchStart(DOMTimeMilliSec* aStart) +{ + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomainLookupStart(DOMTimeMilliSec* aStart) +{ + // TODO: Implement me! + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomainLookupEnd(DOMTimeMilliSec* aEnd) +{ + // TODO: Implement me! + *aEnd = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetConnectStart(DOMTimeMilliSec* aStart) +{ + // TODO: Implement me! + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetConnectEnd(DOMTimeMilliSec* aEnd) +{ + // TODO: Implement me! + *aEnd = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetHandshakeStart(DOMTimeMilliSec* aStart) +{ + // TODO: Implement me! + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetRequestStart(DOMTimeMilliSec* aStart) +{ + // TODO: Implement me! + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetResponseStart(DOMTimeMilliSec* aStart) +{ + // TODO: Implement me! + *aStart = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetResponseEnd(DOMTimeMilliSec* aEnd) +{ + // TODO: Implement me! + *aEnd = mFetchStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomLoading(DOMTimeMilliSec* aTime) +{ + *aTime = mDOMLoading; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomInteractive(DOMTimeMilliSec* aTime) +{ + *aTime = mDOMInteractive; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomContentLoadedEventStart(DOMTimeMilliSec* aStart) +{ + *aStart = mDOMContentLoadedEventStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomContentLoadedEventEnd(DOMTimeMilliSec* aEnd) +{ + *aEnd = mDOMContentLoadedEventEnd; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetDomComplete(DOMTimeMilliSec* aTime) +{ + *aTime = mDOMComplete; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetLoadEventStart(DOMTimeMilliSec* aStart) +{ + *aStart = mLoadEventStart; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMNavigationTiming::GetLoadEventEnd(DOMTimeMilliSec* aEnd) +{ + *aEnd = mLoadEventEnd; + return NS_OK; +} + diff -r 385684ad7eed dom/base/nsDOMNavigationTiming.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/base/nsDOMNavigationTiming.h Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (lots of improvements) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +#ifndef nsDOMNavigationTiming_h___ +#define nsDOMNavigationTiming_h___ + +#include "nsIDOMPerformanceTiming.h" +#include "nsIDOMPerformanceNavigation.h" +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsCOMArray.h" + +class nsDOMNavigationTimingClock; +class nsIURI; +class nsIDocument; + +class nsDOMNavigationTiming : public nsIDOMPerformanceTiming, + public nsIDOMPerformanceNavigation +{ +public: + nsDOMNavigationTiming(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMPERFORMANCETIMING + NS_DECL_NSIDOMPERFORMANCENAVIGATION + + void NotifyNavigationStart(); + void NotifyFetchStart(nsIURI* aURI, nsDOMPerformanceNavigationType aNavigationType); + void NotifyRedirect(nsIURI* aOldURI, nsIURI* aNewURI); + void NotifyBeforeUnload(); + void NotifyUnloadAccepted(nsIURI* aOldURI); + void NotifyLastUnload(); + void NotifyLoadEventStart(); + void NotifyLoadEventEnd(); + + // Document changes state to 'loading' before connecting to timing + void SetDOMLoading(nsIURI* aURI, DOMTimeMilliSec aValue); + void NotifyDOMLoading(nsIURI* aURI); + void NotifyDOMInteractive(nsIURI* aURI); + void NotifyDOMComplete(nsIURI* aURI); + void NotifyDOMContentLoadedStart(nsIURI* aURI); + void NotifyDOMContentLoadedEnd(nsIURI* aURI); + +private: + nsDOMNavigationTiming(const nsDOMNavigationTiming &){}; + ~nsDOMNavigationTiming(); + + void Clear(); + PRBool ReportRedirects(); + + nsCOMPtr mUnloadedURI; + nsCOMPtr mLoadedURI; + nsCOMArray mRedirects; + + typedef enum { NOT_CHECKED, + CHECK_PASSED, + NO_REDIRECTS, + CHECK_FAILED} RedirectCheckState; + RedirectCheckState mRedirectCheck; + + nsDOMPerformanceNavigationType mNavigationType; + DOMTimeMilliSec mNavigationStart; + DOMTimeMilliSec mFetchStart; + DOMTimeMilliSec mRedirectStart; + DOMTimeMilliSec mRedirectEnd; + DOMTimeMilliSec mUnloadAttempt; + DOMTimeMilliSec mUnloadStart; + DOMTimeMilliSec mLastUnload; + DOMTimeMilliSec mNavigationEnd; + DOMTimeMilliSec mLoadEventStart; + DOMTimeMilliSec mLoadEventEnd; + + DOMTimeMilliSec mDOMLoading; + DOMTimeMilliSec mDOMInteractive; + DOMTimeMilliSec mDOMContentLoadedEventStart; + DOMTimeMilliSec mDOMContentLoadedEventEnd; + DOMTimeMilliSec mDOMComplete; +}; + +#endif /* nsDOMNavigationTiming_h___ */ + diff -r 385684ad7eed dom/base/nsGlobalWindow.cpp --- a/dom/base/nsGlobalWindow.cpp Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/base/nsGlobalWindow.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -49,16 +49,18 @@ #ifdef MOZ_IPC #include "base/basictypes.h" #endif // Local Includes #include "nsGlobalWindow.h" #include "nsScreen.h" #include "nsHistory.h" +#include "nsPerformance.h" +#include "nsIDOMPerformanceTiming.h" #include "nsBarProps.h" #include "nsDOMStorage.h" #include "nsDOMOfflineResourceList.h" #include "nsDOMError.h" // Helper Classes #include "nsXPIDLString.h" #include "nsJSUtils.h" @@ -1104,16 +1106,17 @@ nsGlobalWindow::CleanUp(PRBool aIgnoreMo mScrollbars = nsnull; mLocation = nsnull; mHistory = nsnull; mFrames = nsnull; mApplicationCache = nsnull; mIndexedDB = nsnull; mPendingStorageEventsObsolete = nsnull; + mPerformance = nsnull; ClearControllers(); mOpener = nsnull; // Forces Release if (mContext) { #ifdef DEBUG nsCycleCollector_DEBUG_shouldBeFreed(mContext); #endif @@ -2179,16 +2182,28 @@ nsGlobalWindow::SetNewDocument(nsIDocume // alive etc. if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) { nsCOMPtr html_doc(do_QueryInterface(mDocument)); nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject, html_doc); } + // Pick up timing from the doc shell. + if (newInnerWindow) { // && nsGlobalWindow::HasPerformanceSupport() + nsIDocShell* docShell = GetDocShell(); + if (docShell) { + nsCOMPtr timing; + docShell->GetNavigationTiming(getter_AddRefs(timing)); + if (timing) { + newInnerWindow->mPerformance = new nsPerformance(timing); + } + } + } + if (aDocument) { aDocument->SetScriptGlobalObject(newInnerWindow); } if (!aState) { if (reUseInnerWindow) { if (newInnerWindow->mDoc != aDocument) { newInnerWindow->mDocument = do_QueryInterface(aDocument); @@ -2733,17 +2748,16 @@ nsGlobalWindow::PostHandleEvent(nsEventC nsEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_LOAD); event.flags |= NS_EVENT_FLAG_CANT_BUBBLE; // Most of the time we could get a pres context to pass in here, // but not always (i.e. if this window is not shown there won't // be a pres context available). Since we're not firing a GUI // event we don't need a pres context anyway so we just pass // null as the pres context all the time here. - nsEventDispatcher::Dispatch(content, nsnull, &event, nsnull, &status); } } return NS_OK; } nsresult @@ -2967,16 +2981,29 @@ nsGlobalWindow::GetHistory(nsIDOMHistory } } NS_IF_ADDREF(*aHistory = mHistory); return NS_OK; } NS_IMETHODIMP +nsGlobalWindow::GetPerformance(nsIDOMPerformance** aPerformance) +{ + FORWARD_TO_INNER(GetPerformance, (aPerformance), NS_ERROR_NOT_INITIALIZED); + + *aPerformance = nsnull; + + //if (nsGlobalWindow::HasPerformanceSupport()) { + NS_IF_ADDREF(*aPerformance = mPerformance); + //} + return NS_OK; +} + +NS_IMETHODIMP nsGlobalWindow::GetParent(nsIDOMWindow** aParent) { FORWARD_TO_OUTER(GetParent, (aParent), NS_ERROR_NOT_INITIALIZED); *aParent = nsnull; if (!mDocShell) return NS_OK; diff -r 385684ad7eed dom/base/nsGlobalWindow.h --- a/dom/base/nsGlobalWindow.h Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/base/nsGlobalWindow.h Wed Apr 06 15:14:13 2011 +0200 @@ -134,16 +134,17 @@ class nsIDOMEvent; class nsIScrollableFrame; class nsIControllers; class nsBarProp; class nsLocation; class nsNavigator; class nsScreen; class nsHistory; +class nsPerformance; class nsIDocShellLoadInfo; class WindowStateHolder; class nsGlobalWindowObserver; class nsGlobalWindow; class nsDummyJavaPluginOwner; class PostMessageEvent; class nsRunnable; @@ -575,16 +576,20 @@ public: static nsGlobalWindow* GetOuterWindowWithId(PRUint64 aWindowID) { return sOuterWindowsById ? sOuterWindowsById->Get(aWindowID) : nsnull; } static bool HasIndexedDBSupport() { return nsContentUtils::GetBoolPref("indexedDB.feature.enabled", PR_TRUE); } + static bool HasPerformanceSupport() { + return nsContentUtils::GetBoolPref("dom.enable_performance", PR_FALSE); + } + private: // Enable updates for the accelerometer. void EnableAccelerationUpdates(); // Disables updates for the accelerometer. void DisableAccelerationUpdates(); protected: @@ -901,16 +906,17 @@ protected: nsCOMPtr mContext; nsWeakPtr mOpener; nsCOMPtr mControllers; nsCOMPtr mArguments; nsCOMPtr mArgumentsLast; nsCOMPtr mArgumentsOrigin; nsRefPtr mNavigator; nsRefPtr mScreen; + nsRefPtr mPerformance; nsRefPtr mFrames; nsRefPtr mMenubar; nsRefPtr mToolbar; nsRefPtr mLocationbar; nsRefPtr mPersonalbar; nsRefPtr mStatusbar; nsRefPtr mScrollbars; nsCOMPtr mWindowUtils; diff -r 385684ad7eed dom/base/nsPerformance.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/base/nsPerformance.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,279 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (update to match bearly-final spec) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "nsPerformance.h" +#include "nsCOMPtr.h" +#include "nscore.h" +#include "nsIDocShell.h" +#include "nsDOMClassInfo.h" +#include "nsDOMNavigationTiming.h" + +DOMCI_DATA(PerformanceTiming, nsPerformanceTiming) + +NS_IMPL_ADDREF(nsPerformanceTiming) +NS_IMPL_RELEASE(nsPerformanceTiming) + +// QueryInterface implementation for nsPerformanceTiming +NS_INTERFACE_MAP_BEGIN(nsPerformanceTiming) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformanceTiming) + NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceTiming) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PerformanceTiming) +NS_INTERFACE_MAP_END + +nsPerformanceTiming::nsPerformanceTiming(nsDOMNavigationTiming* aData) +{ + NS_ASSERTION(aData, "Timing data should be provided"); + mData = aData; +} + +nsPerformanceTiming::~nsPerformanceTiming() +{ +} + +NS_IMETHODIMP +nsPerformanceTiming::GetNavigationStart(DOMTimeMilliSec* aTime) +{ + return mData->GetNavigationStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetUnloadEventStart(DOMTimeMilliSec* aTime) +{ + return mData->GetUnloadEventStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetUnloadEventEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetUnloadEventEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetRedirectStart(DOMTimeMilliSec* aTime) +{ + return mData->GetRedirectStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetRedirectEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetRedirectEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetFetchStart(DOMTimeMilliSec* aTime) +{ + return mData->GetFetchStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomainLookupStart(DOMTimeMilliSec* aTime) +{ + return mData->GetDomainLookupStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomainLookupEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetDomainLookupEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetConnectStart(DOMTimeMilliSec* aTime) +{ + return mData->GetConnectStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetConnectEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetConnectEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetHandshakeStart(DOMTimeMilliSec* aTime) +{ + return mData->GetHandshakeStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetRequestStart(DOMTimeMilliSec* aTime) +{ + return mData->GetRequestStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetResponseStart(DOMTimeMilliSec* aTime) +{ + return mData->GetResponseStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetResponseEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetResponseEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomLoading(DOMTimeMilliSec* aTime) +{ + return mData->GetDomLoading(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomInteractive(DOMTimeMilliSec* aTime) +{ + return mData->GetDomInteractive(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomContentLoadedEventStart(DOMTimeMilliSec* aTime) +{ + return mData->GetDomContentLoadedEventStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomContentLoadedEventEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetDomContentLoadedEventEnd(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetDomComplete(DOMTimeMilliSec* aTime) +{ + return mData->GetDomComplete(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetLoadEventStart(DOMTimeMilliSec* aTime) +{ + return mData->GetLoadEventStart(aTime); +} + +NS_IMETHODIMP +nsPerformanceTiming::GetLoadEventEnd(DOMTimeMilliSec* aTime) +{ + return mData->GetLoadEventEnd(aTime); +} + + + +DOMCI_DATA(PerformanceNavigation, nsPerformanceNavigation) + +NS_IMPL_ADDREF(nsPerformanceNavigation) +NS_IMPL_RELEASE(nsPerformanceNavigation) + +// QueryInterface implementation for nsPerformanceNavigation +NS_INTERFACE_MAP_BEGIN(nsPerformanceNavigation) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformanceNavigation) + NS_INTERFACE_MAP_ENTRY(nsIDOMPerformanceNavigation) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PerformanceNavigation) +NS_INTERFACE_MAP_END + +nsPerformanceNavigation::nsPerformanceNavigation(nsDOMNavigationTiming* aData) +{ + NS_ASSERTION(aData, "Timing data should be provided"); + mData = aData; +} + +nsPerformanceNavigation::~nsPerformanceNavigation() +{ +} + +NS_IMETHODIMP +nsPerformanceNavigation::GetType( + nsDOMPerformanceNavigationType* aNavigationType) +{ + return mData->GetType(aNavigationType); +} + +NS_IMETHODIMP +nsPerformanceNavigation::GetRedirectCount(PRUint16* aRedirectCount) +{ + return mData->GetRedirectCount(aRedirectCount); +} + + +DOMCI_DATA(Performance, nsPerformance) + +NS_IMPL_ADDREF(nsPerformance) +NS_IMPL_RELEASE(nsPerformance) + +nsPerformance::nsPerformance(nsIDOMPerformanceTiming* aTiming) +{ + NS_ASSERTION(aTiming, "Timing data should be provided"); + mData = static_cast(aTiming); +} + +nsPerformance::~nsPerformance() +{ +} + +// QueryInterface implementation for nsPerformance +NS_INTERFACE_MAP_BEGIN(nsPerformance) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMPerformance) + NS_INTERFACE_MAP_ENTRY(nsIDOMPerformance) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Performance) +NS_INTERFACE_MAP_END + +// +// nsIDOMPerformance methods +// +NS_IMETHODIMP +nsPerformance::GetTiming(nsIDOMPerformanceTiming** aTiming) +{ + if (!mTiming) { + mTiming = new nsPerformanceTiming(mData); + } + NS_ENSURE_TRUE(mTiming, NS_ERROR_OUT_OF_MEMORY); + NS_IF_ADDREF(*aTiming = mTiming); + return NS_OK; +} + +NS_IMETHODIMP +nsPerformance::GetNavigation(nsIDOMPerformanceNavigation** aNavigation) +{ + if (!mNavigation) { + mNavigation = new nsPerformanceNavigation(mData); + } + NS_ENSURE_TRUE(mNavigation, NS_ERROR_OUT_OF_MEMORY); + NS_IF_ADDREF(*aNavigation = mNavigation); + return NS_OK; +} + diff -r 385684ad7eed dom/base/nsPerformance.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/base/nsPerformance.h Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (update to match bearly-final spec) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ +#ifndef nsPerformance_h___ +#define nsPerformance_h___ + +#include "nsIDOMPerformance.h" +#include "nsIDOMPerformanceTiming.h" +#include "nsIDOMPerformanceNavigation.h" +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" + +class nsIDocument; +class nsIURI; +class nsDOMNavigationTiming; + +// Script "performance.timing" object +class nsPerformanceTiming : public nsIDOMPerformanceTiming +{ +public: + nsPerformanceTiming(nsDOMNavigationTiming* data); + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMPERFORMANCETIMING +private: + ~nsPerformanceTiming(); + nsRefPtr mData; +}; + +// Script "performance.navigation" object +class nsPerformanceNavigation : public nsIDOMPerformanceNavigation +{ +public: + nsPerformanceNavigation(nsDOMNavigationTiming* data); + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMPERFORMANCENAVIGATION +private: + ~nsPerformanceNavigation(); + nsRefPtr mData; +}; + +// Script "performance" object +class nsPerformance : public nsIDOMPerformance +{ +public: + nsPerformance(nsIDOMPerformanceTiming* timing); + + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMPERFORMANCE + +private: + ~nsPerformance(); + + nsRefPtr mData; + nsCOMPtr mTiming; + nsCOMPtr mNavigation; +}; + +#endif /* nsPerformance_h___ */ + diff -r 385684ad7eed dom/interfaces/base/Makefile.in --- a/dom/interfaces/base/Makefile.in Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/interfaces/base/Makefile.in Wed Apr 06 15:14:13 2011 +0200 @@ -81,11 +81,14 @@ XPIDLSRCS = \ nsIDOMNSFeatureFactory.idl \ nsIDOMClientRect.idl \ nsIDOMClientRectList.idl \ nsIFocusManager.idl \ nsIQueryContentEventResult.idl \ nsITabChild.idl \ nsITabParent.idl \ nsIDOMGlobalPropertyInitializer.idl \ + nsIDOMPerformance.idl \ + nsIDOMPerformanceTiming.idl \ + nsIDOMPerformanceNavigation.idl \ $(NULL) include $(topsrcdir)/config/rules.mk diff -r 385684ad7eed dom/interfaces/base/domstubs.idl --- a/dom/interfaces/base/domstubs.idl Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/interfaces/base/domstubs.idl Wed Apr 06 15:14:13 2011 +0200 @@ -35,16 +35,17 @@ * 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" typedef unsigned long long DOMTimeStamp; +typedef unsigned long long DOMTimeMilliSec; // Core interface nsIDOMAttr; interface nsIDOMCDATASection; interface nsIDOMCharacterData; interface nsIDOMComment; interface nsIDOMDOMImplementation; interface nsIDOMDocument; diff -r 385684ad7eed dom/interfaces/base/nsIDOMPerformance.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/interfaces/base/nsIDOMPerformance.idl Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,50 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (update to match nearly-final spec) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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" +interface nsIDOMPerformanceTiming; +interface nsIDOMPerformanceNavigation; + +[scriptable, uuid(446faf26-000b-4e66-a5fd-ae37c5ed6beb)] +interface nsIDOMPerformance : nsISupports +{ + readonly attribute nsIDOMPerformanceTiming timing; + readonly attribute nsIDOMPerformanceNavigation navigation; +}; + diff -r 385684ad7eed dom/interfaces/base/nsIDOMPerformanceNavigation.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/interfaces/base/nsIDOMPerformanceNavigation.idl Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,55 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (update to match nearly-final spec) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "domstubs.idl" + +typedef unsigned short nsDOMPerformanceNavigationType; + +[scriptable, uuid(a2132ad8-a841-4285-a140-338e8de6c2e0)] +interface nsIDOMPerformanceNavigation : nsISupports +{ + const nsDOMPerformanceNavigationType TYPE_NAVIGATE = 0; + const nsDOMPerformanceNavigationType TYPE_RELOAD = 1; + const nsDOMPerformanceNavigationType TYPE_BACK_FORWARD = 2; + const nsDOMPerformanceNavigationType TYPE_RESERVED = 255; + + readonly attribute nsDOMPerformanceNavigationType type; + readonly attribute unsigned short redirectCount; +}; + diff -r 385684ad7eed dom/interfaces/base/nsIDOMPerformanceTiming.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/interfaces/base/nsIDOMPerformanceTiming.idl Wed Apr 06 15:14:13 2011 +0200 @@ -0,0 +1,67 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 implementation of Web Timing draft specification + * http://dev.w3.org/2006/webapi/WebTiming/ + * + * The Initial Developer of the Original Code is Google Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Sergey Novikov (original author) + * Igor Bazarny (update to match nearly-final spec) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "domstubs.idl" + +[scriptable, uuid(2a630b50-61b6-41b3-996d-70be67fbbcb0)] +interface nsIDOMPerformanceTiming : nsISupports +{ + readonly attribute DOMTimeMilliSec navigationStart; + readonly attribute DOMTimeMilliSec unloadEventStart; + readonly attribute DOMTimeMilliSec unloadEventEnd; + readonly attribute DOMTimeMilliSec redirectStart; + readonly attribute DOMTimeMilliSec redirectEnd; + readonly attribute DOMTimeMilliSec fetchStart; + readonly attribute DOMTimeMilliSec domainLookupStart; + readonly attribute DOMTimeMilliSec domainLookupEnd; + readonly attribute DOMTimeMilliSec connectStart; + readonly attribute DOMTimeMilliSec connectEnd; + readonly attribute DOMTimeMilliSec handshakeStart; + readonly attribute DOMTimeMilliSec requestStart; + readonly attribute DOMTimeMilliSec responseStart; + readonly attribute DOMTimeMilliSec responseEnd; + readonly attribute DOMTimeMilliSec domLoading; + readonly attribute DOMTimeMilliSec domInteractive; + readonly attribute DOMTimeMilliSec domContentLoadedEventStart; + readonly attribute DOMTimeMilliSec domContentLoadedEventEnd; + readonly attribute DOMTimeMilliSec domComplete; + readonly attribute DOMTimeMilliSec loadEventStart; + readonly attribute DOMTimeMilliSec loadEventEnd; +}; + diff -r 385684ad7eed dom/interfaces/base/nsIDOMWindowInternal.idl --- a/dom/interfaces/base/nsIDOMWindowInternal.idl Tue Apr 05 09:19:34 2011 -0700 +++ b/dom/interfaces/base/nsIDOMWindowInternal.idl Wed Apr 06 15:14:13 2011 +0200 @@ -37,20 +37,21 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsIDOMWindow2.idl" interface nsIPrompt; interface nsIControllers; interface nsIDOMLocation; +interface nsIDOMPerformance; interface nsIVariant; interface nsIAnimationFrameListener; -[scriptable, uuid(9d6a1157-0719-46a7-b49f-7ffeaa0b5c86)] +[scriptable, uuid(5930f197-259e-4f6b-aeca-c96a74518cc6)] interface nsIDOMWindowInternal : nsIDOMWindow2 { readonly attribute nsIDOMWindowInternal window; /* [replaceable] self */ readonly attribute nsIDOMWindowInternal self; readonly attribute nsIDOMNavigator navigator; @@ -227,16 +228,21 @@ interface nsIDOMWindowInternal : nsIDOMW */ void mozRequestAnimationFrame([optional] in nsIAnimationFrameListener aListener); /** * The current animation start time in milliseconds since the epoch. */ readonly attribute long long mozAnimationStartTime; + + /** + * A namespace to hold performance related data and statistics. + */ + readonly attribute nsIDOMPerformance performance; }; [scriptable, uuid(8fc58f56-f769-4368-a098-edd08550cf1a)] interface nsIDOMMozURLProperty : nsISupports { DOMString createObjectURL(in nsIDOMBlob blob); void revokeObjectURL(in DOMString URL); }; diff -r 385684ad7eed layout/base/nsDocumentViewer.cpp --- a/layout/base/nsDocumentViewer.cpp Tue Apr 05 09:19:34 2011 -0700 +++ b/layout/base/nsDocumentViewer.cpp Wed Apr 06 15:14:13 2011 +0200 @@ -113,16 +113,19 @@ #include "nsIXULDocument.h" #include "nsXULPopupManager.h" #endif #include "nsPrintfCString.h" #include "nsIClipboardHelper.h" #include "nsPIDOMWindow.h" +#include "nsIDOMPerformance.h" +#include "nsIDOMPerformanceTiming.h" +#include "nsDOMNavigationTiming.h" #include "nsPIWindowRoot.h" #include "nsJSEnvironment.h" #include "nsFocusManager.h" #include "nsIScrollableFrame.h" #include "nsIHTMLDocument.h" #include "nsITimelineService.h" #include "nsGfxCIID.h" @@ -330,16 +333,21 @@ public: /** * Find the view to use as the container view for MakeWindow. Returns * null if this will be the root of a view manager hierarchy. In that * case, if mParentWidget is null then this document should not even * be displayed. */ virtual nsIView* FindContainerView(); + /** + * Set collector for navigation timing data (load, unload events). + */ + virtual void SetNavigationTiming(nsDOMNavigationTiming* timing); + // nsIContentViewerEdit NS_DECL_NSICONTENTVIEWEREDIT // nsIContentViewerFile NS_DECL_NSICONTENTVIEWERFILE // nsIMarkupDocumentViewer NS_DECL_NSIMARKUPDOCUMENTVIEWER @@ -449,16 +457,19 @@ protected: nsCOMPtr mPresShell; nsCOMPtr mSelectionListener; nsCOMPtr mFocusListener; nsCOMPtr mPreviousViewer; nsCOMPtr mSHEntry; + // Navigation timing data collector + nsRefPtr mTiming; + nsIWidget* mParentWidget; // purposely won't be ref counted. May be null PRBool mAttachedToParent; // view is attached to the parent widget nsIntRect mBounds; // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley) // presshell only. float mTextZoom; // Text zoom, defaults to 1.0 @@ -988,16 +999,24 @@ DocumentViewerImpl::InitInternal(nsIWidg // MakeWindow())... rv = InitPresentationStuff(!makeCX); } return rv; } +void DocumentViewerImpl::SetNavigationTiming(nsDOMNavigationTiming* timing) +{ + mTiming = timing; + if (mDocument) { + mDocument->SetNavigationTiming(timing); + } +} + // // LoadComplete(aStatus) // // aStatus - The status returned from loading the document. // // This method is called by the container when the document has been // completely loaded. // @@ -1049,18 +1068,24 @@ DocumentViewerImpl::LoadComplete(nsresul // onload to the document content since that would likely confuse scripts // on the page. nsIDocShell *docShell = window->GetDocShell(); NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED); docShell->GetRestoringDocument(&restoring); if (!restoring) { + if (mTiming) { + mTiming->NotifyLoadEventStart(); + } nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status); + if (mTiming) { + mTiming->NotifyLoadEventEnd(); + } #ifdef MOZ_TIMELINE // if navigator.xul's load is complete, the main nav window is visible // mark that point. nsIURI *uri = mDocument ? mDocument->GetDocumentURI() : nsnull; if (uri) { //printf("DEBUG: getting spec for uri (%p)\n", uri.get()); @@ -1316,16 +1341,20 @@ DocumentViewerImpl::PageHide(PRBool aIsU // Never permit popups from the unload handler, no matter how we get // here. nsAutoPopupStatePusher popupStatePusher(openAbused, PR_TRUE); nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status); } + if (mTiming) { + mTiming->NotifyLastUnload(); + } + #ifdef MOZ_XUL // look for open menupopups and close them after the unload event, in case // the unload event listeners open any new popups nsContentUtils::HidePopupsInDocument(mDocument); #endif return NS_OK; } diff -r 385684ad7eed layout/base/nsIDocumentViewer.h --- a/layout/base/nsIDocumentViewer.h Tue Apr 05 09:19:34 2011 -0700 +++ b/layout/base/nsIDocumentViewer.h Wed Apr 06 15:14:13 2011 +0200 @@ -43,16 +43,18 @@ #include "nsIContentViewer.h" class nsIDocument; class nsPresContext; class nsIPresShell; class nsIStyleSheet; class nsIView; +class nsDOMNavigationTiming; + #define NS_IDOCUMENT_VIEWER_IID \ { 0x5a5c9a1d, 0x49c4, 0x4f3f, \ { 0x80, 0xcd, 0x12, 0x09, 0x5b, 0x1e, 0x1f, 0x61 } } /** * A document viewer is a kind of content viewer that uses NGLayout * to manage the presentation of the content. */ @@ -64,13 +66,15 @@ public: NS_IMETHOD GetPresShell(nsIPresShell** aResult) = 0; NS_IMETHOD GetPresContext(nsPresContext** aResult) = 0; NS_IMETHOD SetDocumentInternal(nsIDocument* aDocument, PRBool aForceReuseInnerWindow) = 0; virtual nsIView* FindContainerView() = 0; + + virtual void SetNavigationTiming(nsDOMNavigationTiming* timing) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewer, NS_IDOCUMENT_VIEWER_IID) #endif /* nsIDocumentViewer_h___ */