--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -232,16 +232,20 @@ netmonitor.waterfall.tooltip.total=Total
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.blocked): This is part of the tooltip
# displayed in the requests waterfall for blocked time (in milliseconds).
netmonitor.waterfall.tooltip.blocked=Blocked %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.dns): This is part of the tooltip
# displayed in the requests waterfall for dns time (in milliseconds).
netmonitor.waterfall.tooltip.dns=DNS %S ms
+# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.ssl): This is part of the tooltip
+# displayed in the requests waterfall for tls setup time (in milliseconds).
+netmonitor.waterfall.tooltip.ssl=TLS %S ms
+
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.connect): This is part of the tooltip
# displayed in the requests waterfall for connect time (in milliseconds).
netmonitor.waterfall.tooltip.connect=Connect %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.send): This is part of the tooltip
# displayed in the requests waterfall for send time (in milliseconds).
netmonitor.waterfall.tooltip.send=Send %S ms
@@ -704,16 +708,21 @@ netmonitor.response.mime=MIME Type:
# in a "blocked" state.
netmonitor.timings.blocked=Blocked:
# LOCALIZATION NOTE (netmonitor.timings.dns): This is the label displayed
# in the network details timings tab identifying the amount of time spent
# in a "dns" state.
netmonitor.timings.dns=DNS resolution:
+# LOCALIZATION NOTE (netmonitor.timings.ssl): This is the label displayed
+# in the network details timings tab identifying the amount of time spent
+# in a "tls" handshake state.
+netmonitor.timings.ssl=TLS setup:
+
# LOCALIZATION NOTE (netmonitor.timings.connect): This is the label displayed
# in the network details timings tab identifying the amount of time spent
# in a "connect" state.
netmonitor.timings.connect=Connecting:
# LOCALIZATION NOTE (netmonitor.timings.send): This is the label displayed
# in the network details timings tab identifying the amount of time spent
# in a "send" state.
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css
+++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css
@@ -14,31 +14,33 @@
@import "chrome://devtools/content/sourceeditor/codemirror/mozilla.css";
:root.theme-dark {
--table-splitter-color: rgba(255,255,255,0.15);
--table-zebra-background: rgba(255,255,255,0.05);
--timing-blocked-color: rgba(235, 83, 104, 0.8);
--timing-dns-color: rgba(223, 128, 255, 0.8); /* pink */
+ --timing-ssl-color: rgba(217, 102, 41, 0.8); /* orange */
--timing-connect-color: rgba(217, 102, 41, 0.8); /* orange */
--timing-send-color: rgba(70, 175, 227, 0.8); /* light blue */
--timing-wait-color: rgba(94, 136, 176, 0.8); /* blue grey */
--timing-receive-color: rgba(112, 191, 83, 0.8); /* green */
--sort-ascending-image: url(chrome://devtools/skin/images/sort-ascending-arrow.svg);
--sort-descending-image: url(chrome://devtools/skin/images/sort-descending-arrow.svg);
}
:root.theme-light {
--table-splitter-color: rgba(0,0,0,0.15);
--table-zebra-background: rgba(0,0,0,0.05);
--timing-blocked-color: rgba(235, 83, 104, 0.8);
--timing-dns-color: rgba(223, 128, 255, 0.8); /* pink */
+ --timing-ssl-color: rgba(217, 102, 41, 0.8); /* orange */
--timing-connect-color: rgba(217, 102, 41, 0.8); /* orange */
--timing-send-color: rgba(0, 136, 204, 0.8); /* blue */
--timing-wait-color: rgba(95, 136, 176, 0.8); /* blue grey */
--timing-receive-color: rgba(44, 187, 15, 0.8); /* green */
--sort-ascending-image: url(chrome://devtools/skin/images/sort-ascending-arrow.svg);
--sort-descending-image: url(chrome://devtools/skin/images/sort-descending-arrow.svg);
}
@@ -676,16 +678,20 @@ body,
.requests-list-timings-box.dns {
background-color: var(--timing-dns-color);
}
.requests-list-timings-box.connect {
background-color: var(--timing-connect-color);
}
+.requests-list-timings-box.ssl {
+ background-color: var(--timing-ssl-color);
+}
+
.requests-list-timings-box.send {
background-color: var(--timing-send-color);
}
.requests-list-timings-box.wait {
background-color: var(--timing-wait-color);
}
--- a/devtools/client/netmonitor/src/components/request-list-column-waterfall.js
+++ b/devtools/client/netmonitor/src/components/request-list-column-waterfall.js
@@ -16,17 +16,17 @@ const { div } = DOM;
const UPDATED_WATERFALL_PROPS = [
"eventTimings",
"fromCache",
"fromServiceWorker",
"totalTime",
];
// List of properties of the timing info we want to create boxes for
-const TIMING_KEYS = ["blocked", "dns", "connect", "send", "wait", "receive"];
+const TIMING_KEYS = ["blocked", "dns", "connect", "ssl", "send", "wait", "receive"];
const RequestListColumnWaterfall = createClass({
displayName: "RequestListColumnWaterfall",
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
--- a/devtools/client/netmonitor/src/components/timings-panel.js
+++ b/devtools/client/netmonitor/src/components/timings-panel.js
@@ -7,17 +7,17 @@
const { DOM, PropTypes } = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils/l10n");
const { getNetMonitorTimingsURL } = require("../utils/mdn-utils");
// Components
const MDNLink = require("./mdn-link");
const { div, span } = DOM;
-const types = ["blocked", "dns", "connect", "send", "wait", "receive"];
+const types = ["blocked", "dns", "connect", "ssl", "send", "wait", "receive"];
const TIMINGS_END_PADDING = "80px";
/*
* Timings panel component
* Display timeline bars that shows the total wait time for various stages
*/
function TimingsPanel({ request }) {
if (!request.eventTimings) {
--- a/devtools/client/netmonitor/test/browser_net_simple-request-data.js
+++ b/devtools/client/netmonitor/test/browser_net_simple-request-data.js
@@ -322,16 +322,18 @@ function test() {
let requestItem = getSortedRequests(store.getState()).get(0);
ok(requestItem.eventTimings,
"There should be a eventTimings data available.");
is(typeof requestItem.eventTimings.timings.blocked, "number",
"The eventTimings data has an incorrect |timings.blocked| property.");
is(typeof requestItem.eventTimings.timings.dns, "number",
"The eventTimings data has an incorrect |timings.dns| property.");
+ is(typeof requestItem.eventTimings.timings.ssl, "number",
+ "The eventTimings data has an incorrect |timings.ssl| property.");
is(typeof requestItem.eventTimings.timings.connect, "number",
"The eventTimings data has an incorrect |timings.connect| property.");
is(typeof requestItem.eventTimings.timings.send, "number",
"The eventTimings data has an incorrect |timings.send| property.");
is(typeof requestItem.eventTimings.timings.wait, "number",
"The eventTimings data has an incorrect |timings.wait| property.");
is(typeof requestItem.eventTimings.timings.receive, "number",
"The eventTimings data has an incorrect |timings.receive| property.");
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -726,17 +726,19 @@ NetworkMonitor.prototype = {
0x5006: "TRANSACTION_CLOSE",
0x804b0003: "STATUS_RESOLVING",
0x804b000b: "STATUS_RESOLVED",
0x804b0007: "STATUS_CONNECTING_TO",
0x804b0004: "STATUS_CONNECTED_TO",
0x804b0005: "STATUS_SENDING_TO",
0x804b000a: "STATUS_WAITING_FOR",
- 0x804b0006: "STATUS_RECEIVING_FROM"
+ 0x804b0006: "STATUS_RECEIVING_FROM",
+ 0x804b000c: "STATUS_TLS_STARTING",
+ 0x804b000d: "STATUS_TLS_ENDING"
},
httpDownloadActivities: [
gActivityDistributor.ACTIVITY_SUBTYPE_RESPONSE_START,
gActivityDistributor.ACTIVITY_SUBTYPE_RESPONSE_HEADER,
gActivityDistributor.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
gActivityDistributor.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE
],
@@ -1386,16 +1388,17 @@ NetworkMonitor.prototype = {
if (fromCache) {
// If it came from the browser cache, we have no timing
// information and these should all be 0
return {
total: 0,
timings: {
blocked: 0,
dns: 0,
+ ssl: 0,
connect: 0,
send: 0,
wait: 0,
receive: 0
}
};
}
@@ -1420,16 +1423,46 @@ NetworkMonitor.prototype = {
if (timings.STATUS_CONNECTING_TO && timings.STATUS_CONNECTED_TO) {
harTimings.connect = timings.STATUS_CONNECTED_TO.last -
timings.STATUS_CONNECTING_TO.first;
} else {
harTimings.connect = -1;
}
+ if (timings.STATUS_TLS_STARTING && timings.STATUS_TLS_ENDING) {
+ harTimings.ssl = timings.STATUS_TLS_ENDING.last -
+ timings.STATUS_TLS_STARTING.first;
+ } else {
+ harTimings.ssl = -1;
+ }
+
+ // sometimes the connection information events are attached to a speculative
+ // channel instead of this one, but necko might glue them back together in the
+ // nsITimedChannel interface used by Resource and Navigation Timing
+ let timedChannel = httpActivity.channel.QueryInterface(Ci.nsITimedChannel);
+
+ if ((harTimings.connect <= 0) && timedChannel) {
+ if (timedChannel.secureConnectionStartTime > timedChannel.connectStartTime) {
+ harTimings.connect =
+ timedChannel.secureConnectionStartTime - timedChannel.connectStartTime;
+ harTimings.ssl =
+ timedChannel.connectEndTime - timedChannel.secureConnectionStartTime;
+ } else {
+ harTimings.connect =
+ timedChannel.connectEndTime - timedChannel.connectStartTime;
+ harTimings.ssl = -1;
+ }
+ }
+
+ if ((harTimings.dns <= 0) && timedChannel) {
+ harTimings.dns =
+ timedChannel.domainLookupEndTime - timedChannel.domainLookupStartTime;
+ }
+
if (timings.STATUS_SENDING_TO) {
harTimings.send = timings.STATUS_SENDING_TO.last - timings.STATUS_SENDING_TO.first;
} else if (timings.REQUEST_HEADER && timings.REQUEST_BODY_SENT) {
harTimings.send = timings.REQUEST_BODY_SENT.last - timings.REQUEST_HEADER.first;
} else {
harTimings.send = -1;
}
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -197,17 +197,17 @@ PerformanceMainThread::AddEntry(nsIHttpC
// To be removed once bug 1124165 lands
bool
PerformanceMainThread::IsPerformanceTimingAttribute(const nsAString& aName)
{
// Note that toJSON is added to this list due to bug 1047848
static const char* attributes[] =
{"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
"redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
- "connectStart", "connectEnd", "requestStart", "responseStart",
+ "connectStart", "secureConnectionStart", "connectEnd", "requestStart", "responseStart",
"responseEnd", "domLoading", "domInteractive",
"domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
"loadEventStart", "loadEventEnd", nullptr};
for (uint32_t i = 0; attributes[i]; ++i) {
if (aName.EqualsASCII(attributes[i])) {
return true;
}
@@ -246,16 +246,19 @@ PerformanceMainThread::GetPerformanceTim
return Timing()->DomainLookupStart();
}
if (aProperty.EqualsLiteral("domainLookupEnd")) {
return Timing()->DomainLookupEnd();
}
if (aProperty.EqualsLiteral("connectStart")) {
return Timing()->ConnectStart();
}
+ if (aProperty.EqualsLiteral("secureConnectionStart")) {
+ return Timing()->SecureConnectionStart();
+ }
if (aProperty.EqualsLiteral("connectEnd")) {
return Timing()->ConnectEnd();
}
if (aProperty.EqualsLiteral("requestStart")) {
return Timing()->RequestStart();
}
if (aProperty.EqualsLiteral("responseStart")) {
return Timing()->ResponseStart();
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -123,19 +123,19 @@ public:
DOMHighResTimeStamp ResponseEnd() const {
return mTiming
? mTiming->ResponseEndHighRes()
: 0;
}
DOMHighResTimeStamp SecureConnectionStart() const
{
- // This measurement is not available for Navigation Timing either.
- // There is a different bug submitted for it.
- return 0;
+ return mTiming && mTiming->TimingAllowed()
+ ? mTiming->SecureConnectionStartHighRes()
+ : 0;
}
virtual const PerformanceResourceTiming* ToResourceTiming() const override
{
return this;
}
uint64_t TransferSize() const
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -73,22 +73,50 @@ PerformanceTiming::InitializeTimingInfo(
aChannel->GetAsyncOpen(&mAsyncOpen);
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
aChannel->GetRedirectCount(&mRedirectCount);
aChannel->GetRedirectStart(&mRedirectStart);
aChannel->GetRedirectEnd(&mRedirectEnd);
aChannel->GetDomainLookupStart(&mDomainLookupStart);
aChannel->GetDomainLookupEnd(&mDomainLookupEnd);
aChannel->GetConnectStart(&mConnectStart);
+ aChannel->GetSecureConnectionStart(&mSecureConnectionStart);
aChannel->GetConnectEnd(&mConnectEnd);
aChannel->GetRequestStart(&mRequestStart);
aChannel->GetResponseStart(&mResponseStart);
aChannel->GetCacheReadStart(&mCacheReadStart);
aChannel->GetResponseEnd(&mResponseEnd);
aChannel->GetCacheReadEnd(&mCacheReadEnd);
+
+ // the performance timing api essentially requires that the event timestamps
+ // are >= asyncOpen().. but in truth the browser engages in a number of
+ // speculative activities that sometimes mean connections and lookups begin
+ // earlier. Workaround that here by just using asyncOpen as the minimum
+ // timestamp for dns and connection info.
+ if (!mAsyncOpen.IsNull()) {
+ if (!mDomainLookupStart.IsNull() && mDomainLookupStart < mAsyncOpen) {
+ mDomainLookupStart = mAsyncOpen;
+ }
+
+ if (!mDomainLookupEnd.IsNull() && mDomainLookupEnd < mAsyncOpen) {
+ mDomainLookupEnd = mAsyncOpen;
+ }
+
+ if (!mConnectStart.IsNull() && mConnectStart < mAsyncOpen) {
+ mConnectStart = mAsyncOpen;
+ }
+
+ if (!mSecureConnectionStart.IsNull() && mSecureConnectionStart < mAsyncOpen) {
+ mSecureConnectionStart = mAsyncOpen;
+ }
+
+ if (!mConnectEnd.IsNull() && mConnectEnd < mAsyncOpen) {
+ mConnectEnd = mAsyncOpen;
+ }
+ }
}
}
PerformanceTiming::~PerformanceTiming()
{
}
DOMHighResTimeStamp
@@ -292,16 +320,33 @@ PerformanceTiming::ConnectStartHighRes()
DOMTimeMilliSec
PerformanceTiming::ConnectStart()
{
return static_cast<int64_t>(ConnectStartHighRes());
}
DOMHighResTimeStamp
+PerformanceTiming::SecureConnectionStartHighRes()
+{
+ if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
+ nsContentUtils::ShouldResistFingerprinting()) {
+ return mZeroTime;
+ }
+ return mSecureConnectionStart.IsNull() ? mZeroTime
+ : TimeStampToDOMHighRes(mSecureConnectionStart);
+}
+
+DOMTimeMilliSec
+PerformanceTiming::SecureConnectionStart()
+{
+ return static_cast<int64_t>(SecureConnectionStartHighRes());
+}
+
+DOMHighResTimeStamp
PerformanceTiming::ConnectEndHighRes()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
nsContentUtils::ShouldResistFingerprinting()) {
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
return mConnectEnd.IsNull() ? ConnectStartHighRes()
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -159,28 +159,30 @@ public:
// High resolution (used by resource timing)
DOMHighResTimeStamp FetchStartHighRes();
DOMHighResTimeStamp RedirectStartHighRes();
DOMHighResTimeStamp RedirectEndHighRes();
DOMHighResTimeStamp DomainLookupStartHighRes();
DOMHighResTimeStamp DomainLookupEndHighRes();
DOMHighResTimeStamp ConnectStartHighRes();
+ DOMHighResTimeStamp SecureConnectionStartHighRes();
DOMHighResTimeStamp ConnectEndHighRes();
DOMHighResTimeStamp RequestStartHighRes();
DOMHighResTimeStamp ResponseStartHighRes();
DOMHighResTimeStamp ResponseEndHighRes();
// Low resolution (used by navigation timing)
DOMTimeMilliSec FetchStart();
DOMTimeMilliSec RedirectStart();
DOMTimeMilliSec RedirectEnd();
DOMTimeMilliSec DomainLookupStart();
DOMTimeMilliSec DomainLookupEnd();
DOMTimeMilliSec ConnectStart();
+ DOMTimeMilliSec SecureConnectionStart();
DOMTimeMilliSec ConnectEnd();
DOMTimeMilliSec RequestStart();
DOMTimeMilliSec ResponseStart();
DOMTimeMilliSec ResponseEnd();
DOMTimeMilliSec DomLoading()
{
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
@@ -271,16 +273,17 @@ private:
DOMHighResTimeStamp mZeroTime;
TimeStamp mAsyncOpen;
TimeStamp mRedirectStart;
TimeStamp mRedirectEnd;
TimeStamp mDomainLookupStart;
TimeStamp mDomainLookupEnd;
TimeStamp mConnectStart;
+ TimeStamp mSecureConnectionStart;
TimeStamp mConnectEnd;
TimeStamp mRequestStart;
TimeStamp mResponseStart;
TimeStamp mCacheReadStart;
TimeStamp mResponseEnd;
TimeStamp mCacheReadEnd;
uint16_t mRedirectCount;
bool mTimingAllowed;
--- a/dom/webidl/PerformanceTiming.webidl
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -16,18 +16,17 @@ interface PerformanceTiming {
readonly attribute unsigned long long unloadEventEnd;
readonly attribute unsigned long long redirectStart;
readonly attribute unsigned long long redirectEnd;
readonly attribute unsigned long long fetchStart;
readonly attribute unsigned long long domainLookupStart;
readonly attribute unsigned long long domainLookupEnd;
readonly attribute unsigned long long connectStart;
readonly attribute unsigned long long connectEnd;
- // secureConnectionStart will be implemneted in bug 772589
- // readonly attribute unsigned long long secureConnectionStart;
+ readonly attribute unsigned long long secureConnectionStart;
readonly attribute unsigned long long requestStart;
readonly attribute unsigned long long responseStart;
readonly attribute unsigned long long responseEnd;
readonly attribute unsigned long long domLoading;
readonly attribute unsigned long long domInteractive;
readonly attribute unsigned long long domContentLoadedEventStart;
readonly attribute unsigned long long domContentLoadedEventEnd;
readonly attribute unsigned long long domComplete;
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -164,16 +164,18 @@ interface nsISocketTransport : nsITransp
*/
const unsigned long STATUS_RESOLVING = 0x804b0003;
const unsigned long STATUS_RESOLVED = 0x804b000b;
const unsigned long STATUS_CONNECTING_TO = 0x804b0007;
const unsigned long STATUS_CONNECTED_TO = 0x804b0004;
const unsigned long STATUS_SENDING_TO = 0x804b0005;
const unsigned long STATUS_WAITING_FOR = 0x804b000a;
const unsigned long STATUS_RECEIVING_FROM = 0x804b0006;
+ const unsigned long STATUS_TLS_HANDSHAKE_STARTING = 0x804b000c;
+ const unsigned long STATUS_TLS_HANDSHAKE_ENDED = 0x804b000d;
/**
* connectionFlags is a bitmask that can be used to modify underlying
* behavior of the socket connection. See the flags below.
*/
attribute unsigned long connectionFlags;
/**
--- a/netwerk/base/nsITimedChannel.idl
+++ b/netwerk/base/nsITimedChannel.idl
@@ -35,16 +35,17 @@ interface nsITimedChannel : nsISupports
[noscript] attribute TimeStamp handleFetchEventStart;
[noscript] attribute TimeStamp handleFetchEventEnd;
// The following are only set when the document is not (only) read from the
// cache
[noscript] readonly attribute TimeStamp domainLookupStart;
[noscript] readonly attribute TimeStamp domainLookupEnd;
[noscript] readonly attribute TimeStamp connectStart;
+ [noscript] readonly attribute TimeStamp secureConnectionStart;
[noscript] readonly attribute TimeStamp connectEnd;
[noscript] readonly attribute TimeStamp requestStart;
[noscript] readonly attribute TimeStamp responseStart;
[noscript] readonly attribute TimeStamp responseEnd;
// The redirect attributes timings must be writeble, se we can transfer
// the data from one channel to the redirected channel.
[noscript] attribute TimeStamp redirectStart;
@@ -79,16 +80,17 @@ interface nsITimedChannel : nsISupports
readonly attribute PRTime launchServiceWorkerEndTime;
readonly attribute PRTime dispatchFetchEventStartTime;
readonly attribute PRTime dispatchFetchEventEndTime;
readonly attribute PRTime handleFetchEventStartTime;
readonly attribute PRTime handleFetchEventEndTime;
readonly attribute PRTime domainLookupStartTime;
readonly attribute PRTime domainLookupEndTime;
readonly attribute PRTime connectStartTime;
+ readonly attribute PRTime secureConnectionStartTime;
readonly attribute PRTime connectEndTime;
readonly attribute PRTime requestStartTime;
readonly attribute PRTime responseStartTime;
readonly attribute PRTime responseEndTime;
readonly attribute PRTime cacheReadStartTime;
readonly attribute PRTime cacheReadEndTime;
readonly attribute PRTime redirectStartTime;
readonly attribute PRTime redirectEndTime;
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -885,16 +885,21 @@ nsLoadGroup::TelemetryReportChannel(nsIT
if (NS_FAILED(rv))
return;
TimeStamp connectStart;
rv = aTimedChannel->GetConnectStart(&connectStart);
if (NS_FAILED(rv))
return;
+ TimeStamp secureConnectionStart;
+ rv = aTimedChannel->GetSecureConnectionStart(&secureConnectionStart);
+ if (NS_FAILED(rv))
+ return;
+
TimeStamp connectEnd;
rv = aTimedChannel->GetConnectEnd(&connectEnd);
if (NS_FAILED(rv))
return;
TimeStamp requestStart;
rv = aTimedChannel->GetRequestStart(&requestStart);
if (NS_FAILED(rv))
@@ -918,23 +923,28 @@ nsLoadGroup::TelemetryReportChannel(nsIT
} \
\
if (!domainLookupStart.IsNull() && !domainLookupEnd.IsNull()) { \
Telemetry::AccumulateTimeDelta( \
Telemetry::HTTP_##prefix##_DNS_LOOKUP_TIME, \
domainLookupStart, domainLookupEnd); \
} \
\
+ if (!secureConnectionStart.IsNull() && !connectEnd.IsNull()) { \
+ Telemetry::AccumulateTimeDelta( \
+ Telemetry::HTTP_##prefix##_TLS_HANDSHAKE, \
+ secureConnectionStart, connectEnd); \
+ } \
+ \
if (!connectStart.IsNull() && !connectEnd.IsNull()) { \
Telemetry::AccumulateTimeDelta( \
- Telemetry::HTTP_##prefix##_TCP_CONNECTION, \
+ Telemetry::HTTP_##prefix##_TCP_CONNECTION_2, \
connectStart, connectEnd); \
} \
\
- \
if (!requestStart.IsNull() && !responseEnd.IsNull()) { \
Telemetry::AccumulateTimeDelta( \
Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_SENT, \
asyncOpen, requestStart); \
\
Telemetry::AccumulateTimeDelta( \
Telemetry::HTTP_##prefix##_FIRST_SENT_TO_LAST_RECEIVED, \
requestStart, responseEnd); \
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -142,16 +142,17 @@ struct ParamTraits<mozilla::net::NetAddr
template<>
struct ParamTraits<mozilla::net::ResourceTimingStruct>
{
static void Write(Message* aMsg, const mozilla::net::ResourceTimingStruct& aParam)
{
WriteParam(aMsg, aParam.domainLookupStart);
WriteParam(aMsg, aParam.domainLookupEnd);
WriteParam(aMsg, aParam.connectStart);
+ WriteParam(aMsg, aParam.secureConnectionStart);
WriteParam(aMsg, aParam.connectEnd);
WriteParam(aMsg, aParam.requestStart);
WriteParam(aMsg, aParam.responseStart);
WriteParam(aMsg, aParam.responseEnd);
WriteParam(aMsg, aParam.fetchStart);
WriteParam(aMsg, aParam.redirectStart);
WriteParam(aMsg, aParam.redirectEnd);
@@ -164,16 +165,17 @@ struct ParamTraits<mozilla::net::Resourc
WriteParam(aMsg, aParam.cacheReadEnd);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, mozilla::net::ResourceTimingStruct* aResult)
{
return ReadParam(aMsg, aIter, &aResult->domainLookupStart) &&
ReadParam(aMsg, aIter, &aResult->domainLookupEnd) &&
ReadParam(aMsg, aIter, &aResult->connectStart) &&
+ ReadParam(aMsg, aIter, &aResult->secureConnectionStart) &&
ReadParam(aMsg, aIter, &aResult->connectEnd) &&
ReadParam(aMsg, aIter, &aResult->requestStart) &&
ReadParam(aMsg, aIter, &aResult->responseStart) &&
ReadParam(aMsg, aIter, &aResult->responseEnd) &&
ReadParam(aMsg, aIter, &aResult->fetchStart) &&
ReadParam(aMsg, aIter, &aResult->redirectStart) &&
ReadParam(aMsg, aIter, &aResult->redirectEnd) &&
ReadParam(aMsg, aIter, &aResult->transferSize) &&
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -2429,16 +2429,25 @@ Http2Session::OnTransportStatus(nsITrans
case NS_NET_STATUS_RESOLVING_HOST:
case NS_NET_STATUS_RESOLVED_HOST:
case NS_NET_STATUS_CONNECTING_TO:
case NS_NET_STATUS_CONNECTED_TO:
case NS_NET_STATUS_TLS_HANDSHAKE_STARTING:
case NS_NET_STATUS_TLS_HANDSHAKE_ENDED:
{
Http2Stream *target = mStreamIDHash.Get(mUseH2Deps ? 0xF : 0x3);
+ if (!target) {
+ // any transaction will do if we can't find the low numbered one
+ // generally this happens when the initial transaction hasn't been
+ // assigned a stream id yet.
+ auto iter = mStreamTransactionHash.Iter();
+ if (!iter.Done()) {
+ target = iter.Data();
+ }
+ }
nsAHttpTransaction *transaction = target ? target->Transaction() : nullptr;
if (transaction)
transaction->OnTransportStatus(aTransport, aStatus, aProgress);
break;
}
default:
// The other transport events are ignored here because there is no good
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -3835,16 +3835,22 @@ HttpBaseChannel::GetDomainLookupEnd(Time
NS_IMETHODIMP
HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
*_retval = mTransactionTimings.connectStart;
return NS_OK;
}
NS_IMETHODIMP
+HttpBaseChannel::GetSecureConnectionStart(TimeStamp* _retval) {
+ *_retval = mTransactionTimings.secureConnectionStart;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
*_retval = mTransactionTimings.connectEnd;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
*_retval = mTransactionTimings.requestStart;
@@ -3909,16 +3915,17 @@ IMPL_TIMING_ATTR(LaunchServiceWorkerStar
IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
IMPL_TIMING_ATTR(DispatchFetchEventStart)
IMPL_TIMING_ATTR(DispatchFetchEventEnd)
IMPL_TIMING_ATTR(HandleFetchEventStart)
IMPL_TIMING_ATTR(HandleFetchEventEnd)
IMPL_TIMING_ATTR(DomainLookupStart)
IMPL_TIMING_ATTR(DomainLookupEnd)
IMPL_TIMING_ATTR(ConnectStart)
+IMPL_TIMING_ATTR(SecureConnectionStart)
IMPL_TIMING_ATTR(ConnectEnd)
IMPL_TIMING_ATTR(RequestStart)
IMPL_TIMING_ATTR(ResponseStart)
IMPL_TIMING_ATTR(ResponseEnd)
IMPL_TIMING_ATTR(CacheReadStart)
IMPL_TIMING_ATTR(CacheReadEnd)
IMPL_TIMING_ATTR(RedirectStart)
IMPL_TIMING_ATTR(RedirectEnd)
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1038,16 +1038,17 @@ HttpChannelChild::OnStopRequest(const ns
nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
if (conv) {
conv->GetDecodedDataLength(&mDecodedBodySize);
}
mTransactionTimings.domainLookupStart = timing.domainLookupStart;
mTransactionTimings.domainLookupEnd = timing.domainLookupEnd;
mTransactionTimings.connectStart = timing.connectStart;
+ mTransactionTimings.secureConnectionStart = timing.secureConnectionStart;
mTransactionTimings.connectEnd = timing.connectEnd;
mTransactionTimings.requestStart = timing.requestStart;
mTransactionTimings.responseStart = timing.responseStart;
mTransactionTimings.responseEnd = timing.responseEnd;
// Do not overwrite or adjust the original mAsyncOpenTime by timing.fetchStart
// We must use the original child process time in order to account for child
// side work and IPC transit overhead.
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -1525,16 +1525,17 @@ HttpChannelParent::OnStopRequest(nsIRequ
MOZ_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
"Cannot call OnStopRequest if diverting is set!");
ResourceTimingStruct timing;
mChannel->GetDomainLookupStart(&timing.domainLookupStart);
mChannel->GetDomainLookupEnd(&timing.domainLookupEnd);
mChannel->GetConnectStart(&timing.connectStart);
+ mChannel->GetSecureConnectionStart(&timing.secureConnectionStart);
mChannel->GetConnectEnd(&timing.connectEnd);
mChannel->GetRequestStart(&timing.requestStart);
mChannel->GetResponseStart(&timing.responseStart);
mChannel->GetResponseEnd(&timing.responseEnd);
mChannel->GetAsyncOpen(&timing.fetchStart);
mChannel->GetRedirectStart(&timing.redirectStart);
mChannel->GetRedirectEnd(&timing.redirectEnd);
mChannel->GetTransferSize(&timing.transferSize);
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -690,16 +690,23 @@ NullHttpChannel::GetDomainLookupEnd(mozi
NS_IMETHODIMP
NullHttpChannel::GetConnectStart(mozilla::TimeStamp *aConnectStart)
{
*aConnectStart = mAsyncOpenTime;
return NS_OK;
}
NS_IMETHODIMP
+NullHttpChannel::GetSecureConnectionStart(mozilla::TimeStamp *aSecureConnectionStart)
+{
+ *aSecureConnectionStart = mAsyncOpenTime;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
NullHttpChannel::GetConnectEnd(mozilla::TimeStamp *aConnectEnd)
{
*aConnectEnd = mAsyncOpenTime;
return NS_OK;
}
NS_IMETHODIMP
NullHttpChannel::GetRequestStart(mozilla::TimeStamp *aRequestStart)
@@ -867,16 +874,17 @@ IMPL_TIMING_ATTR(LaunchServiceWorkerStar
IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
IMPL_TIMING_ATTR(DispatchFetchEventStart)
IMPL_TIMING_ATTR(DispatchFetchEventEnd)
IMPL_TIMING_ATTR(HandleFetchEventStart)
IMPL_TIMING_ATTR(HandleFetchEventEnd)
IMPL_TIMING_ATTR(DomainLookupStart)
IMPL_TIMING_ATTR(DomainLookupEnd)
IMPL_TIMING_ATTR(ConnectStart)
+IMPL_TIMING_ATTR(SecureConnectionStart)
IMPL_TIMING_ATTR(ConnectEnd)
IMPL_TIMING_ATTR(RequestStart)
IMPL_TIMING_ATTR(ResponseStart)
IMPL_TIMING_ATTR(ResponseEnd)
IMPL_TIMING_ATTR(CacheReadStart)
IMPL_TIMING_ATTR(CacheReadEnd)
IMPL_TIMING_ATTR(RedirectStart)
IMPL_TIMING_ATTR(RedirectEnd)
--- a/netwerk/protocol/http/NullHttpTransaction.cpp
+++ b/netwerk/protocol/http/NullHttpTransaction.cpp
@@ -165,16 +165,40 @@ NullHttpTransaction::GetSecurityCallback
nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
*outCB = copyCB.forget().take();
}
void
NullHttpTransaction::OnTransportStatus(nsITransport* transport,
nsresult status, int64_t progress)
{
+ if (status == NS_NET_STATUS_RESOLVING_HOST) {
+ if (mTimings.domainLookupStart.IsNull()) {
+ mTimings.domainLookupStart = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_RESOLVED_HOST) {
+ if (mTimings.domainLookupEnd.IsNull()) {
+ mTimings.domainLookupEnd = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_CONNECTING_TO) {
+ if (mTimings.connectStart.IsNull()) {
+ mTimings.connectStart = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_CONNECTED_TO) {
+ if (mTimings.connectEnd.IsNull()) {
+ mTimings.connectEnd = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
+ if (mTimings.secureConnectionStart.IsNull() &&
+ !mTimings.connectEnd.IsNull()) {
+ mTimings.secureConnectionStart = mTimings.connectEnd;
+ }
+ mTimings.connectEnd = TimeStamp::Now();;
+ }
+
if (mActivityDistributor) {
NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor,
mConnectionInfo->GetOrigin(),
mConnectionInfo->OriginPort(),
mConnectionInfo->EndToEndSSL(),
NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
static_cast<uint32_t>(status),
PR_Now(),
--- a/netwerk/protocol/http/NullHttpTransaction.h
+++ b/netwerk/protocol/http/NullHttpTransaction.h
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_net_NullHttpTransaction_h
#define mozilla_net_NullHttpTransaction_h
#include "nsAHttpTransaction.h"
#include "mozilla/Attributes.h"
+#include "TimingStruct.h"
// This is the minimal nsAHttpTransaction implementation. A NullHttpTransaction
// can be used to drive connection level semantics (such as SSL handshakes
// tunnels) so that a nsHttpConnection becomes fully established in
// anticipation of a real transaction needing to use it soon.
class nsIHttpActivityObserver;
@@ -51,16 +52,18 @@ public:
}
// We have to override this function because |mTransaction| in nsHalfOpenSocket
// could be either nsHttpTransaction or NullHttpTransaction.
// NullHttpTransaction will be activated on the connection immediately after
// creation and be never put in a pending queue, so it's OK to just return 0.
uint64_t TopLevelOuterContentWindowId() override { return 0; }
+ TimingStruct Timings() { return mTimings; }
+
protected:
virtual ~NullHttpTransaction();
private:
nsresult mStatus;
protected:
uint32_t mCaps;
nsHttpRequestHead *mRequestHead;
@@ -70,16 +73,17 @@ private:
// redundant requests on the network. The member itself is atomic, but
// access to it from the networking thread may happen either before or
// after the main thread modifies it. To deal with raciness, only unsetting
// bitfields should be allowed: 'lost races' will thus err on the
// conservative side, e.g. by going ahead with a 2nd DNS refresh.
Atomic<uint32_t> mCapsToClear;
bool mIsDone;
bool mClaimed;
+ TimingStruct mTimings;
protected:
RefPtr<nsAHttpConnection> mConnection;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
RefPtr<nsHttpConnectionInfo> mConnectionInfo;
nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
};
--- a/netwerk/protocol/http/TimingStruct.h
+++ b/netwerk/protocol/http/TimingStruct.h
@@ -9,16 +9,17 @@
#include "mozilla/TimeStamp.h"
namespace mozilla { namespace net {
struct TimingStruct {
TimeStamp domainLookupStart;
TimeStamp domainLookupEnd;
TimeStamp connectStart;
+ TimeStamp secureConnectionStart;
TimeStamp connectEnd;
TimeStamp requestStart;
TimeStamp responseStart;
TimeStamp responseEnd;
};
struct ResourceTimingStruct : TimingStruct {
TimeStamp fetchStart;
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6910,16 +6910,25 @@ nsHttpChannel::GetConnectStart(TimeStamp
if (mTransaction)
*_retval = mTransaction->GetConnectStart();
else
*_retval = mTransactionTimings.connectStart;
return NS_OK;
}
NS_IMETHODIMP
+nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
+ if (mTransaction)
+ *_retval = mTransaction->GetSecureConnectionStart();
+ else
+ *_retval = mTransactionTimings.secureConnectionStart;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
if (mTransaction)
*_retval = mTransaction->GetConnectEnd();
else
*_retval = mTransactionTimings.connectEnd;
return NS_OK;
}
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -173,16 +173,17 @@ public:
NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID) override;
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks) override;
NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup) override;
// nsITimedChannel
NS_IMETHOD GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart) override;
NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp *aDomainLookupEnd) override;
NS_IMETHOD GetConnectStart(mozilla::TimeStamp *aConnectStart) override;
+ NS_IMETHOD GetSecureConnectionStart(mozilla::TimeStamp *aSecureConnectionStart) override;
NS_IMETHOD GetConnectEnd(mozilla::TimeStamp *aConnectEnd) override;
NS_IMETHOD GetRequestStart(mozilla::TimeStamp *aRequestStart) override;
NS_IMETHOD GetResponseStart(mozilla::TimeStamp *aResponseStart) override;
NS_IMETHOD GetResponseEnd(mozilla::TimeStamp *aResponseEnd) override;
// nsICorsPreflightCallback
NS_IMETHOD OnPreflightSucceeded() override;
NS_IMETHOD OnPreflightFailed(nsresult aError) override;
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -532,18 +532,25 @@ nsHttpConnection::EnsureNPNComplete(nsre
Telemetry::Accumulate(Telemetry::SPDY_NPN_CONNECT, UsingSpdy());
}
npnComplete:
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] setting complete to true", this));
mNPNComplete = true;
mTransaction->OnTransportStatus(mSocketTransport,
- NS_NET_STATUS_TLS_HANDSHAKE_ENDED,
- 0);
+ NS_NET_STATUS_TLS_HANDSHAKE_ENDED, 0);
+
+ // this is happening after the bootstrap was originally written to. so update it.
+ if (mBootstrappedTimings.secureConnectionStart.IsNull() &&
+ !mBootstrappedTimings.connectEnd.IsNull()) {
+ mBootstrappedTimings.secureConnectionStart = mBootstrappedTimings.connectEnd;
+ mBootstrappedTimings.connectEnd = TimeStamp::Now();
+ }
+
if (mWaitingFor0RTTResponse) {
// Didn't get 0RTT OK, back out of the "attempting 0RTT" state
mWaitingFor0RTTResponse = false;
LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] 0rtt failed", this));
if (NS_FAILED(mTransaction->Finish0RTT(true, negotiatedNPN != mEarlyNegotiatedALPN))) {
mTransaction->Close(NS_ERROR_NET_RESET);
}
mContentBytesWritten0RTT = 0;
@@ -577,18 +584,24 @@ nsHttpConnection::OnTunnelNudged(TLSFilt
// called on the socket thread
nsresult
nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri)
{
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("nsHttpConnection::Activate [this=%p trans=%p caps=%x]\n",
this, trans, caps));
- if (!trans->IsNullTransaction() && !mFastOpen)
+ if (!mExperienced && !trans->IsNullTransaction() && !mFastOpen) {
mExperienced = true;
+ nsHttpTransaction *hTrans = trans->QueryHttpTransaction();
+ if (hTrans) {
+ hTrans->BootstrapTimings(mBootstrappedTimings);
+ }
+ mBootstrappedTimings = TimingStruct();
+ }
mTransactionCaps = caps;
mPriority = pri;
if (mTransaction && mUsingSpdyVersion) {
return AddTransaction(trans, pri);
}
NS_ENSURE_ARG_POINTER(trans);
@@ -2372,10 +2385,16 @@ nsHttpConnection::SetFastOpen(bool aFast
mFastOpen = aFastOpen;
if (!mFastOpen &&
mTransaction &&
!mTransaction->IsNullTransaction()) {
mExperienced = true;
}
}
+void
+nsHttpConnection::BootstrapTimings(TimingStruct times)
+{
+ mBootstrappedTimings = times;
+}
+
} // namespace net
} // namespace mozilla
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -11,16 +11,17 @@
#include "nsAHttpTransaction.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsProxyRelease.h"
#include "prinrval.h"
#include "TunnelUtils.h"
#include "mozilla/Mutex.h"
#include "ARefBase.h"
+#include "TimingStruct.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsITimer.h"
class nsISocketTransport;
class nsISSLSocketControl;
@@ -394,16 +395,21 @@ private:
nsCString mEarlyNegotiatedALPN;
bool mDid0RTTSpdy;
bool mFastOpen;
uint8_t mFastOpenStatus;
bool mForceSendDuringFastOpenPending;
bool mReceivedSocketWouldBlockDuringFastOpen;
+
+public:
+ void BootstrapTimings(TimingStruct times);
+private:
+ TimingStruct mBootstrappedTimings;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnection, NS_HTTPCONNECTION_IID)
} // namespace net
} // namespace mozilla
#endif // nsHttpConnection_h__
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -4355,16 +4355,21 @@ nsHalfOpenSocket::SetupConn(nsIAsyncOutp
bool aFastOpen)
{
MOZ_ASSERT(!aFastOpen || (out == mStreamOut));
// assign the new socket to the http connection
RefPtr<nsHttpConnection> conn = new nsHttpConnection();
LOG(("nsHalfOpenSocket::SetupConn "
"Created new nshttpconnection %p\n", conn.get()));
+ NullHttpTransaction *nullTrans = mTransaction->QueryNullTransaction();
+ if (nullTrans) {
+ conn->BootstrapTimings(nullTrans->Timings());
+ }
+
// Some capabilities are needed before a transaciton actually gets
// scheduled (e.g. how to negotiate false start)
conn->SetTransactionCaps(mTransaction->Caps());
NetAddr peeraddr;
nsCOMPtr<nsIInterfaceRequestor> callbacks;
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
nsresult rv;
@@ -4567,17 +4572,17 @@ nsHttpConnectionMgr::nsHalfOpenSocket::O
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_DIAGNOSTIC_ASSERT(mEnt);
if (mTransaction) {
RefPtr<PendingTransactionInfo> info = FindTransactionHelper(false);
if ((trans == mSocketTransport) ||
((trans == mBackupTransport) && (status == NS_NET_STATUS_CONNECTED_TO) &&
info)) {
- // Send this status event only if the transaction is still panding,
+ // Send this status event only if the transaction is still pending,
// i.e. it has not found a free already connected socket.
// Sockets in halfOpen state can only get following events:
// NS_NET_STATUS_RESOLVING_HOST, NS_NET_STATUS_RESOLVED_HOST,
// NS_NET_STATUS_CONNECTING_TO and NS_NET_STATUS_CONNECTED_TO.
// mBackupTransport is only started after
// NS_NET_STATUS_CONNECTING_TO of mSocketTransport, so ignore all
// mBackupTransport events until NS_NET_STATUS_CONNECTED_TO.
mTransaction->OnTransportStatus(trans, status, progress);
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -573,16 +573,24 @@ nsHttpTransaction::OnTransportStatus(nsI
SetDomainLookupStart(TimeStamp::Now(), true);
} else if (status == NS_NET_STATUS_RESOLVED_HOST) {
SetDomainLookupEnd(TimeStamp::Now());
} else if (status == NS_NET_STATUS_CONNECTING_TO) {
SetConnectStart(TimeStamp::Now());
} else if (status == NS_NET_STATUS_CONNECTED_TO) {
SetConnectEnd(TimeStamp::Now(), true);
} else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
+ {
+ // before overwriting connectEnd, copy it to secureConnectionStart
+ MutexAutoLock lock(mLock);
+ if (mTimings.secureConnectionStart.IsNull() &&
+ !mTimings.connectEnd.IsNull()) {
+ mTimings.secureConnectionStart = mTimings.connectEnd;
+ }
+ }
SetConnectEnd(TimeStamp::Now(), false);
} else if (status == NS_NET_STATUS_SENDING_TO) {
// Set the timestamp to Now(), only if it null
SetRequestStart(TimeStamp::Now(), true);
}
}
if (!mTransportSink)
@@ -1943,16 +1951,23 @@ const TimingStruct
nsHttpTransaction::Timings()
{
mozilla::MutexAutoLock lock(mLock);
TimingStruct timings = mTimings;
return timings;
}
void
+nsHttpTransaction::BootstrapTimings(TimingStruct times)
+{
+ mozilla::MutexAutoLock lock(mLock);
+ mTimings = times;
+}
+
+void
nsHttpTransaction::SetDomainLookupStart(mozilla::TimeStamp timeStamp, bool onlyIfNull)
{
mozilla::MutexAutoLock lock(mLock);
if (onlyIfNull && !mTimings.domainLookupStart.IsNull()) {
return; // We only set the timestamp if it was previously null
}
mTimings.domainLookupStart = timeStamp;
}
@@ -2034,16 +2049,23 @@ nsHttpTransaction::GetDomainLookupEnd()
mozilla::TimeStamp
nsHttpTransaction::GetConnectStart()
{
mozilla::MutexAutoLock lock(mLock);
return mTimings.connectStart;
}
mozilla::TimeStamp
+nsHttpTransaction::GetSecureConnectionStart()
+{
+ mozilla::MutexAutoLock lock(mLock);
+ return mTimings.secureConnectionStart;
+}
+
+mozilla::TimeStamp
nsHttpTransaction::GetConnectEnd()
{
mozilla::MutexAutoLock lock(mLock);
return mTimings.connectEnd;
}
mozilla::TimeStamp
nsHttpTransaction::GetRequestStart()
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -143,27 +143,30 @@ public:
return r;
}
void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
uint32_t InitialRwin() const { return mInitialRwin; };
bool ChannelPipeFull() { return mWaitingOnPipeOut; }
// Locked methods to get and set timing info
const TimingStruct Timings();
+ void BootstrapTimings(TimingStruct times);
void SetDomainLookupStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetDomainLookupEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetConnectStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetConnectEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetRequestStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetResponseStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
void SetResponseEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
mozilla::TimeStamp GetDomainLookupStart();
mozilla::TimeStamp GetDomainLookupEnd();
mozilla::TimeStamp GetConnectStart();
+ mozilla::TimeStamp GetSecureConnectionStart();
+
mozilla::TimeStamp GetConnectEnd();
mozilla::TimeStamp GetRequestStart();
mozilla::TimeStamp GetResponseStart();
mozilla::TimeStamp GetResponseEnd();
int64_t GetTransferSize() { return mTransferSize; }
MOZ_MUST_USE bool Do0RTT() override;
--- a/testing/web-platform/meta/navigation-timing/idlharness.html.ini
+++ b/testing/web-platform/meta/navigation-timing/idlharness.html.ini
@@ -1,16 +1,10 @@
[idlharness.html]
type: testharness
- [PerformanceTiming interface: attribute secureConnectionStart]
- expected: FAIL
-
- [PerformanceTiming interface: window.performance.timing must inherit property "secureConnectionStart" with the proper type (10)]
- expected: FAIL
-
[Performance interface: existence and properties of interface object]
expected: FAIL
[Performance interface: existence and properties of interface prototype object]
expected: FAIL
[EventTarget interface: window.performance must inherit property "addEventListener" with the proper type (0)]
expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/user-timing/invoke_with_timing_attributes.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[invoke_with_timing_attributes.html]
- type: testharness
- [performance.mark should throw if used with timing attribute secureConnectionStart]
- expected: FAIL
-
- [performance.measure should throw if used with timing attribute secureConnectionStart]
- expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/user-timing/mark_exceptions.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[mark_exceptions.html]
- type: testharness
- [window.performance.mark("secureConnectionStart") throws a SyntaxError exception.]
- expected: FAIL
-
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1894,23 +1894,35 @@
"HTTP_PAGE_DNS_LOOKUP_TIME": {
"record_in_processes": ["main", "content"],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
"description": "HTTP page channel: DNS lookup time (ms)"
},
- "HTTP_PAGE_TCP_CONNECTION": {
- "record_in_processes": ["main", "content"],
- "expires_in_version": "never",
+ "HTTP_PAGE_TLS_HANDSHAKE": {
+ "record_in_processes": ["main", "content"],
+ "expires_in_version": "never",
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
- "description": "HTTP page channel: TCP connection setup (ms)"
+ "description": "HTTP page channel: After TCP SYN to Ready for HTTP (ms)"
+ },
+ "HTTP_PAGE_TCP_CONNECTION_2": {
+ "record_in_processes": ["main", "content"],
+ "expires_in_version": "never",
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
+ "kind": "exponential",
+ "high": 30000,
+ "n_buckets": 50,
+ "description": "HTTP page channel: TCP SYN to Ready for HTTP (ms)"
},
"HTTP_PAGE_OPEN_TO_FIRST_SENT": {
"record_in_processes": ["main", "content"],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
"description": "HTTP page channel: Open -> first byte of request sent (ms)"
@@ -2030,23 +2042,35 @@
"HTTP_SUB_DNS_LOOKUP_TIME": {
"record_in_processes": ["main", "content"],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
"description": "HTTP subitem channel: DNS lookup time (ms)"
},
- "HTTP_SUB_TCP_CONNECTION": {
- "record_in_processes": ["main", "content"],
+ "HTTP_SUB_TLS_HANDSHAKE": {
+ "record_in_processes": ["main", "content"],
+ "expires_in_version": "never",
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
+ "kind": "exponential",
+ "high": 30000,
+ "n_buckets": 50,
+ "description": "HTTP subitem channel: After TCP SYN to Ready for HTTP (ms)"
+ },
+ "HTTP_SUB_TCP_CONNECTION_2": {
+ "record_in_processes": ["main", "content"],
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
- "description": "HTTP subitem channel: TCP connection setup (ms)"
+ "description": "HTTP subitem channel: TCP SYN to Ready for HTTP (ms)"
},
"HTTP_SUB_OPEN_TO_FIRST_SENT": {
"record_in_processes": ["main", "content"],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
"description": "HTTP subitem channel: Open -> first byte of request sent (ms)"
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -298,17 +298,16 @@
"HTTP_PAGE_DNS_ISSUE_TIME",
"HTTP_PAGE_DNS_LOOKUP_TIME",
"HTTP_PAGE_FIRST_SENT_TO_LAST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE",
"HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE_V2",
"HTTP_PAGE_OPEN_TO_FIRST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_SENT",
"HTTP_PAGE_REVALIDATION",
- "HTTP_PAGE_TCP_CONNECTION",
"HTTP_PROXY_TYPE",
"HTTP_REQUEST_PER_CONN",
"HTTP_REQUEST_PER_PAGE",
"HTTP_REQUEST_PER_PAGE_FROM_CACHE",
"HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME",
"HTTP_SUBITEM_OPEN_LATENCY_TIME",
"HTTP_SUB_CACHE_READ_TIME",
"HTTP_SUB_CACHE_READ_TIME_V2",
@@ -321,17 +320,16 @@
"HTTP_SUB_DNS_ISSUE_TIME",
"HTTP_SUB_DNS_LOOKUP_TIME",
"HTTP_SUB_FIRST_SENT_TO_LAST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE",
"HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE_V2",
"HTTP_SUB_OPEN_TO_FIRST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_SENT",
"HTTP_SUB_REVALIDATION",
- "HTTP_SUB_TCP_CONNECTION",
"HTTP_TRANSACTION_USE_ALTSVC",
"HTTP_TRANSACTION_USE_ALTSVC_OE",
"INNERWINDOWS_WITH_MUTATION_LISTENERS",
"IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB",
"IPV4_AND_IPV6_ADDRESS_CONNECTIVITY",
"JS_TELEMETRY_ADDON_EXCEPTIONS",
"LINK_ICON_SIZES_ATTR_DIMENSION",
"LINK_ICON_SIZES_ATTR_USAGE",
@@ -1006,17 +1004,16 @@
"HTTP_PAGE_DNS_ISSUE_TIME",
"HTTP_PAGE_DNS_LOOKUP_TIME",
"HTTP_PAGE_FIRST_SENT_TO_LAST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE",
"HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE_V2",
"HTTP_PAGE_OPEN_TO_FIRST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_SENT",
"HTTP_PAGE_REVALIDATION",
- "HTTP_PAGE_TCP_CONNECTION",
"HTTP_PROXY_TYPE",
"HTTP_REQUEST_PER_CONN",
"HTTP_REQUEST_PER_PAGE",
"HTTP_REQUEST_PER_PAGE_FROM_CACHE",
"HTTP_RESPONSE_VERSION",
"HTTP_SAW_QUIC_ALT_PROTOCOL",
"HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME",
"HTTP_SUBITEM_OPEN_LATENCY_TIME",
@@ -1031,17 +1028,16 @@
"HTTP_SUB_DNS_ISSUE_TIME",
"HTTP_SUB_DNS_LOOKUP_TIME",
"HTTP_SUB_FIRST_SENT_TO_LAST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE",
"HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE_V2",
"HTTP_SUB_OPEN_TO_FIRST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_SENT",
"HTTP_SUB_REVALIDATION",
- "HTTP_SUB_TCP_CONNECTION",
"HTTP_TRANSACTION_USE_ALTSVC",
"HTTP_TRANSACTION_USE_ALTSVC_OE",
"IMAGE_DECODE_CHUNKS",
"IMAGE_DECODE_COUNT",
"IMAGE_DECODE_LATENCY_US",
"IMAGE_DECODE_ON_DRAW_LATENCY",
"IMAGE_DECODE_SPEED_GIF",
"IMAGE_DECODE_SPEED_JPEG",