nsServerTiming.cpp (3608B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "nsServerTiming.h" 8 9 #include "nsHttp.h" 10 11 NS_IMPL_ISUPPORTS(nsServerTiming, nsIServerTiming) 12 13 NS_IMETHODIMP 14 nsServerTiming::GetName(nsACString& aName) { 15 aName.Assign(mName); 16 return NS_OK; 17 } 18 19 NS_IMETHODIMP 20 nsServerTiming::GetDuration(double* aDuration) { 21 *aDuration = mDuration; 22 return NS_OK; 23 } 24 25 NS_IMETHODIMP 26 nsServerTiming::GetDescription(nsACString& aDescription) { 27 aDescription.Assign(mDescription); 28 return NS_OK; 29 } 30 31 namespace mozilla { 32 namespace net { 33 34 static double ParseDouble(const nsACString& aString) { 35 nsresult rv; 36 double val = PromiseFlatCString(aString).ToDouble(&rv); 37 return NS_FAILED(rv) ? 0.0f : val; 38 } 39 40 void ServerTimingParser::Parse() { 41 // https://w3c.github.io/server-timing/#the-server-timing-header-field 42 // Server-Timing = #server-timing-metric 43 // server-timing-metric = metric-name *( OWS ";" OWS server-timing-param 44 // ) metric-name = token server-timing-param = 45 // server-timing-param-name OWS "=" OWS 46 // server-timing-param-value 47 // server-timing-param-name = token 48 // server-timing-param-value = token / quoted-string 49 50 ParsedHeaderValueListList parsedHeader(mValue, false); 51 for (uint32_t index = 0; index < parsedHeader.mValues.Length(); ++index) { 52 if (parsedHeader.mValues[index].mValues.IsEmpty()) { 53 continue; 54 } 55 56 // According to spec, the first ParsedHeaderPair's name is metric-name. 57 RefPtr<nsServerTiming> timingHeader = new nsServerTiming(); 58 mServerTimingHeaders.AppendElement(timingHeader); 59 timingHeader->SetName(parsedHeader.mValues[index].mValues[0].mName); 60 61 if (parsedHeader.mValues[index].mValues.Length() == 1) { 62 continue; 63 } 64 65 // Try to find duration and description from the rest ParsedHeaderPairs. 66 bool foundDuration = false; 67 bool foundDescription = false; 68 for (uint32_t pairIndex = 1; 69 pairIndex < parsedHeader.mValues[index].mValues.Length(); 70 ++pairIndex) { 71 nsDependentCSubstring& currentName = 72 parsedHeader.mValues[index].mValues[pairIndex].mName; 73 nsDependentCSubstring& currentValue = 74 parsedHeader.mValues[index].mValues[pairIndex].mValue; 75 76 // We should only take the value from the first 77 // occurrence of server-timing-param-name ("dur" and "desc"). 78 // This is true whether or not the value makes any sense (or, indeed, if 79 // there even is a value). 80 if (currentName.LowerCaseEqualsASCII("dur") && !foundDuration) { 81 if (currentValue.BeginReading()) { 82 timingHeader->SetDuration(ParseDouble(currentValue)); 83 } else { 84 timingHeader->SetDuration(0.0); 85 } 86 foundDuration = true; 87 } else if (currentName.LowerCaseEqualsASCII("desc") && 88 !foundDescription) { 89 if (!currentValue.IsEmpty()) { 90 timingHeader->SetDescription(currentValue); 91 } else { 92 timingHeader->SetDescription(""_ns); 93 } 94 foundDescription = true; 95 } 96 97 if (foundDuration && foundDescription) { 98 break; 99 } 100 } 101 } 102 } 103 104 nsTArray<nsCOMPtr<nsIServerTiming>>&& 105 ServerTimingParser::TakeServerTimingHeaders() { 106 return std::move(mServerTimingHeaders); 107 } 108 109 } // namespace net 110 } // namespace mozilla