Bug 1423495 - Part6: Use threadsafe refcounting for nsServerTiming r=baku,nwgh

* Also keeps the timing array as nsTArray<nsCOMPtr<nsIServerTiming>> instead of the scriptable nsIArray (which doesn't like being released on another thread)

MozReview-Commit-ID: 37uPZJ38saQ
This commit is contained in:
Valentin Gosu
2018-04-24 13:04:12 +02:00
parent decbd92350
commit 5a8b6a068c
7 changed files with 48 additions and 34 deletions

View File

@@ -98,19 +98,10 @@ PerformanceResourceTiming::GetServerTiming(
return; return;
} }
nsCOMPtr<nsIArray> serverTimingArray = mTimingData->GetServerTiming(); nsTArray<nsCOMPtr<nsIServerTiming>> serverTimingArray = mTimingData->GetServerTiming();
if (!serverTimingArray) { uint32_t length = serverTimingArray.Length();
return;
}
uint32_t length = 0;
if (NS_WARN_IF(NS_FAILED(serverTimingArray->GetLength(&length)))) {
return;
}
for (uint32_t index = 0; index < length; ++index) { for (uint32_t index = 0; index < length; ++index) {
nsCOMPtr<nsIServerTiming> serverTiming = nsCOMPtr<nsIServerTiming> serverTiming = serverTimingArray.ElementAt(index);
do_QueryElementAt(serverTimingArray, index);
MOZ_ASSERT(serverTiming); MOZ_ASSERT(serverTiming);
aRetval.AppendElement( aRetval.AppendElement(

View File

@@ -162,7 +162,7 @@ PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
// ServiceWorker interception responseStart? // ServiceWorker interception responseStart?
aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd); aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd);
aChannel->GetServerTiming(getter_AddRefs(mServerTiming)); aChannel->GetNativeServerTiming(mServerTiming);
// The performance timing api essentially requires that the event timestamps // The performance timing api essentially requires that the event timestamps
// have a strict relation with each other. The truth, however, is the // have a strict relation with each other. The truth, however, is the
@@ -673,17 +673,16 @@ PerformanceTiming::IsTopLevelContentDocument() const
return rootItem->ItemType() == nsIDocShellTreeItem::typeContent; return rootItem->ItemType() == nsIDocShellTreeItem::typeContent;
} }
already_AddRefed<nsIArray> nsTArray<nsCOMPtr<nsIServerTiming>>
PerformanceTimingData::GetServerTiming() const PerformanceTimingData::GetServerTiming()
{ {
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
!TimingAllowed() || !TimingAllowed() ||
nsContentUtils::ShouldResistFingerprinting()) { nsContentUtils::ShouldResistFingerprinting()) {
return nullptr; return nsTArray<nsCOMPtr<nsIServerTiming>>();
} }
nsCOMPtr<nsIArray> serverTiming = mServerTiming; return nsTArray<nsCOMPtr<nsIServerTiming>>(mServerTiming);
return serverTiming.forget();
} }
} // dom namespace } // dom namespace

View File

@@ -13,6 +13,7 @@
#include "nsRFPService.h" #include "nsRFPService.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "Performance.h" #include "Performance.h"
#include "nsITimedChannel.h"
class nsIHttpChannel; class nsIHttpChannel;
class nsITimedChannel; class nsITimedChannel;
@@ -169,7 +170,7 @@ public:
return mTimingAllowed; return mTimingAllowed;
} }
already_AddRefed<nsIArray> GetServerTiming() const; nsTArray<nsCOMPtr<nsIServerTiming>> GetServerTiming();
private: private:
// Checks if the resource is either same origin as the page that started // Checks if the resource is either same origin as the page that started
@@ -178,7 +179,7 @@ private:
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
nsITimedChannel* aChannel); nsITimedChannel* aChannel);
nsCOMPtr<nsIArray> mServerTiming; nsTArray<nsCOMPtr<nsIServerTiming>> mServerTiming;
nsString mNextHopProtocol; nsString mNextHopProtocol;
TimeStamp mAsyncOpen; TimeStamp mAsyncOpen;

View File

