|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 #ifndef nsPerformance_h___ |
|
6 #define nsPerformance_h___ |
|
7 |
|
8 #include "nsCOMPtr.h" |
|
9 #include "nsAutoPtr.h" |
|
10 #include "mozilla/Attributes.h" |
|
11 #include "nsWrapperCache.h" |
|
12 #include "nsDOMNavigationTiming.h" |
|
13 #include "nsContentUtils.h" |
|
14 #include "nsIDOMWindow.h" |
|
15 #include "js/TypeDecls.h" |
|
16 #include "mozilla/dom/BindingDeclarations.h" |
|
17 |
|
18 class nsITimedChannel; |
|
19 class nsPerformance; |
|
20 class nsIHttpChannel; |
|
21 |
|
22 namespace mozilla { |
|
23 namespace dom { |
|
24 class PerformanceEntry; |
|
25 } |
|
26 } |
|
27 |
|
28 // Script "performance.timing" object |
|
29 class nsPerformanceTiming MOZ_FINAL : public nsWrapperCache |
|
30 { |
|
31 public: |
|
32 typedef mozilla::TimeStamp TimeStamp; |
|
33 |
|
34 /** |
|
35 * @param aPerformance |
|
36 * The performance object (the JS parent). |
|
37 * This will allow access to "window.performance.timing" attribute for |
|
38 * the navigation timing (can't be null). |
|
39 * @param aChannel |
|
40 * An nsITimedChannel used to gather all the networking timings by both |
|
41 * the navigation timing and the resource timing (can't be null). |
|
42 * @param aHttpChannel |
|
43 * An nsIHttpChannel (the resource's http channel). |
|
44 * This will be used by the resource timing cross-domain check |
|
45 * algorithm. |
|
46 * Argument is null for the navigation timing (navigation timing uses |
|
47 * another algorithm for the cross-domain redirects). |
|
48 * @param aZeroTime |
|
49 * The offset that will be added to the timestamp of each event. This |
|
50 * argument should be equal to performance.navigationStart for |
|
51 * navigation timing and "0" for the resource timing. |
|
52 */ |
|
53 nsPerformanceTiming(nsPerformance* aPerformance, |
|
54 nsITimedChannel* aChannel, |
|
55 nsIHttpChannel* aHttpChannel, |
|
56 DOMHighResTimeStamp aZeroTime); |
|
57 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceTiming) |
|
58 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceTiming) |
|
59 |
|
60 nsDOMNavigationTiming* GetDOMTiming() const; |
|
61 |
|
62 nsPerformance* GetParentObject() const |
|
63 { |
|
64 return mPerformance; |
|
65 } |
|
66 |
|
67 /** |
|
68 * @param aStamp |
|
69 * The TimeStamp recorded for a specific event. This TimeStamp can |
|
70 * be null. |
|
71 * @return the duration of an event with a given TimeStamp, relative to the |
|
72 * navigationStart TimeStamp (the moment the user landed on the |
|
73 * page), if the given TimeStamp is valid. Otherwise, it will return |
|
74 * the FetchStart timing value. |
|
75 */ |
|
76 inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) |
|
77 { |
|
78 return (!aStamp.IsNull()) |
|
79 ? TimeStampToDOMHighRes(aStamp) |
|
80 : FetchStartHighRes(); |
|
81 } |
|
82 |
|
83 /** |
|
84 * The nsITimedChannel records an absolute timestamp for each event. |
|
85 * The nsDOMNavigationTiming will record the moment when the user landed on |
|
86 * the page. This is a window.performance unique timestamp, so it can be used |
|
87 * for all the events (navigation timing and resource timing events). |
|
88 * |
|
89 * The algorithm operates in 2 steps: |
|
90 * 1. The first step is to subtract the two timestamps: the argument (the |
|
91 * envet's timesramp) and the navigation start timestamp. This will result in |
|
92 * a relative timestamp of the event (relative to the navigation start - |
|
93 * window.performance.timing.navigationStart). |
|
94 * 2. The second step is to add any required offset (the mZeroTime). For now, |
|
95 * this offset value is either 0 (for the resource timing), or equal to |
|
96 * "performance.navigationStart" (for navigation timing). |
|
97 * For the resource timing, mZeroTime is set to 0, causing the result to be a |
|
98 * relative time. |
|
99 * For the navigation timing, mZeroTime is set to "performance.navigationStart" |
|
100 * causing the result be an absolute time. |
|
101 * |
|
102 * @param aStamp |
|
103 * The TimeStamp recorded for a specific event. This TimeStamp can't |
|
104 * be null. |
|
105 * @return number of milliseconds value as one of: |
|
106 * - relative to the navigation start time, time the user has landed on the |
|
107 * page |
|
108 * - an absolute wall clock time since the unix epoch |
|
109 */ |
|
110 inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const |
|
111 { |
|
112 MOZ_ASSERT(!aStamp.IsNull()); |
|
113 mozilla::TimeDuration duration = |
|
114 aStamp - GetDOMTiming()->GetNavigationStartTimeStamp(); |
|
115 return duration.ToMilliseconds() + mZeroTime; |
|
116 } |
|
117 |
|
118 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; |
|
119 |
|
120 // PerformanceNavigation WebIDL methods |
|
121 DOMTimeMilliSec NavigationStart() const { |
|
122 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
123 return 0; |
|
124 } |
|
125 return GetDOMTiming()->GetNavigationStart(); |
|
126 } |
|
127 DOMTimeMilliSec UnloadEventStart() { |
|
128 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
129 return 0; |
|
130 } |
|
131 return GetDOMTiming()->GetUnloadEventStart(); |
|
132 } |
|
133 DOMTimeMilliSec UnloadEventEnd() { |
|
134 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
135 return 0; |
|
136 } |
|
137 return GetDOMTiming()->GetUnloadEventEnd(); |
|
138 } |
|
139 |
|
140 uint16_t GetRedirectCount() const; |
|
141 bool IsSameOriginAsReferral() const; |
|
142 void CheckRedirectCrossOrigin(nsIHttpChannel* aResourceChannel); |
|
143 |
|
144 // High resolution (used by resource timing) |
|
145 DOMHighResTimeStamp FetchStartHighRes(); |
|
146 DOMHighResTimeStamp RedirectStartHighRes(); |
|
147 DOMHighResTimeStamp RedirectEndHighRes(); |
|
148 DOMHighResTimeStamp DomainLookupStartHighRes(); |
|
149 DOMHighResTimeStamp DomainLookupEndHighRes(); |
|
150 DOMHighResTimeStamp ConnectStartHighRes(); |
|
151 DOMHighResTimeStamp ConnectEndHighRes(); |
|
152 DOMHighResTimeStamp RequestStartHighRes(); |
|
153 DOMHighResTimeStamp ResponseStartHighRes(); |
|
154 DOMHighResTimeStamp ResponseEndHighRes(); |
|
155 |
|
156 // Low resolution (used by navigation timing) |
|
157 DOMTimeMilliSec FetchStart(); |
|
158 DOMTimeMilliSec RedirectStart(); |
|
159 DOMTimeMilliSec RedirectEnd(); |
|
160 DOMTimeMilliSec DomainLookupStart(); |
|
161 DOMTimeMilliSec DomainLookupEnd(); |
|
162 DOMTimeMilliSec ConnectStart(); |
|
163 DOMTimeMilliSec ConnectEnd(); |
|
164 DOMTimeMilliSec RequestStart(); |
|
165 DOMTimeMilliSec ResponseStart(); |
|
166 DOMTimeMilliSec ResponseEnd(); |
|
167 |
|
168 DOMTimeMilliSec DomLoading() { |
|
169 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
170 return 0; |
|
171 } |
|
172 return GetDOMTiming()->GetDomLoading(); |
|
173 } |
|
174 DOMTimeMilliSec DomInteractive() const { |
|
175 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
176 return 0; |
|
177 } |
|
178 return GetDOMTiming()->GetDomInteractive(); |
|
179 } |
|
180 DOMTimeMilliSec DomContentLoadedEventStart() const { |
|
181 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
182 return 0; |
|
183 } |
|
184 return GetDOMTiming()->GetDomContentLoadedEventStart(); |
|
185 } |
|
186 DOMTimeMilliSec DomContentLoadedEventEnd() const { |
|
187 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
188 return 0; |
|
189 } |
|
190 return GetDOMTiming()->GetDomContentLoadedEventEnd(); |
|
191 } |
|
192 DOMTimeMilliSec DomComplete() const { |
|
193 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
194 return 0; |
|
195 } |
|
196 return GetDOMTiming()->GetDomComplete(); |
|
197 } |
|
198 DOMTimeMilliSec LoadEventStart() const { |
|
199 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
200 return 0; |
|
201 } |
|
202 return GetDOMTiming()->GetLoadEventStart(); |
|
203 } |
|
204 DOMTimeMilliSec LoadEventEnd() const { |
|
205 if (!nsContentUtils::IsPerformanceTimingEnabled()) { |
|
206 return 0; |
|
207 } |
|
208 return GetDOMTiming()->GetLoadEventEnd(); |
|
209 } |
|
210 |
|
211 private: |
|
212 ~nsPerformanceTiming(); |
|
213 bool IsInitialized() const; |
|
214 nsRefPtr<nsPerformance> mPerformance; |
|
215 nsCOMPtr<nsITimedChannel> mChannel; |
|
216 DOMHighResTimeStamp mFetchStart; |
|
217 // This is an offset that will be added to each timing ([ms] resolution). |
|
218 // There are only 2 possible values: (1) logicaly equal to navigationStart |
|
219 // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results |
|
220 // are relative to the navigation start). |
|
221 DOMHighResTimeStamp mZeroTime; |
|
222 bool mReportCrossOriginResources; |
|
223 }; |
|
224 |
|
225 // Script "performance.navigation" object |
|
226 class nsPerformanceNavigation MOZ_FINAL : public nsWrapperCache |
|
227 { |
|
228 public: |
|
229 explicit nsPerformanceNavigation(nsPerformance* aPerformance); |
|
230 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsPerformanceNavigation) |
|
231 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsPerformanceNavigation) |
|
232 |
|
233 nsDOMNavigationTiming* GetDOMTiming() const; |
|
234 nsPerformanceTiming* GetPerformanceTiming() const; |
|
235 |
|
236 nsPerformance* GetParentObject() const |
|
237 { |
|
238 return mPerformance; |
|
239 } |
|
240 |
|
241 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; |
|
242 |
|
243 // PerformanceNavigation WebIDL methods |
|
244 uint16_t Type() const { |
|
245 return GetDOMTiming()->GetType(); |
|
246 } |
|
247 uint16_t RedirectCount() const { |
|
248 return GetPerformanceTiming()->GetRedirectCount(); |
|
249 } |
|
250 |
|
251 private: |
|
252 ~nsPerformanceNavigation(); |
|
253 nsRefPtr<nsPerformance> mPerformance; |
|
254 }; |
|
255 |
|
256 // Script "performance" object |
|
257 class nsPerformance MOZ_FINAL : public nsISupports, |
|
258 public nsWrapperCache |
|
259 { |
|
260 public: |
|
261 typedef mozilla::dom::PerformanceEntry PerformanceEntry; |
|
262 nsPerformance(nsIDOMWindow* aWindow, |
|
263 nsDOMNavigationTiming* aDOMTiming, |
|
264 nsITimedChannel* aChannel, |
|
265 nsPerformance* aParentPerformance); |
|
266 |
|
267 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
268 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance) |
|
269 |
|
270 nsDOMNavigationTiming* GetDOMTiming() const |
|
271 { |
|
272 return mDOMTiming; |
|
273 } |
|
274 |
|
275 nsITimedChannel* GetChannel() const |
|
276 { |
|
277 return mChannel; |
|
278 } |
|
279 |
|
280 nsPerformance* GetParentPerformance() const |
|
281 { |
|
282 return mParentPerformance; |
|
283 } |
|
284 |
|
285 nsIDOMWindow* GetParentObject() const |
|
286 { |
|
287 return mWindow.get(); |
|
288 } |
|
289 |
|
290 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; |
|
291 |
|
292 // Performance WebIDL methods |
|
293 DOMHighResTimeStamp Now(); |
|
294 nsPerformanceTiming* Timing(); |
|
295 nsPerformanceNavigation* Navigation(); |
|
296 |
|
297 void GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval); |
|
298 void GetEntriesByType(const nsAString& entryType, |
|
299 nsTArray<nsRefPtr<PerformanceEntry> >& retval); |
|
300 void GetEntriesByName(const nsAString& name, |
|
301 const mozilla::dom::Optional< nsAString >& entryType, |
|
302 nsTArray<nsRefPtr<PerformanceEntry> >& retval); |
|
303 void AddEntry(nsIHttpChannel* channel, |
|
304 nsITimedChannel* timedChannel); |
|
305 void ClearResourceTimings(); |
|
306 void SetResourceTimingBufferSize(uint64_t maxSize); |
|
307 |
|
308 private: |
|
309 ~nsPerformance(); |
|
310 |
|
311 nsCOMPtr<nsIDOMWindow> mWindow; |
|
312 nsRefPtr<nsDOMNavigationTiming> mDOMTiming; |
|
313 nsCOMPtr<nsITimedChannel> mChannel; |
|
314 nsRefPtr<nsPerformanceTiming> mTiming; |
|
315 nsRefPtr<nsPerformanceNavigation> mNavigation; |
|
316 nsTArray<nsRefPtr<PerformanceEntry> > mEntries; |
|
317 nsRefPtr<nsPerformance> mParentPerformance; |
|
318 uint64_t mBufferSizeSet; |
|
319 uint64_t mPrimaryBufferSize; |
|
320 |
|
321 static const uint64_t kDefaultBufferSize = 150; |
|
322 |
|
323 // Helper classes |
|
324 class PerformanceEntryComparator { |
|
325 public: |
|
326 bool Equals(const PerformanceEntry* aElem1, |
|
327 const PerformanceEntry* aElem2) const; |
|
328 bool LessThan(const PerformanceEntry* aElem1, |
|
329 const PerformanceEntry* aElem2) const; |
|
330 }; |
|
331 }; |
|
332 |
|
333 inline nsDOMNavigationTiming* |
|
334 nsPerformanceNavigation::GetDOMTiming() const |
|
335 { |
|
336 return mPerformance->GetDOMTiming(); |
|
337 } |
|
338 |
|
339 inline nsPerformanceTiming* |
|
340 nsPerformanceNavigation::GetPerformanceTiming() const |
|
341 { |
|
342 return mPerformance->Timing(); |
|
343 } |
|
344 |
|
345 inline nsDOMNavigationTiming* |
|
346 nsPerformanceTiming::GetDOMTiming() const |
|
347 { |
|
348 return mPerformance->GetDOMTiming(); |
|
349 } |
|
350 |
|
351 #endif /* nsPerformance_h___ */ |
|
352 |