Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / timing / Performance.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "core/timing/Performance.h"
34
35 #include "core/dom/Document.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/loader/DocumentLoader.h"
38 #include "core/timing/ResourceTimingInfo.h"
39 #include "core/timing/PerformanceResourceTiming.h"
40 #include "core/timing/PerformanceUserTiming.h"
41 #include "platform/weborigin/SecurityOrigin.h"
42 #include "wtf/CurrentTime.h"
43
44 namespace blink {
45
46 static const size_t defaultResourceTimingBufferSize = 150;
47
48 Performance::Performance(LocalFrame* frame)
49     : DOMWindowProperty(frame)
50     , m_resourceTimingBufferSize(defaultResourceTimingBufferSize)
51     , m_referenceTime(frame && frame->host() ? frame->document()->loader()->timing()->referenceMonotonicTime() : 0.0)
52     , m_userTiming(nullptr)
53 {
54 }
55
56 Performance::~Performance()
57 {
58 }
59
60 const AtomicString& Performance::interfaceName() const
61 {
62     return EventTargetNames::Performance;
63 }
64
65 ExecutionContext* Performance::executionContext() const
66 {
67     if (!frame())
68         return nullptr;
69     return frame()->document();
70 }
71
72 PassRefPtrWillBeRawPtr<MemoryInfo> Performance::memory() const
73 {
74     return MemoryInfo::create();
75 }
76
77 PerformanceNavigation* Performance::navigation() const
78 {
79     if (!m_navigation)
80         m_navigation = PerformanceNavigation::create(m_frame);
81
82     return m_navigation.get();
83 }
84
85 PerformanceTiming* Performance::timing() const
86 {
87     if (!m_timing)
88         m_timing = PerformanceTiming::create(m_frame);
89
90     return m_timing.get();
91 }
92
93 PerformanceEntryVector Performance::getEntries() const
94 {
95     PerformanceEntryVector entries;
96
97     entries.appendVector(m_resourceTimingBuffer);
98
99     if (m_userTiming) {
100         entries.appendVector(m_userTiming->getMarks());
101         entries.appendVector(m_userTiming->getMeasures());
102     }
103
104     std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
105     return entries;
106 }
107
108 PerformanceEntryVector Performance::getEntriesByType(const String& entryType)
109 {
110     PerformanceEntryVector entries;
111
112     if (equalIgnoringCase(entryType, "resource")) {
113         for (const auto& resource : m_resourceTimingBuffer)
114             entries.append(resource);
115     }
116
117     if (m_userTiming) {
118         if (equalIgnoringCase(entryType, "mark"))
119             entries.appendVector(m_userTiming->getMarks());
120         else if (equalIgnoringCase(entryType, "measure"))
121             entries.appendVector(m_userTiming->getMeasures());
122     }
123
124     std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
125     return entries;
126 }
127
128 PerformanceEntryVector Performance::getEntriesByName(const String& name, const String& entryType)
129 {
130     PerformanceEntryVector entries;
131
132     if (entryType.isNull() || equalIgnoringCase(entryType, "resource")) {
133         for (const auto& resource : m_resourceTimingBuffer) {
134             if (resource->name() == name)
135                 entries.append(resource);
136         }
137     }
138
139     if (m_userTiming) {
140         if (entryType.isNull() || equalIgnoringCase(entryType, "mark"))
141             entries.appendVector(m_userTiming->getMarks(name));
142         if (entryType.isNull() || equalIgnoringCase(entryType, "measure"))
143             entries.appendVector(m_userTiming->getMeasures(name));
144     }
145
146     std::sort(entries.begin(), entries.end(), PerformanceEntry::startTimeCompareLessThan);
147     return entries;
148 }
149
150 void Performance::webkitClearResourceTimings()
151 {
152     m_resourceTimingBuffer.clear();
153 }
154
155 void Performance::webkitSetResourceTimingBufferSize(unsigned size)
156 {
157     m_resourceTimingBufferSize = size;
158     if (isResourceTimingBufferFull())
159         dispatchEvent(Event::create(EventTypeNames::webkitresourcetimingbufferfull));
160 }
161
162 static bool passesTimingAllowCheck(const ResourceResponse& response, Document* requestingDocument, const AtomicString& originalTimingAllowOrigin)
163 {
164     AtomicallyInitializedStatic(AtomicString&, timingAllowOrigin = *new AtomicString("timing-allow-origin"));
165
166     RefPtr<SecurityOrigin> resourceOrigin = SecurityOrigin::create(response.url());
167     if (resourceOrigin->isSameSchemeHostPort(requestingDocument->securityOrigin()))
168         return true;
169
170     const AtomicString& timingAllowOriginString = originalTimingAllowOrigin.isEmpty() ? response.httpHeaderField(timingAllowOrigin) : originalTimingAllowOrigin;
171     if (timingAllowOriginString.isEmpty() || equalIgnoringCase(timingAllowOriginString, "null"))
172         return false;
173
174     if (timingAllowOriginString == starAtom)
175         return true;
176
177     const String& securityOrigin = requestingDocument->securityOrigin()->toString();
178     Vector<String> timingAllowOrigins;
179     timingAllowOriginString.string().split(' ', timingAllowOrigins);
180     for (const String& allowOrigin : timingAllowOrigins) {
181         if (allowOrigin == securityOrigin)
182             return true;
183     }
184
185     return false;
186 }
187
188 static bool allowsTimingRedirect(const Vector<ResourceResponse>& redirectChain, const ResourceResponse& finalResponse, Document* initiatorDocument)
189 {
190     if (!passesTimingAllowCheck(finalResponse, initiatorDocument, emptyAtom))
191         return false;
192
193     for (const ResourceResponse& response : redirectChain) {
194         if (!passesTimingAllowCheck(response, initiatorDocument, emptyAtom))
195             return false;
196     }
197
198     return true;
199 }
200
201 void Performance::addResourceTiming(const ResourceTimingInfo& info, Document* initiatorDocument)
202 {
203     if (isResourceTimingBufferFull())
204         return;
205
206     const ResourceResponse& finalResponse = info.finalResponse();
207     bool allowTimingDetails = passesTimingAllowCheck(finalResponse, initiatorDocument, info.originalTimingAllowOrigin());
208     double startTime = info.initialTime();
209
210     if (info.redirectChain().isEmpty()) {
211         RefPtrWillBeRawPtr<PerformanceEntry> entry = PerformanceResourceTiming::create(info, initiatorDocument, startTime, allowTimingDetails);
212         addResourceTimingBuffer(entry);
213         return;
214     }
215
216     const Vector<ResourceResponse>& redirectChain = info.redirectChain();
217     bool allowRedirectDetails = allowsTimingRedirect(redirectChain, finalResponse, initiatorDocument);
218
219     if (!allowRedirectDetails) {
220         ResourceLoadTiming* finalTiming = finalResponse.resourceLoadTiming();
221         ASSERT(finalTiming);
222         if (finalTiming)
223             startTime = finalTiming->requestTime;
224     }
225
226     ResourceLoadTiming* lastRedirectTiming = redirectChain.last().resourceLoadTiming();
227     ASSERT(lastRedirectTiming);
228     double lastRedirectEndTime = lastRedirectTiming->receiveHeadersEnd;
229
230     RefPtrWillBeRawPtr<PerformanceEntry> entry = PerformanceResourceTiming::create(info, initiatorDocument, startTime, lastRedirectEndTime, allowTimingDetails, allowRedirectDetails);
231     addResourceTimingBuffer(entry);
232 }
233
234 void Performance::addResourceTimingBuffer(PassRefPtrWillBeRawPtr<PerformanceEntry> entry)
235 {
236     m_resourceTimingBuffer.append(entry);
237
238     if (isResourceTimingBufferFull())
239         dispatchEvent(Event::create(EventTypeNames::webkitresourcetimingbufferfull));
240 }
241
242 bool Performance::isResourceTimingBufferFull()
243 {
244     return m_resourceTimingBuffer.size() >= m_resourceTimingBufferSize;
245 }
246
247 void Performance::mark(const String& markName, ExceptionState& exceptionState)
248 {
249     if (!m_userTiming)
250         m_userTiming = UserTiming::create(this);
251     m_userTiming->mark(markName, exceptionState);
252 }
253
254 void Performance::clearMarks(const String& markName)
255 {
256     if (!m_userTiming)
257         m_userTiming = UserTiming::create(this);
258     m_userTiming->clearMarks(markName);
259 }
260
261 void Performance::measure(const String& measureName, const String& startMark, const String& endMark, ExceptionState& exceptionState)
262 {
263     if (!m_userTiming)
264         m_userTiming = UserTiming::create(this);
265     m_userTiming->measure(measureName, startMark, endMark, exceptionState);
266 }
267
268 void Performance::clearMeasures(const String& measureName)
269 {
270     if (!m_userTiming)
271         m_userTiming = UserTiming::create(this);
272     m_userTiming->clearMeasures(measureName);
273 }
274
275 double Performance::now() const
276 {
277     return 1000.0 * (monotonicallyIncreasingTime() - m_referenceTime);
278 }
279
280 void Performance::trace(Visitor* visitor)
281 {
282     visitor->trace(m_navigation);
283     visitor->trace(m_timing);
284     visitor->trace(m_resourceTimingBuffer);
285     visitor->trace(m_userTiming);
286     EventTargetWithInlineData::trace(visitor);
287     DOMWindowProperty::trace(visitor);
288 }
289
290 } // namespace blink