1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_PerformanceResourceTiming_h___
8 #define mozilla_dom_PerformanceResourceTiming_h___
9 
10 #include "mozilla/UniquePtr.h"
11 #include "nsCOMPtr.h"
12 #include "Performance.h"
13 #include "PerformanceEntry.h"
14 #include "PerformanceServerTiming.h"
15 #include "PerformanceTiming.h"
16 
17 namespace mozilla {
18 namespace dom {
19 
20 // http://www.w3.org/TR/resource-timing/#performanceresourcetiming
21 class PerformanceResourceTiming : public PerformanceEntry {
22  public:
23   typedef mozilla::TimeStamp TimeStamp;
24 
25   NS_DECL_ISUPPORTS_INHERITED
26   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
27       PerformanceResourceTiming, PerformanceEntry)
28 
29   PerformanceResourceTiming(
30       UniquePtr<PerformanceTimingData>&& aPerformanceTimingData,
31       Performance* aPerformance, const nsAString& aName);
32 
33   virtual JSObject* WrapObject(JSContext* aCx,
34                                JS::Handle<JSObject*> aGivenProto) override;
35 
36   virtual DOMHighResTimeStamp StartTime() const override;
37 
Duration()38   virtual DOMHighResTimeStamp Duration() const override {
39     return ResponseEnd() - StartTime();
40   }
41 
GetInitiatorType(nsAString & aInitiatorType)42   void GetInitiatorType(nsAString& aInitiatorType) const {
43     aInitiatorType = mInitiatorType;
44   }
45 
SetInitiatorType(const nsAString & aInitiatorType)46   void SetInitiatorType(const nsAString& aInitiatorType) {
47     mInitiatorType = aInitiatorType;
48   }
49 
GetNextHopProtocol(nsAString & aNextHopProtocol)50   void GetNextHopProtocol(nsAString& aNextHopProtocol) const {
51     if (mTimingData) {
52       aNextHopProtocol = mTimingData->NextHopProtocol();
53     }
54   }
55 
WorkerStart()56   DOMHighResTimeStamp WorkerStart() const {
57     return mTimingData ? mTimingData->WorkerStartHighRes(mPerformance) : 0;
58   }
59 
FetchStart()60   DOMHighResTimeStamp FetchStart() const {
61     return mTimingData ? mTimingData->FetchStartHighRes(mPerformance) : 0;
62   }
63 
RedirectStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)64   DOMHighResTimeStamp RedirectStart(
65       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
66     // We have to check if all the redirect URIs had the same origin (since
67     // there is no check in RedirectStartHighRes())
68     return ReportRedirectForCaller(aSubjectPrincipal)
69                ? mTimingData->RedirectStartHighRes(mPerformance)
70                : 0;
71   }
72 
RedirectEnd(Maybe<nsIPrincipal * > & aSubjectPrincipal)73   DOMHighResTimeStamp RedirectEnd(
74       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
75     // We have to check if all the redirect URIs had the same origin (since
76     // there is no check in RedirectEndHighRes())
77     return ReportRedirectForCaller(aSubjectPrincipal)
78                ? mTimingData->RedirectEndHighRes(mPerformance)
79                : 0;
80   }
81 
DomainLookupStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)82   DOMHighResTimeStamp DomainLookupStart(
83       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
84     return TimingAllowedForCaller(aSubjectPrincipal)
85                ? mTimingData->DomainLookupStartHighRes(mPerformance)
86                : 0;
87   }
88 
DomainLookupEnd(Maybe<nsIPrincipal * > & aSubjectPrincipal)89   DOMHighResTimeStamp DomainLookupEnd(
90       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
91     return TimingAllowedForCaller(aSubjectPrincipal)
92                ? mTimingData->DomainLookupEndHighRes(mPerformance)
93                : 0;
94   }
95 
ConnectStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)96   DOMHighResTimeStamp ConnectStart(
97       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
98     return TimingAllowedForCaller(aSubjectPrincipal)
99                ? mTimingData->ConnectStartHighRes(mPerformance)
100                : 0;
101   }
102 
ConnectEnd(Maybe<nsIPrincipal * > & aSubjectPrincipal)103   DOMHighResTimeStamp ConnectEnd(
104       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
105     return TimingAllowedForCaller(aSubjectPrincipal)
106                ? mTimingData->ConnectEndHighRes(mPerformance)
107                : 0;
108   }
109 
RequestStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)110   DOMHighResTimeStamp RequestStart(
111       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
112     return TimingAllowedForCaller(aSubjectPrincipal)
113                ? mTimingData->RequestStartHighRes(mPerformance)
114                : 0;
115   }
116 
ResponseStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)117   DOMHighResTimeStamp ResponseStart(
118       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
119     return TimingAllowedForCaller(aSubjectPrincipal)
120                ? mTimingData->ResponseStartHighRes(mPerformance)
121                : 0;
122   }
123 
ResponseEnd()124   DOMHighResTimeStamp ResponseEnd() const {
125     return mTimingData ? mTimingData->ResponseEndHighRes(mPerformance) : 0;
126   }
127 
SecureConnectionStart(Maybe<nsIPrincipal * > & aSubjectPrincipal)128   DOMHighResTimeStamp SecureConnectionStart(
129       Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
130     return TimingAllowedForCaller(aSubjectPrincipal)
131                ? mTimingData->SecureConnectionStartHighRes(mPerformance)
132                : 0;
133   }
134 
ToResourceTiming()135   virtual const PerformanceResourceTiming* ToResourceTiming() const override {
136     return this;
137   }
138 
TransferSize(Maybe<nsIPrincipal * > & aSubjectPrincipal)139   uint64_t TransferSize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
140     return TimingAllowedForCaller(aSubjectPrincipal)
141                ? mTimingData->TransferSize()
142                : 0;
143   }
144 
EncodedBodySize(Maybe<nsIPrincipal * > & aSubjectPrincipal)145   uint64_t EncodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
146     return TimingAllowedForCaller(aSubjectPrincipal)
147                ? mTimingData->EncodedBodySize()
148                : 0;
149   }
150 
DecodedBodySize(Maybe<nsIPrincipal * > & aSubjectPrincipal)151   uint64_t DecodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
152     return TimingAllowedForCaller(aSubjectPrincipal)
153                ? mTimingData->DecodedBodySize()
154                : 0;
155   }
156 
157   void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval,
158                        Maybe<nsIPrincipal*>& aSubjectPrincipal);
159 
160   size_t SizeOfIncludingThis(
161       mozilla::MallocSizeOf aMallocSizeOf) const override;
162 
163  protected:
164   virtual ~PerformanceResourceTiming();
165 
166   size_t SizeOfExcludingThis(
167       mozilla::MallocSizeOf aMallocSizeOf) const override;
168 
169   // Check if caller has access to cross-origin timings, either by the rules
170   // from the spec, or based on addon permissions.
171   bool TimingAllowedForCaller(Maybe<nsIPrincipal*>& aCaller) const;
172 
173   // Check if cross-origin redirects should be reported to the caller.
174   bool ReportRedirectForCaller(Maybe<nsIPrincipal*>& aCaller) const;
175 
176   nsString mInitiatorType;
177   UniquePtr<PerformanceTimingData> mTimingData;
178   RefPtr<Performance> mPerformance;
179 
180   // The same initial requested URI as the `name` attribute.
181   nsCOMPtr<nsIURI> mOriginalURI;
182 };
183 
184 }  // namespace dom
185 }  // namespace mozilla
186 
187 #endif /* mozilla_dom_PerformanceResourceTiming_h___ */
188