Bug 1436517 - Limit access to the server-timing header to HTTPS contexts. r?mcmanus
This also introduces a hidden pref to allow server-timing access from
HTTP contexts for the purposes of our xpcshell tests. We'll remove that
once we get h2 (and therefore tls test) support for server-timing
trailers (https://bugzilla.mozilla.org/show_bug.cgi?id=1436601).
This does not reject or otherwise error when receiving server-timing
headers or trailers on non-HTTPS contexts, it just makes it unavailable
outside the channel.
MozReview-Commit-ID: qi4h0VQknE
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -4492,22 +4492,27 @@ ParseServerTimingHeader(const nsAutoPtr<
}
}
NS_IMETHODIMP
HttpBaseChannel::GetServerTiming(nsIArray **aServerTiming)
{
NS_ENSURE_ARG_POINTER(aServerTiming);
- nsTArray<nsCOMPtr<nsIServerTiming>> data;
- nsresult rv = NS_OK;
- nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- ParseServerTimingHeader(mResponseHead, array);
- ParseServerTimingHeader(mResponseTrailers, array);
-
- array.forget(aServerTiming);
+ bool isHTTPS = false;
+ if (gHttpHandler->AllowPlaintextServerTiming() ||
+ (NS_SUCCEEDED(mURI->SchemeIs("https", &isHTTPS)) && isHTTPS)) {
+ nsTArray<nsCOMPtr<nsIServerTiming>> data;
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ParseServerTimingHeader(mResponseHead, array);
+ ParseServerTimingHeader(mResponseTrailers, array);
+
+ array.forget(aServerTiming);
+ }
+
return NS_OK;
}
} // namespace net
} // namespace mozilla
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -283,16 +283,17 @@ nsHttpHandler::nsHttpHandler()
, mUseFastOpen(true)
, mFastOpenConsecutiveFailureLimit(5)
, mFastOpenConsecutiveFailureCounter(0)
, mFastOpenStallsLimit(3)
, mFastOpenStallsCounter(0)
, mFastOpenStallsIdleTime(10)
, mFastOpenStallsTimeout(20)
, mActiveTabPriority(true)
+ , mAllowPlaintextServerTiming(false)
, mProcessId(0)
, mNextChannelId(1)
, mLastActiveTabLoadOptimizationLock("nsHttpConnectionMgr::LastActiveTabLoadOptimization")
{
LOG(("Creating nsHttpHandler [this=%p].\n", this));
mUserAgentOverride.SetIsVoid(true);
@@ -459,16 +460,17 @@ nsHttpHandler::Init()
prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.long_lived_connections"), this, true);
prefBranch->AddObserver(SAFE_HINT_HEADER_VALUE, this, true);
prefBranch->AddObserver(SECURITY_PREFIX, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_ENABLE, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_FAILURE_LIMIT, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_LIMIT, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_IDLE, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_TIMEOUT, this, true);
+ prefBranch->AddObserver(HTTP_PREF("allow-plaintext-server-timing"), this, false);
PrefsChanged(prefBranch, nullptr);
}
nsHttpChannelAuthProvider::InitializePrefs();
mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
mCompatFirefox.AssignLiteral("Firefox/" MOZILLA_UAVERSION);
@@ -1769,16 +1771,20 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
if (ratio > 0 && ratio < 1) {
mFocusedWindowTransactionRatio = ratio;
} else {
NS_WARNING("Wrong value for focused_window_transaction_ratio");
}
}
}
+ if (PREF_CHANGED(HTTP_PREF("allow-plaintext-server-timing"))) {
+ Unused << prefs->GetBoolPref(HTTP_PREF("allow-plaintext-server-timing"), &mAllowPlaintextServerTiming);
+ }
+
//
// INTL options
//
if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
// We don't want to set the new accept languages here since
// this pref is a complex type and it may be racy with flushing
// string resources.
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -143,16 +143,18 @@ public:
uint32_t TailBlockingDelayQuantum(bool aAfterDOMContentLoaded) {
return aAfterDOMContentLoaded ? mTailDelayQuantumAfterDCL : mTailDelayQuantum;
}
uint32_t TailBlockingDelayMax() { return mTailDelayMax; }
uint32_t TailBlockingTotalMax() { return mTailTotalMax; }
uint32_t ThrottlingReadLimit() { return mThrottleVersion == 1 ? 0 : mThrottleReadLimit; }
+ bool AllowPlaintextServerTiming() { return mAllowPlaintextServerTiming; }
+
// TCP Keepalive configuration values.
// Returns true if TCP keepalive should be enabled for short-lived conns.
bool TCPKeepaliveEnabledForShortLivedConns() {
return mTCPKeepaliveShortLivedEnabled;
}
// Return time (secs) that a connection is consider short lived (for TCP
// keepalive purposes). After this time, the connection is long-lived.
@@ -661,16 +663,18 @@ private:
uint32_t mFastOpenStallsLimit;
uint32_t mFastOpenStallsCounter;
uint32_t mFastOpenStallsIdleTime;
uint32_t mFastOpenStallsTimeout;
// If true, the transactions from active tab will be dispatched first.
bool mActiveTabPriority;
+ bool mAllowPlaintextServerTiming;
+
private:
// For Rate Pacing Certain Network Events. Only assign this pointer on
// socket thread.
void MakeNewRequestTokenBucket();
RefPtr<EventTokenBucket> mRequestTokenBucket;
public:
// Socket thread only
--- a/netwerk/test/unit/test_header_Server_Timing.js
+++ b/netwerk/test/unit/test_header_Server_Timing.js
@@ -49,16 +49,21 @@ function contentHandler(metadata, respon
response.write(body);
response.write(createServerTimingHeader(trailerServerTiming));
response.write("\r\n");
response.finish();
}
function run_test()
{
+ Services.prefs.setBoolPref("network.http.allow-plaintext-server-timing", true);
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("network.http.allow-plaintext-server-timing");
+ });
+
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
httpServer.start(-1);
do_test_pending();
make_and_open_channel(URL, readServerContent);
}