@@ -9,6 +9,8 @@ interface nsIPrincipal;
namespace mozilla { namespace mozilla {
class TimeStamp; class TimeStamp;
} }
#include "nsTArrayForwardDeclare.h"
#include "nsCOMPtr.h"
%} %}
native TimeStamp(mozilla::TimeStamp); native TimeStamp(mozilla::TimeStamp);
@@ -20,6 +22,8 @@ interface nsIServerTiming : nsISupports {
[must_use] readonly attribute ACString description; [must_use] readonly attribute ACString description;
}; };
[ref] native nsServerTimingArrayRef(nsTArray<nsCOMPtr<nsIServerTiming>>);
// All properties return zero if the value is not available // All properties return zero if the value is not available
[scriptable, uuid(ca63784d-959c-4c3a-9a59-234a2a520de0)] [scriptable, uuid(ca63784d-959c-4c3a-9a59-234a2a520de0)]
interface nsITimedChannel : nsISupports { interface nsITimedChannel : nsISupports {
@@ -110,4 +114,5 @@ interface nsITimedChannel : nsISupports {
[noscript] attribute boolean reportResourceTiming; [noscript] attribute boolean reportResourceTiming;
readonly attribute nsIArray serverTiming; readonly attribute nsIArray serverTiming;
nsServerTimingArrayRef getNativeServerTiming();
}; };

View File

@@ -4566,7 +4566,7 @@ HttpBaseChannel::CallTypeSniffers(void *aClosure, const uint8_t *aData,
template <class T> template <class T>
static void static void
ParseServerTimingHeader(const nsAutoPtr<T> &aHeader, ParseServerTimingHeader(const nsAutoPtr<T> &aHeader,
nsIMutableArray* aOutput) nsTArray<nsCOMPtr<nsIServerTiming>>& aOutput)
{ {
if (!aHeader) { if (!aHeader) {
return; return;
@@ -4582,27 +4582,39 @@ ParseServerTimingHeader(const nsAutoPtr<T> &aHeader,
parser.Parse(); parser.Parse();
nsTArray<nsCOMPtr<nsIServerTiming>> array = parser.TakeServerTimingHeaders(); nsTArray<nsCOMPtr<nsIServerTiming>> array = parser.TakeServerTimingHeaders();
for (const auto &data : array) { aOutput.AppendElements(array);
aOutput->AppendElement(data);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
HttpBaseChannel::GetServerTiming(nsIArray **aServerTiming) HttpBaseChannel::GetServerTiming(nsIArray **aServerTiming)
{ {
nsresult rv;
NS_ENSURE_ARG_POINTER(aServerTiming); NS_ENSURE_ARG_POINTER(aServerTiming);
bool isHTTPS = false;
if (NS_SUCCEEDED(mURI->SchemeIs("https", &isHTTPS)) && isHTTPS) {
nsTArray<nsCOMPtr<nsIServerTiming>> data;
nsresult rv = NS_OK;
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
ParseServerTimingHeader(mResponseHead, array); nsTArray<nsCOMPtr<nsIServerTiming>> data;
ParseServerTimingHeader(mResponseTrailers, array); rv = GetNativeServerTiming(data);
NS_ENSURE_SUCCESS(rv, rv);
for (const auto &entry : data) {
array->AppendElement(entry);
}
array.forget(aServerTiming); array.forget(aServerTiming);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetNativeServerTiming(nsTArray<nsCOMPtr<nsIServerTiming>>& aServerTiming)
{
aServerTiming.Clear();
bool isHTTPS = false;
if (NS_SUCCEEDED(mURI->SchemeIs("https", &isHTTPS)) && isHTTPS) {
ParseServerTimingHeader(mResponseHead, aServerTiming);
ParseServerTimingHeader(mResponseTrailers, aServerTiming);
} }
return NS_OK; return NS_OK;

View File

@@ -901,6 +901,12 @@ NullHttpChannel::GetServerTiming(nsIArray **aServerTiming)
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
NS_IMETHODIMP
NullHttpChannel::GetNativeServerTiming(nsTArray<nsCOMPtr<nsIServerTiming>>& aServerTiming)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#define IMPL_TIMING_ATTR(name) \ #define IMPL_TIMING_ATTR(name) \
NS_IMETHODIMP \ NS_IMETHODIMP \
NullHttpChannel::Get##name##Time(PRTime* _retval) { \ NullHttpChannel::Get##name##Time(PRTime* _retval) { \

View File

@@ -14,7 +14,7 @@
class nsServerTiming final : public nsIServerTiming class nsServerTiming final : public nsIServerTiming
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISERVERTIMING NS_DECL_NSISERVERTIMING
nsServerTiming() = default; nsServerTiming() = default;