1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/base/nsPerformance.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,352 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#ifndef nsPerformance_h___ 1.9 +#define nsPerformance_h___ 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsAutoPtr.h" 1.13 +#include "mozilla/Attributes.h" 1.14 +#include "nsWrapperCache.h" 1.15 +#include "nsDOMNavigationTiming.h" 1.16 +#include "nsContentUtils.h" 1.17 +#include "nsIDOMWindow.h" 1.18 +#include "js/TypeDecls.h" 1.19 +#include "mozilla/dom/BindingDeclarations.h" 1.20 + 1.21 +class nsITimedChannel; 1.22 +class nsPerformance; 1.23 +class nsIHttpChannel; 1.24 + 1.25 +namespace mozilla { 1.26 +namespace dom { 1.27 + class PerformanceEntry; 1.28 +} 1.29 +} 1.30 + 1.31 +// Script "performance.timing" object 1.32 +class nsPerformanceTiming MOZ_FINAL : public nsWrapperCache 1.33 +{ 1.34 +public: 1.35 + typedef mozilla::TimeStamp TimeStamp; 1.36 + 1.37 +/** 1.38 + * @param aPerformance 1.39 + * The performance object (the JS parent). 1.40 + * This will allow access to "window.performance.timing" attribute for 1.41 + * the navigation timing (can't be null). 1.42 + * @param aChannel 1.43 + * An nsITimedChannel used to gather all the networking timings by both 1.44 + * the navigation timing and the resource timing (can't be null). 1.45 + * @param aHttpChannel 1.46 + * An nsIHttpChannel (the resource's http channel). 1.47 + * This will be used by the resource timing cross-domain check 1.48 + * algorithm. 1.49 + * Argument is null for the navigation timing (navigation timing uses 1.50 + * another algorithm for the cross-domain redirects). 1.51 + * @param aZeroTime 1.52 + * The offset that will be added to the timestamp of each event. This 1.53 + * argument should be equal to performance.navigationStart for 1.54 + * navigation timing and "0" for the resource timing. 1.55 + */ 1.56 + nsPerformanceTiming(nsPerformance* aPerformance, 1.57 + nsITimedChannel* aChannel, 1.58 + nsIHttpChannel* aHttpChannel, 1.59 + DOMHighResTimeStamp aZeroTime); 1.60 + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceTiming) 1.61 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceTiming) 1.62 + 1.63 + nsDOMNavigationTiming* GetDOMTiming() const; 1.64 + 1.65 + nsPerformance* GetParentObject() const 1.66 + { 1.67 + return mPerformance; 1.68 + } 1.69 + 1.70 + /** 1.71 + * @param aStamp 1.72 + * The TimeStamp recorded for a specific event. This TimeStamp can 1.73 + * be null. 1.74 + * @return the duration of an event with a given TimeStamp, relative to the 1.75 + * navigationStart TimeStamp (the moment the user landed on the 1.76 + * page), if the given TimeStamp is valid. Otherwise, it will return 1.77 + * the FetchStart timing value. 1.78 + */ 1.79 + inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) 1.80 + { 1.81 + return (!aStamp.IsNull()) 1.82 + ? TimeStampToDOMHighRes(aStamp) 1.83 + : FetchStartHighRes(); 1.84 + } 1.85 + 1.86 + /** 1.87 + * The nsITimedChannel records an absolute timestamp for each event. 1.88 + * The nsDOMNavigationTiming will record the moment when the user landed on 1.89 + * the page. This is a window.performance unique timestamp, so it can be used 1.90 + * for all the events (navigation timing and resource timing events). 1.91 + * 1.92 + * The algorithm operates in 2 steps: 1.93 + * 1. The first step is to subtract the two timestamps: the argument (the 1.94 + * envet's timesramp) and the navigation start timestamp. This will result in 1.95 + * a relative timestamp of the event (relative to the navigation start - 1.96 + * window.performance.timing.navigationStart). 1.97 + * 2. The second step is to add any required offset (the mZeroTime). For now, 1.98 + * this offset value is either 0 (for the resource timing), or equal to 1.99 + * "performance.navigationStart" (for navigation timing). 1.100 + * For the resource timing, mZeroTime is set to 0, causing the result to be a 1.101 + * relative time. 1.102 + * For the navigation timing, mZeroTime is set to "performance.navigationStart" 1.103 + * causing the result be an absolute time. 1.104 + * 1.105 + * @param aStamp 1.106 + * The TimeStamp recorded for a specific event. This TimeStamp can't 1.107 + * be null. 1.108 + * @return number of milliseconds value as one of: 1.109 + * - relative to the navigation start time, time the user has landed on the 1.110 + * page 1.111 + * - an absolute wall clock time since the unix epoch 1.112 + */ 1.113 + inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const 1.114 + { 1.115 + MOZ_ASSERT(!aStamp.IsNull()); 1.116 + mozilla::TimeDuration duration = 1.117 + aStamp - GetDOMTiming()->GetNavigationStartTimeStamp(); 1.118 + return duration.ToMilliseconds() + mZeroTime; 1.119 + } 1.120 + 1.121 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; 1.122 + 1.123 + // PerformanceNavigation WebIDL methods 1.124 + DOMTimeMilliSec NavigationStart() const { 1.125 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.126 + return 0; 1.127 + } 1.128 + return GetDOMTiming()->GetNavigationStart(); 1.129 + } 1.130 + DOMTimeMilliSec UnloadEventStart() { 1.131 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.132 + return 0; 1.133 + } 1.134 + return GetDOMTiming()->GetUnloadEventStart(); 1.135 + } 1.136 + DOMTimeMilliSec UnloadEventEnd() { 1.137 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.138 + return 0; 1.139 + } 1.140 + return GetDOMTiming()->GetUnloadEventEnd(); 1.141 + } 1.142 + 1.143 + uint16_t GetRedirectCount() const; 1.144 + bool IsSameOriginAsReferral() const; 1.145 + void CheckRedirectCrossOrigin(nsIHttpChannel* aResourceChannel); 1.146 + 1.147 + // High resolution (used by resource timing) 1.148 + DOMHighResTimeStamp FetchStartHighRes(); 1.149 + DOMHighResTimeStamp RedirectStartHighRes(); 1.150 + DOMHighResTimeStamp RedirectEndHighRes(); 1.151 + DOMHighResTimeStamp DomainLookupStartHighRes(); 1.152 + DOMHighResTimeStamp DomainLookupEndHighRes(); 1.153 + DOMHighResTimeStamp ConnectStartHighRes(); 1.154 + DOMHighResTimeStamp ConnectEndHighRes(); 1.155 + DOMHighResTimeStamp RequestStartHighRes(); 1.156 + DOMHighResTimeStamp ResponseStartHighRes(); 1.157 + DOMHighResTimeStamp ResponseEndHighRes(); 1.158 + 1.159 + // Low resolution (used by navigation timing) 1.160 + DOMTimeMilliSec FetchStart(); 1.161 + DOMTimeMilliSec RedirectStart(); 1.162 + DOMTimeMilliSec RedirectEnd(); 1.163 + DOMTimeMilliSec DomainLookupStart(); 1.164 + DOMTimeMilliSec DomainLookupEnd(); 1.165 + DOMTimeMilliSec ConnectStart(); 1.166 + DOMTimeMilliSec ConnectEnd(); 1.167 + DOMTimeMilliSec RequestStart(); 1.168 + DOMTimeMilliSec ResponseStart(); 1.169 + DOMTimeMilliSec ResponseEnd(); 1.170 + 1.171 + DOMTimeMilliSec DomLoading() { 1.172 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.173 + return 0; 1.174 + } 1.175 + return GetDOMTiming()->GetDomLoading(); 1.176 + } 1.177 + DOMTimeMilliSec DomInteractive() const { 1.178 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.179 + return 0; 1.180 + } 1.181 + return GetDOMTiming()->GetDomInteractive(); 1.182 + } 1.183 + DOMTimeMilliSec DomContentLoadedEventStart() const { 1.184 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.185 + return 0; 1.186 + } 1.187 + return GetDOMTiming()->GetDomContentLoadedEventStart(); 1.188 + } 1.189 + DOMTimeMilliSec DomContentLoadedEventEnd() const { 1.190 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.191 + return 0; 1.192 + } 1.193 + return GetDOMTiming()->GetDomContentLoadedEventEnd(); 1.194 + } 1.195 + DOMTimeMilliSec DomComplete() const { 1.196 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.197 + return 0; 1.198 + } 1.199 + return GetDOMTiming()->GetDomComplete(); 1.200 + } 1.201 + DOMTimeMilliSec LoadEventStart() const { 1.202 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.203 + return 0; 1.204 + } 1.205 + return GetDOMTiming()->GetLoadEventStart(); 1.206 + } 1.207 + DOMTimeMilliSec LoadEventEnd() const { 1.208 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.209 + return 0; 1.210 + } 1.211 + return GetDOMTiming()->GetLoadEventEnd(); 1.212 + } 1.213 + 1.214 +private: 1.215 + ~nsPerformanceTiming(); 1.216 + bool IsInitialized() const; 1.217 + nsRefPtr<nsPerformance> mPerformance; 1.218 + nsCOMPtr<nsITimedChannel> mChannel; 1.219 + DOMHighResTimeStamp mFetchStart; 1.220 + // This is an offset that will be added to each timing ([ms] resolution). 1.221 + // There are only 2 possible values: (1) logicaly equal to navigationStart 1.222 + // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results 1.223 + // are relative to the navigation start). 1.224 + DOMHighResTimeStamp mZeroTime; 1.225 + bool mReportCrossOriginResources; 1.226 +}; 1.227 + 1.228 +// Script "performance.navigation" object 1.229 +class nsPerformanceNavigation MOZ_FINAL : public nsWrapperCache 1.230 +{ 1.231 +public: 1.232 + explicit nsPerformanceNavigation(nsPerformance* aPerformance); 1.233 + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceNavigation) 1.234 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceNavigation) 1.235 + 1.236 + nsDOMNavigationTiming* GetDOMTiming() const; 1.237 + nsPerformanceTiming* GetPerformanceTiming() const; 1.238 + 1.239 + nsPerformance* GetParentObject() const 1.240 + { 1.241 + return mPerformance; 1.242 + } 1.243 + 1.244 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; 1.245 + 1.246 + // PerformanceNavigation WebIDL methods 1.247 + uint16_t Type() const { 1.248 + return GetDOMTiming()->GetType(); 1.249 + } 1.250 + uint16_t RedirectCount() const { 1.251 + return GetPerformanceTiming()->GetRedirectCount(); 1.252 + } 1.253 + 1.254 +private: 1.255 + ~nsPerformanceNavigation(); 1.256 + nsRefPtr<nsPerformance> mPerformance; 1.257 +}; 1.258 + 1.259 +// Script "performance" object 1.260 +class nsPerformance MOZ_FINAL : public nsISupports, 1.261 + public nsWrapperCache 1.262 +{ 1.263 +public: 1.264 + typedef mozilla::dom::PerformanceEntry PerformanceEntry; 1.265 + nsPerformance(nsIDOMWindow* aWindow, 1.266 + nsDOMNavigationTiming* aDOMTiming, 1.267 + nsITimedChannel* aChannel, 1.268 + nsPerformance* aParentPerformance); 1.269 + 1.270 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.271 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance) 1.272 + 1.273 + nsDOMNavigationTiming* GetDOMTiming() const 1.274 + { 1.275 + return mDOMTiming; 1.276 + } 1.277 + 1.278 + nsITimedChannel* GetChannel() const 1.279 + { 1.280 + return mChannel; 1.281 + } 1.282 + 1.283 + nsPerformance* GetParentPerformance() const 1.284 + { 1.285 + return mParentPerformance; 1.286 + } 1.287 + 1.288 + nsIDOMWindow* GetParentObject() const 1.289 + { 1.290 + return mWindow.get(); 1.291 + } 1.292 + 1.293 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; 1.294 + 1.295 + // Performance WebIDL methods 1.296 + DOMHighResTimeStamp Now(); 1.297 + nsPerformanceTiming* Timing(); 1.298 + nsPerformanceNavigation* Navigation(); 1.299 + 1.300 + void GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval); 1.301 + void GetEntriesByType(const nsAString& entryType, 1.302 + nsTArray<nsRefPtr<PerformanceEntry> >& retval); 1.303 + void GetEntriesByName(const nsAString& name, 1.304 + const mozilla::dom::Optional< nsAString >& entryType, 1.305 + nsTArray<nsRefPtr<PerformanceEntry> >& retval); 1.306 + void AddEntry(nsIHttpChannel* channel, 1.307 + nsITimedChannel* timedChannel); 1.308 + void ClearResourceTimings(); 1.309 + void SetResourceTimingBufferSize(uint64_t maxSize); 1.310 + 1.311 +private: 1.312 + ~nsPerformance(); 1.313 + 1.314 + nsCOMPtr<nsIDOMWindow> mWindow; 1.315 + nsRefPtr<nsDOMNavigationTiming> mDOMTiming; 1.316 + nsCOMPtr<nsITimedChannel> mChannel; 1.317 + nsRefPtr<nsPerformanceTiming> mTiming; 1.318 + nsRefPtr<nsPerformanceNavigation> mNavigation; 1.319 + nsTArray<nsRefPtr<PerformanceEntry> > mEntries; 1.320 + nsRefPtr<nsPerformance> mParentPerformance; 1.321 + uint64_t mBufferSizeSet; 1.322 + uint64_t mPrimaryBufferSize; 1.323 + 1.324 + static const uint64_t kDefaultBufferSize = 150; 1.325 + 1.326 + // Helper classes 1.327 + class PerformanceEntryComparator { 1.328 + public: 1.329 + bool Equals(const PerformanceEntry* aElem1, 1.330 + const PerformanceEntry* aElem2) const; 1.331 + bool LessThan(const PerformanceEntry* aElem1, 1.332 + const PerformanceEntry* aElem2) const; 1.333 + }; 1.334 +}; 1.335 + 1.336 +inline nsDOMNavigationTiming* 1.337 +nsPerformanceNavigation::GetDOMTiming() const 1.338 +{ 1.339 + return mPerformance->GetDOMTiming(); 1.340 +} 1.341 + 1.342 +inline nsPerformanceTiming* 1.343 +nsPerformanceNavigation::GetPerformanceTiming() const 1.344 +{ 1.345 + return mPerformance->Timing(); 1.346 +} 1.347 + 1.348 +inline nsDOMNavigationTiming* 1.349 +nsPerformanceTiming::GetDOMTiming() const 1.350 +{ 1.351 + return mPerformance->GetDOMTiming(); 1.352 +} 1.353 + 1.354 +#endif /* nsPerformance_h___ */ 1.355 +