1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is implementation of Web Timing draft specification
16 : * http://dev.w3.org/2006/webapi/WebTiming/
17 : *
18 : * The Initial Developer of the Original Code is Google Inc.
19 : * Portions created by the Initial Developer are Copyright (C) 2010
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Sergey Novikov <sergeyn@google.com> (original author)
24 : * Igor Bazarny <igor.bazarny@gmail.com> (lots of improvements)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsDOMNavigationTiming.h"
41 : #include "nsCOMPtr.h"
42 : #include "nscore.h"
43 : #include "TimeStamp.h"
44 : #include "nsContentUtils.h"
45 :
46 : #include "nsIDOMEventTarget.h"
47 : #include "nsIDocument.h"
48 : #include "nsIScriptSecurityManager.h"
49 :
50 0 : nsDOMNavigationTiming::nsDOMNavigationTiming()
51 : {
52 0 : Clear();
53 0 : }
54 :
55 0 : nsDOMNavigationTiming::~nsDOMNavigationTiming()
56 : {
57 0 : }
58 :
59 : void
60 0 : nsDOMNavigationTiming::Clear()
61 : {
62 0 : mNavigationType = nsIDOMPerformanceNavigation::TYPE_RESERVED;
63 0 : mNavigationStart = 0;
64 0 : mFetchStart = 0;
65 0 : mRedirectStart = 0;
66 0 : mRedirectEnd = 0;
67 0 : mRedirectCount = 0;
68 0 : mBeforeUnloadStart = 0;
69 0 : mUnloadStart = 0;
70 0 : mUnloadEnd = 0;
71 0 : mLoadEventStart = 0;
72 0 : mLoadEventEnd = 0;
73 0 : mDOMLoading = 0;
74 0 : mDOMInteractive = 0;
75 0 : mDOMContentLoadedEventStart = 0;
76 0 : mDOMContentLoadedEventEnd = 0;
77 0 : mDOMComplete = 0;
78 0 : mRedirectCheck = NOT_CHECKED;
79 0 : }
80 :
81 : nsresult
82 0 : nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp,
83 : DOMTimeMilliSec* aResult)
84 : {
85 0 : if (aStamp.IsNull()) {
86 0 : *aResult = 0;
87 0 : return NS_OK;
88 : }
89 0 : mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
90 0 : *aResult = mNavigationStart + static_cast<PRInt32>(duration.ToMilliseconds());
91 0 : return NS_OK;
92 : }
93 :
94 : nsresult
95 0 : nsDOMNavigationTiming::TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp,
96 : DOMTimeMilliSec* aResult)
97 : {
98 0 : if (!aStamp.IsNull()) {
99 0 : return TimeStampToDOM(aStamp, aResult);
100 : } else {
101 0 : return GetFetchStart(aResult);
102 : }
103 : }
104 :
105 0 : DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart(){
106 : DOMTimeMilliSec result;
107 0 : TimeStampToDOM(mozilla::TimeStamp::Now(), &result);
108 0 : return result;
109 : }
110 :
111 : void
112 0 : nsDOMNavigationTiming::NotifyNavigationStart()
113 : {
114 0 : mNavigationStart = PR_Now() / PR_USEC_PER_MSEC;
115 0 : mNavigationStartTimeStamp = mozilla::TimeStamp::Now();
116 0 : }
117 :
118 : void
119 0 : nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, nsDOMPerformanceNavigationType aNavigationType)
120 : {
121 0 : mFetchStart = DurationFromStart();
122 0 : mNavigationType = aNavigationType;
123 : // At the unload event time we don't really know the loading uri.
124 : // Need it for later check for unload timing access.
125 0 : mLoadedURI = aURI;
126 0 : }
127 :
128 : void
129 0 : nsDOMNavigationTiming::NotifyRedirect(nsIURI* aOldURI, nsIURI* aNewURI)
130 : {
131 0 : if (mRedirects.Count() == 0) {
132 0 : mRedirectStart = mFetchStart;
133 : }
134 0 : mFetchStart = DurationFromStart();
135 0 : mRedirectEnd = mFetchStart;
136 :
137 : // At the unload event time we don't really know the loading uri.
138 : // Need it for later check for unload timing access.
139 0 : mLoadedURI = aNewURI;
140 :
141 0 : mRedirects.AppendObject(aOldURI);
142 0 : }
143 :
144 : void
145 0 : nsDOMNavigationTiming::NotifyBeforeUnload()
146 : {
147 0 : mBeforeUnloadStart = DurationFromStart();
148 0 : }
149 :
150 : void
151 0 : nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI)
152 : {
153 0 : mUnloadStart = mBeforeUnloadStart;
154 0 : mUnloadedURI = aOldURI;
155 0 : }
156 :
157 : void
158 0 : nsDOMNavigationTiming::NotifyUnloadEventStart()
159 : {
160 0 : mUnloadStart = DurationFromStart();
161 0 : }
162 :
163 : void
164 0 : nsDOMNavigationTiming::NotifyUnloadEventEnd()
165 : {
166 0 : mUnloadEnd = DurationFromStart();
167 0 : }
168 :
169 : void
170 0 : nsDOMNavigationTiming::NotifyLoadEventStart()
171 : {
172 0 : mLoadEventStart = DurationFromStart();
173 0 : }
174 :
175 : void
176 0 : nsDOMNavigationTiming::NotifyLoadEventEnd()
177 : {
178 0 : mLoadEventEnd = DurationFromStart();
179 0 : }
180 :
181 : bool
182 0 : nsDOMNavigationTiming::ReportRedirects()
183 : {
184 0 : if (mRedirectCheck == NOT_CHECKED) {
185 0 : mRedirectCount = mRedirects.Count();
186 0 : if (mRedirects.Count() == 0) {
187 0 : mRedirectCheck = NO_REDIRECTS;
188 : } else {
189 0 : mRedirectCheck = CHECK_PASSED;
190 0 : nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
191 0 : for (int i = mRedirects.Count() - 1; i >= 0; --i) {
192 0 : nsIURI * curr = mRedirects[i];
193 0 : nsresult rv = ssm->CheckSameOriginURI(curr, mLoadedURI, false);
194 0 : if (!NS_SUCCEEDED(rv)) {
195 0 : mRedirectCheck = CHECK_FAILED;
196 0 : mRedirectCount = 0;
197 0 : break;
198 : }
199 : }
200 : // All we need to know is in mRedirectCheck now. Clear history.
201 0 : mRedirects.Clear();
202 : }
203 : }
204 0 : return mRedirectCheck == CHECK_PASSED;
205 : }
206 :
207 : void
208 0 : nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
209 : {
210 0 : mLoadedURI = aURI;
211 0 : TimeStampToDOM(aValue, &mDOMLoading);
212 0 : }
213 :
214 : void
215 0 : nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
216 : {
217 0 : mLoadedURI = aURI;
218 0 : mDOMLoading = DurationFromStart();
219 0 : }
220 :
221 : void
222 0 : nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
223 : {
224 0 : mLoadedURI = aURI;
225 0 : mDOMInteractive = DurationFromStart();
226 0 : }
227 :
228 : void
229 0 : nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
230 : {
231 0 : mLoadedURI = aURI;
232 0 : mDOMComplete = DurationFromStart();
233 0 : }
234 :
235 : void
236 0 : nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
237 : {
238 0 : mLoadedURI = aURI;
239 0 : mDOMContentLoadedEventStart = DurationFromStart();
240 0 : }
241 :
242 : void
243 0 : nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
244 : {
245 0 : mLoadedURI = aURI;
246 0 : mDOMContentLoadedEventEnd = DurationFromStart();
247 0 : }
248 :
249 : nsresult
250 0 : nsDOMNavigationTiming::GetType(
251 : nsDOMPerformanceNavigationType* aNavigationType)
252 : {
253 0 : *aNavigationType = mNavigationType;
254 0 : return NS_OK;
255 : }
256 :
257 : nsresult
258 0 : nsDOMNavigationTiming::GetRedirectCount(PRUint16* aRedirectCount)
259 : {
260 0 : *aRedirectCount = 0;
261 0 : if (ReportRedirects()) {
262 0 : *aRedirectCount = mRedirectCount;
263 : }
264 0 : return NS_OK;
265 : }
266 :
267 : nsresult
268 0 : nsDOMNavigationTiming::GetRedirectStart(DOMTimeMilliSec* aRedirectStart)
269 : {
270 0 : *aRedirectStart = 0;
271 0 : if (ReportRedirects()) {
272 0 : *aRedirectStart = mRedirectStart;
273 : }
274 0 : return NS_OK;
275 : }
276 :
277 : nsresult
278 0 : nsDOMNavigationTiming::GetRedirectEnd(DOMTimeMilliSec* aEnd)
279 : {
280 0 : *aEnd = 0;
281 0 : if (ReportRedirects()) {
282 0 : *aEnd = mRedirectEnd;
283 : }
284 0 : return NS_OK;
285 : }
286 :
287 : nsresult
288 0 : nsDOMNavigationTiming::GetNavigationStart(DOMTimeMilliSec* aNavigationStart)
289 : {
290 0 : *aNavigationStart = mNavigationStart;
291 0 : return NS_OK;
292 : }
293 :
294 : nsresult
295 0 : nsDOMNavigationTiming::GetUnloadEventStart(DOMTimeMilliSec* aStart)
296 : {
297 0 : *aStart = 0;
298 0 : nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
299 0 : nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
300 0 : if (NS_SUCCEEDED(rv)) {
301 0 : *aStart = mUnloadStart;
302 : }
303 0 : return NS_OK;
304 : }
305 :
306 : nsresult
307 0 : nsDOMNavigationTiming::GetUnloadEventEnd(DOMTimeMilliSec* aEnd)
308 : {
309 0 : *aEnd = 0;
310 0 : nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
311 0 : nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
312 0 : if (NS_SUCCEEDED(rv)) {
313 0 : *aEnd = mUnloadEnd;
314 : }
315 0 : return NS_OK;
316 : }
317 :
318 : nsresult
319 0 : nsDOMNavigationTiming::GetFetchStart(DOMTimeMilliSec* aStart)
320 : {
321 0 : *aStart = mFetchStart;
322 0 : return NS_OK;
323 : }
324 :
325 : nsresult
326 0 : nsDOMNavigationTiming::GetDomLoading(DOMTimeMilliSec* aTime)
327 : {
328 0 : *aTime = mDOMLoading;
329 0 : return NS_OK;
330 : }
331 :
332 : nsresult
333 0 : nsDOMNavigationTiming::GetDomInteractive(DOMTimeMilliSec* aTime)
334 : {
335 0 : *aTime = mDOMInteractive;
336 0 : return NS_OK;
337 : }
338 :
339 : nsresult
340 0 : nsDOMNavigationTiming::GetDomContentLoadedEventStart(DOMTimeMilliSec* aStart)
341 : {
342 0 : *aStart = mDOMContentLoadedEventStart;
343 0 : return NS_OK;
344 : }
345 :
346 : nsresult
347 0 : nsDOMNavigationTiming::GetDomContentLoadedEventEnd(DOMTimeMilliSec* aEnd)
348 : {
349 0 : *aEnd = mDOMContentLoadedEventEnd;
350 0 : return NS_OK;
351 : }
352 :
353 : nsresult
354 0 : nsDOMNavigationTiming::GetDomComplete(DOMTimeMilliSec* aTime)
355 : {
356 0 : *aTime = mDOMComplete;
357 0 : return NS_OK;
358 : }
359 :
360 : nsresult
361 0 : nsDOMNavigationTiming::GetLoadEventStart(DOMTimeMilliSec* aStart)
362 : {
363 0 : *aStart = mLoadEventStart;
364 0 : return NS_OK;
365 : }
366 :
367 : nsresult
368 0 : nsDOMNavigationTiming::GetLoadEventEnd(DOMTimeMilliSec* aEnd)
369 : {
370 0 : *aEnd = mLoadEventEnd;
371 0 : return NS_OK;
372 : }
|