blob: ea7f88ee4555f0a56536ca74c4f70f57e0c84c94 [file] [log] [blame]
/*
* Copyright (C) 2010 Google, Inc. All Rights Reserved.
* Copyright (C) 2014-2017 Apple, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "HTTPHeaderMap.h"
#include <wtf/Optional.h>
#include <wtf/Seconds.h>
#include <wtf/persistence/PersistentDecoder.h>
#include <wtf/persistence/PersistentEncoder.h>
#include <wtf/text/WTFString.h>
#if PLATFORM(COCOA)
OBJC_CLASS NSDictionary;
#endif
namespace WebCore {
enum class NetworkLoadPriority : uint8_t {
Low,
Medium,
High,
Unknown,
};
class NetworkLoadMetrics {
public:
NetworkLoadMetrics()
{
reset();
}
NetworkLoadMetrics isolatedCopy() const
{
NetworkLoadMetrics copy;
copy.domainLookupStart = domainLookupStart;
copy.domainLookupEnd = domainLookupEnd;
copy.connectStart = connectStart;
copy.secureConnectionStart = secureConnectionStart;
copy.connectEnd = connectEnd;
copy.requestStart = requestStart;
copy.responseStart = responseStart;
copy.responseEnd = responseEnd;
copy.complete = complete;
copy.protocol = protocol.isolatedCopy();
copy.remoteAddress = remoteAddress.isolatedCopy();
copy.connectionIdentifier = connectionIdentifier.isolatedCopy();
copy.priority = priority;
copy.tlsProtocol = tlsProtocol.isolatedCopy();
copy.tlsCipher = tlsCipher.isolatedCopy();
copy.requestHeaders = requestHeaders.isolatedCopy();
copy.requestHeaderBytesSent = requestHeaderBytesSent;
copy.requestBodyBytesSent = requestBodyBytesSent;
copy.responseHeaderBytesReceived = responseHeaderBytesReceived;
copy.responseBodyBytesReceived = responseBodyBytesReceived;
copy.responseBodyDecodedSize = responseBodyDecodedSize;
return copy;
}
void reset()
{
domainLookupStart = Seconds(-1);
domainLookupEnd = Seconds(-1);
connectStart = Seconds(-1);
secureConnectionStart = Seconds(-1);
connectEnd = Seconds(-1);
requestStart = Seconds(0);
responseStart = Seconds(0);
responseEnd = Seconds(0);
complete = false;
protocol = String();
clearNonTimingData();
}
void clearNonTimingData()
{
remoteAddress = String();
connectionIdentifier = String();
priority = NetworkLoadPriority::Unknown;
tlsProtocol = String();
tlsCipher = String();
requestHeaders.clear();
requestHeaderBytesSent = std::numeric_limits<uint32_t>::max();
requestBodyBytesSent = std::numeric_limits<uint64_t>::max();
responseHeaderBytesReceived = std::numeric_limits<uint32_t>::max();
responseBodyBytesReceived = std::numeric_limits<uint64_t>::max();
responseBodyDecodedSize = std::numeric_limits<uint64_t>::max();
}
bool operator==(const NetworkLoadMetrics& other) const
{
return domainLookupStart == other.domainLookupStart
&& domainLookupEnd == other.domainLookupEnd
&& connectStart == other.connectStart
&& secureConnectionStart == other.secureConnectionStart
&& connectEnd == other.connectEnd
&& requestStart == other.requestStart
&& responseStart == other.responseStart
&& responseEnd == other.responseEnd
&& complete == other.complete
&& protocol == other.protocol
&& remoteAddress == other.remoteAddress
&& connectionIdentifier == other.connectionIdentifier
&& priority == other.priority
&& tlsProtocol == other.tlsProtocol
&& tlsCipher == other.tlsCipher
&& requestHeaders == other.requestHeaders
&& requestHeaderBytesSent == other.requestHeaderBytesSent
&& requestBodyBytesSent == other.requestBodyBytesSent
&& responseHeaderBytesReceived == other.responseHeaderBytesReceived
&& responseBodyBytesReceived == other.responseBodyBytesReceived
&& responseBodyDecodedSize == other.responseBodyDecodedSize;
}
bool operator!=(const NetworkLoadMetrics& other) const
{
return !(*this == other);
}
bool isComplete() const { return complete; }
void markComplete() { complete = true; }
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static bool decode(Decoder&, NetworkLoadMetrics&);
// These should be treated as deltas to LoadTiming's fetchStart.
// They should be in ascending order as listed here.
Seconds domainLookupStart; // -1 if no DNS.
Seconds domainLookupEnd; // -1 if no DNS.
Seconds connectStart; // -1 if reused connection.
Seconds secureConnectionStart; // -1 if no secure connection.
Seconds connectEnd; // -1 if reused connection.
Seconds requestStart;
Seconds responseStart;
Seconds responseEnd;
// ALPN Protocol ID: https://w3c.github.io/resource-timing/#bib-RFC7301
String protocol;
String remoteAddress;
String connectionIdentifier;
NetworkLoadPriority priority;
String tlsProtocol;
String tlsCipher;
// Whether or not all of the properties (0 or otherwise) have been set.
bool complete { false };
HTTPHeaderMap requestHeaders;
uint64_t requestHeaderBytesSent;
uint64_t responseHeaderBytesReceived;
uint64_t requestBodyBytesSent;
uint64_t responseBodyBytesReceived;
uint64_t responseBodyDecodedSize;
};
#if PLATFORM(COCOA)
WEBCORE_EXPORT void copyTimingData(NSDictionary *timingData, NetworkLoadMetrics&);
#endif
template<class Encoder>
void NetworkLoadMetrics::encode(Encoder& encoder) const
{
encoder << domainLookupStart;
encoder << domainLookupEnd;
encoder << connectStart;
encoder << secureConnectionStart;
encoder << connectEnd;
encoder << requestStart;
encoder << responseStart;
encoder << responseEnd;
encoder << complete;
encoder << protocol;
encoder << remoteAddress;
encoder << connectionIdentifier;
encoder << priority;
encoder << tlsProtocol;
encoder << tlsCipher;
encoder << requestHeaders;
encoder << requestHeaderBytesSent;
encoder << requestBodyBytesSent;
encoder << responseHeaderBytesReceived;
encoder << responseBodyBytesReceived;
encoder << responseBodyDecodedSize;
}
template<class Decoder>
bool NetworkLoadMetrics::decode(Decoder& decoder, NetworkLoadMetrics& metrics)
{
return decoder.decode(metrics.domainLookupStart)
&& decoder.decode(metrics.domainLookupEnd)
&& decoder.decode(metrics.connectStart)
&& decoder.decode(metrics.secureConnectionStart)
&& decoder.decode(metrics.connectEnd)
&& decoder.decode(metrics.requestStart)
&& decoder.decode(metrics.responseStart)
&& decoder.decode(metrics.responseEnd)
&& decoder.decode(metrics.complete)
&& decoder.decode(metrics.protocol)
&& decoder.decode(metrics.remoteAddress)
&& decoder.decode(metrics.connectionIdentifier)
&& decoder.decode(metrics.priority)
&& decoder.decode(metrics.tlsProtocol)
&& decoder.decode(metrics.tlsCipher)
&& decoder.decode(metrics.requestHeaders)
&& decoder.decode(metrics.requestHeaderBytesSent)
&& decoder.decode(metrics.requestBodyBytesSent)
&& decoder.decode(metrics.responseHeaderBytesReceived)
&& decoder.decode(metrics.responseBodyBytesReceived)
&& decoder.decode(metrics.responseBodyDecodedSize);
}
} // namespace WebCore
// NetworkLoadMetrics should not be stored by the WTF::Persistence::Decoder.
namespace WTF {
namespace Persistence {
template<> struct Coder<Optional<WebCore::NetworkLoadPriority>> {
static NO_RETURN_DUE_TO_ASSERT void encode(Encoder&, const Optional<WebCore::NetworkLoadPriority>&)
{
ASSERT_NOT_REACHED();
}
static bool decode(Decoder&, Optional<WebCore::NetworkLoadPriority>&)
{
ASSERT_NOT_REACHED();
return false;
}
};
}} // namespace WTF::Persistence