[Resource Timing] Gather timing information with reliable responseEnd time
[WebKit-https.git] / Source / WebCore / loader / ResourceTiming.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ResourceTiming.h"
28
29 #include "CachedResource.h"
30 #include "SecurityOrigin.h"
31
32 namespace WebCore {
33
34 static bool passesTimingAllowCheck(const ResourceResponse& response, const SecurityOrigin& initiatorSecurityOrigin)
35 {
36     Ref<SecurityOrigin> resourceOrigin = SecurityOrigin::create(response.url());
37     if (resourceOrigin->isSameSchemeHostPort(initiatorSecurityOrigin))
38         return true;
39
40     const String& timingAllowOriginString = response.httpHeaderField(HTTPHeaderName::TimingAllowOrigin);
41     if (timingAllowOriginString.isEmpty() || equalLettersIgnoringASCIICase(timingAllowOriginString, "null"))
42         return false;
43
44     if (timingAllowOriginString == "*")
45         return true;
46
47     const String& securityOrigin = initiatorSecurityOrigin.toString();
48     Vector<String> timingAllowOrigins;
49     timingAllowOriginString.split(',', timingAllowOrigins);
50     for (auto& origin : timingAllowOrigins) {
51         if (origin.stripWhiteSpace() == securityOrigin)
52             return true;
53     }
54
55     return false;
56 }
57
58 ResourceTiming ResourceTiming::fromCache(const URL& url, const String& initiator, const LoadTiming& loadTiming)
59 {
60     return ResourceTiming(url, initiator, loadTiming);
61 }
62
63 ResourceTiming ResourceTiming::fromLoad(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const SecurityOrigin& securityOrigin)
64 {
65     return ResourceTiming(resource, initiator, loadTiming, networkLoadMetrics, securityOrigin);
66 }
67
68 ResourceTiming ResourceTiming::fromSynchronousLoad(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
69 {
70     return ResourceTiming(url, initiator, loadTiming, networkLoadMetrics, response, securityOrigin);
71 }
72
73 ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming)
74     : m_url(url)
75     , m_initiator(initiator)
76     , m_loadTiming(loadTiming)
77     , m_allowTimingDetails(true)
78 {
79 }
80
81 ResourceTiming::ResourceTiming(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const SecurityOrigin& securityOrigin)
82     : m_url(resource.resourceRequest().url())
83     , m_initiator(initiator)
84     , m_loadTiming(loadTiming)
85     , m_networkLoadMetrics(networkLoadMetrics)
86     , m_allowTimingDetails(passesTimingAllowCheck(resource.response(), securityOrigin))
87 {
88 }
89
90 ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
91     : m_url(url)
92     , m_initiator(initiator)
93     , m_loadTiming(loadTiming)
94     , m_networkLoadMetrics(networkLoadMetrics)
95     , m_allowTimingDetails(passesTimingAllowCheck(response, securityOrigin))
96 {
97 }
98
99 ResourceTiming ResourceTiming::isolatedCopy() const
100 {
101     return ResourceTiming(m_url.isolatedCopy(), m_initiator.isolatedCopy(), m_loadTiming.isolatedCopy(), m_networkLoadMetrics.isolatedCopy(), m_allowTimingDetails);
102 }
103
104 } // namespace WebCore