fune/netwerk/protocol/http/nsServerTiming.cpp
Kershaw Chang 73d9823e67 Bug 1413999 Part2: Take http trailers from chunk decoder and add serverTiming attribute in nsITimedChannel r=dragana
This patch includes:
1. Save http trailers in the header array in chunk decoder.
2. Take trailers from chunk decoder in OnStopRequest().
3. Add serverTiming attribute in nsITimedChannel.
4. Parse server timing header when GetServerTiming() is called.

--HG--
extra : rebase_source : 77c92b8a31d3d7eebb33aea266888f944af33327
2018-01-03 02:04:00 +02:00

108 lines
3.2 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "nsServerTiming.h"
NS_IMPL_ISUPPORTS(nsServerTiming, nsIServerTiming)
NS_IMETHODIMP
nsServerTiming::GetName(nsACString &aName)
{
aName.Assign(mName);
return NS_OK;
}
NS_IMETHODIMP
nsServerTiming::GetDuration(double *aDuration)
{
*aDuration = mDuration;
return NS_OK;
}
NS_IMETHODIMP
nsServerTiming::GetDescription(nsACString &aDescription)
{
aDescription.Assign(mDescription);
return NS_OK;
}
namespace mozilla {
namespace net {
static double
ParseDouble(const nsACString& aString)
{
nsresult rv;
double val = PromiseFlatCString(aString).ToDouble(&rv);
return NS_FAILED(rv) ? 0.0f : val;
}
void
ServerTimingParser::Parse()
{
// https://w3c.github.io/server-timing/#the-server-timing-header-field
// Server-Timing = #server-timing-metric
// server-timing-metric = metric-name *( OWS ";" OWS server-timing-param )
// metric-name = token
// server-timing-param = server-timing-param-name OWS "=" OWS server-timing-param-value
// server-timing-param-name = token
// server-timing-param-value = token / quoted-string
ParsedHeaderValueListList parsedHeader(mValue, false);
for (uint32_t index = 0; index < parsedHeader.mValues.Length(); ++index) {
if (parsedHeader.mValues[index].mValues.IsEmpty()) {
continue;
}
// According to spec, the first ParsedHeaderPair's name is metric-name.
RefPtr<nsServerTiming> timingHeader = new nsServerTiming();
mServerTimingHeaders.AppendElement(timingHeader);
timingHeader->SetName(parsedHeader.mValues[index].mValues[0].mName);
if (parsedHeader.mValues[index].mValues.Length() == 1) {
continue;
}
// Try to find duration and description from the rest ParsedHeaderPairs.
bool foundDuration = false;
bool foundDescription = false;
for (uint32_t pairIndex = 1;
pairIndex < parsedHeader.mValues[index].mValues.Length();
++pairIndex) {
nsDependentCSubstring &currentName =
parsedHeader.mValues[index].mValues[pairIndex].mName;
nsDependentCSubstring &currentValue =
parsedHeader.mValues[index].mValues[pairIndex].mValue;
// We should only take the value from the first
// occurrence of server-timing-param-name ("dur" and "desc").
if (currentName.LowerCaseEqualsASCII("dur") &&
currentValue.BeginReading() &&
!foundDuration) {
timingHeader->SetDuration(ParseDouble(currentValue));
foundDuration = true;
} else if (currentName.LowerCaseEqualsASCII("desc") &&
!currentValue.IsEmpty() &&
!foundDescription) {
timingHeader->SetDescription(currentValue);
foundDescription = true;
}
if (foundDuration && foundDescription) {
break;
}
}
}
}
nsTArray<nsCOMPtr<nsIServerTiming>>&&
ServerTimingParser::TakeServerTimingHeaders()
{
return Move(mServerTimingHeaders);
}
} // namespace net
} // namespace mozilla