Backed out changeset 728aa342ad35 (bug 1536511) for causing crashes on Bug 1545023. a=backout
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Mon, 22 Apr 2019 14:57:20 +0300
changeset 470331 34059c6188e54415a97125be22b06040dbcc2f93
parent 470330 b783cd5203ea589bb7505852e5108ed142d2d37a
child 470346 1d1471ae2e7ac6a16c3b2663ca25d4c82cc68864
push id35900
push usernbeleuzu@mozilla.com
push dateMon, 22 Apr 2019 11:57:53 +0000
treeherdermozilla-central@34059c6188e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1536511, 1545023
milestone68.0a1
backs out728aa342ad358ada0d1ab191108bd9ea3e31173f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 728aa342ad35 (bug 1536511) for causing crashes on Bug 1545023. a=backout
netwerk/protocol/http/nsHttp.cpp
netwerk/protocol/http/nsHttp.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/http/nsHttpResponseHead.cpp
netwerk/protocol/http/nsHttpResponseHead.h
netwerk/protocol/http/nsIHttpProtocolHandler.idl
netwerk/test/unit/test_stale-while-revalidate_max-age-0.js
netwerk/test/unit/test_stale-while-revalidate_negative.js
netwerk/test/unit/test_stale-while-revalidate_positive.js
netwerk/test/unit/xpcshell.ini
testing/web-platform/meta/fetch/stale-while-revalidate/fetch-sw.https.tentative.html.ini
testing/web-platform/meta/fetch/stale-while-revalidate/fetch.tentative.html.ini
testing/web-platform/meta/fetch/stale-while-revalidate/stale-image.tentative.html.ini
testing/web-platform/meta/fetch/stale-while-revalidate/stale-script.tentative.html.ini
testing/web-platform/tests/fetch/stale-while-revalidate/fetch-sw.https.tentative.html
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -298,22 +298,17 @@ bool IsPermanentRedirect(uint32_t httpSt
 }
 
 bool ValidationRequired(bool isForcedValid,
                         nsHttpResponseHead *cachedResponseHead,
                         uint32_t loadFlags, bool allowStaleCacheContent,
                         bool isImmutable, bool customConditionalRequest,
                         nsHttpRequestHead &requestHead, nsICacheEntry *entry,
                         CacheControlParser &cacheControlRequest,
-                        bool fromPreviousSession,
-                        bool *performBackgroundRevalidation) {
-  if (performBackgroundRevalidation) {
-    *performBackgroundRevalidation = false;
-  }
-
+                        bool fromPreviousSession) {
   // Check isForcedValid to see if it is possible to skip validation.
   // Don't skip validation if we have serious reason to believe that this
   // content is invalid (it's expired).
   // See netwerk/cache2/nsICacheEntry.idl for details
   if (isForcedValid && (!cachedResponseHead->ExpiresInPast() ||
                         !cachedResponseHead->MustValidateIfExpired())) {
     LOG(("NOT validating based on isForcedValid being true.\n"));
     return false;
@@ -411,22 +406,16 @@ bool ValidationRequired(bool isForcedVal
     doValidation = freshTime < minFreshRequest;
     LOG(("  validating=%d, min-fresh=%u requested", doValidation,
          minFreshRequest));
   } else if (now < expiration) {
     doValidation = false;
     LOG(("  not validating, expire time not in the past"));
   } else if (cachedResponseHead->MustValidateIfExpired()) {
     doValidation = true;
-  } else if (cachedResponseHead->StaleWhileRevalidate(now, expiration)) {
-    LOG(("  not validating, in the stall-while-revalidate window"));
-    doValidation = false;
-    if (performBackgroundRevalidation) {
-      *performBackgroundRevalidation = true;
-    }
   } else if (loadFlags & nsIRequest::VALIDATE_ONCE_PER_SESSION) {
     // If the cached response does not include expiration infor-
     // mation, then we must validate the response, despite whether
     // or not this is the first access this session.  This behavior
     // is consistent with existing browsers and is generally expected
     // by web authors.
     if (freshness == 0)
       doValidation = true;
--- a/netwerk/protocol/http/nsHttp.h
+++ b/netwerk/protocol/http/nsHttp.h
@@ -215,18 +215,17 @@ bool IsPermanentRedirect(uint32_t httpSt
 const char *GetProtocolVersion(HttpVersion pv);
 
 bool ValidationRequired(bool isForcedValid,
                         nsHttpResponseHead *cachedResponseHead,
                         uint32_t loadFlags, bool allowStaleCacheContent,
                         bool isImmutable, bool customConditionalRequest,
                         nsHttpRequestHead &requestHead, nsICacheEntry *entry,
                         CacheControlParser &cacheControlRequest,
-                        bool fromPreviousSession,
-                        bool *performBackgroundRevalidation = nullptr);
+                        bool fromPreviousSession);
 
 nsresult GetHttpResponseHeadFromCacheEntry(
     nsICacheEntry *entry, nsHttpResponseHead *cachedResponseHead);
 
 nsresult CheckPartial(nsICacheEntry *aEntry, int64_t *aSize,
                       int64_t *aContentLength,
                       nsHttpResponseHead *responseHead);
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4362,17 +4362,16 @@ nsHttpChannel::OnCacheEntryCheck(nsICach
     }
   }
 
   bool isHttps = false;
   rv = mURI->SchemeIs("https", &isHttps);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool doValidation = false;
-  bool doBackgroundValidation = false;
   bool canAddImsHeader = true;
 
   bool isForcedValid = false;
   entry->GetIsForcedValid(&isForcedValid);
 
   bool weaklyFramed, isImmutable;
   nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead, isHttps,
                                           &weaklyFramed, &isImmutable);
@@ -4381,17 +4380,17 @@ nsHttpChannel::OnCacheEntryCheck(nsICach
   if (ResponseWouldVary(entry)) {
     LOG(("Validating based on Vary headers returning TRUE\n"));
     canAddImsHeader = false;
     doValidation = true;
   } else {
     doValidation = nsHttp::ValidationRequired(
         isForcedValid, mCachedResponseHead, mLoadFlags, mAllowStaleCacheContent,
         isImmutable, mCustomConditionalRequest, mRequestHead, entry,
-        cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
+        cacheControlRequest, fromPreviousSession);
   }
 
   // If a content signature is expected to be valid in this load,
   // set doValidation to force a signature check.
   if (!doValidation && mLoadInfo && mLoadInfo->GetVerifySignedContent()) {
     doValidation = true;
   }
 
@@ -4525,20 +4524,16 @@ nsHttpChannel::OnCacheEntryCheck(nsICach
   }
 
   if (mDidReval)
     *aResult = ENTRY_NEEDS_REVALIDATION;
   else if (wantCompleteEntry)
     *aResult = RECHECK_AFTER_WRITE_FINISHED;
   else {
     *aResult = ENTRY_WANTED;
-
-    if (doBackgroundValidation) {
-      PerformBackgroundCacheRevalidation();
-    }
   }
 
   if (mCachedContentIsValid) {
     entry->MaybeMarkValid();
   }
 
   LOG(
       ("nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
@@ -4870,48 +4865,40 @@ nsresult DoUpdateExpirationTime(nsHttpCh
                                 nsHttpResponseHead *aResponseHead,
                                 uint32_t &aExpirationTime) {
   MOZ_ASSERT(aExpirationTime == 0);
   NS_ENSURE_TRUE(aResponseHead, NS_ERROR_FAILURE);
 
   nsresult rv;
 
   if (!aResponseHead->MustValidate()) {
-    // For stale-while-revalidate we use expiration time as the absolute base
-    // for calculation of the stale window absolute end time.  Hence, when the
-    // entry may be served w/o revalidation, we need a non-zero value for the
-    // expiration time.  Let's set it to |now|, which basicly means "expired",
-    // same as when set to 0.
-    uint32_t now = NowInSeconds();
-    aExpirationTime = now;
-
     uint32_t freshnessLifetime = 0;
 
     rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
     if (NS_FAILED(rv)) return rv;
 
     if (freshnessLifetime > 0) {
-      uint32_t currentAge = 0;
+      uint32_t now = NowInSeconds(), currentAge = 0;
 
       rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
                                             &currentAge);
       if (NS_FAILED(rv)) return rv;
 
       LOG(("freshnessLifetime = %u, currentAge = %u\n", freshnessLifetime,
            currentAge));
 
       if (freshnessLifetime > currentAge) {
         uint32_t timeRemaining = freshnessLifetime - currentAge;
         // be careful... now + timeRemaining may overflow
-        if (now + timeRemaining < now) {
+        if (now + timeRemaining < now)
           aExpirationTime = uint32_t(-1);
-        } else {
+        else
           aExpirationTime = now + timeRemaining;
-        }
-      }
+      } else
+        aExpirationTime = 0;
     }
   }
 
   rv = aCacheEntry->SetExpirationTime(aExpirationTime);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return rv;
 }
@@ -10249,118 +10236,10 @@ void nsHttpChannel::ReEvaluateReferrerAf
     if (mOriginalReferrer && mOriginalReferrerPolicy == REFERRER_POLICY_UNSET &&
         mReferrerPolicy ==
             NS_GetDefaultReferrerPolicy(nullptr, nullptr, isPrivate)) {
       SetReferrer(mOriginalReferrer);
     }
   }
 }
 
-namespace {
-
-class BackgroundRevalidatingListener : public nsIStreamListener {
-  NS_DECL_ISUPPORTS
-
-  NS_DECL_NSISTREAMLISTENER
-  NS_DECL_NSIREQUESTOBSERVER
-
- private:
-  virtual ~BackgroundRevalidatingListener() = default;
-};
-
-NS_IMETHODIMP
-BackgroundRevalidatingListener::OnStartRequest(nsIRequest *request) {
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BackgroundRevalidatingListener::OnDataAvailable(nsIRequest *request,
-                                                nsIInputStream *input,
-                                                uint64_t offset,
-                                                uint32_t count) {
-  uint32_t bytesRead = 0;
-  input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BackgroundRevalidatingListener::OnStopRequest(nsIRequest *request,
-                                              nsresult status) {
-  nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
-  if (gHttpHandler) {
-    gHttpHandler->OnBackgroundRevalidation(channel);
-  }
-  return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(BackgroundRevalidatingListener, nsIStreamListener,
-                  nsIRequestObserver)
-
-}  // namespace
-
-void nsHttpChannel::PerformBackgroundCacheRevalidation() {
-  LOG(("nsHttpChannel::PerformBackgroundCacheRevalidation %p", this));
-
-  Unused << NS_DispatchToMainThreadQueue(
-      NewIdleRunnableMethod(
-          "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
-          &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
-      EventQueuePriority::Idle);
-}
-
-void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
-  LOG(("nsHttpChannel::PerformBackgroundCacheRevalidationNow %p", this));
-
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsresult rv;
-
-  nsSecurityFlags secFlags;
-  rv = mLoadInfo->GetSecurityFlags(&secFlags);
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  secFlags |= nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS;
-
-  nsCOMPtr<nsICookieSettings> cookieSettings;
-  rv = mLoadInfo->GetCookieSettings(getter_AddRefs(cookieSettings));
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  nsCOMPtr<nsIChannel> validatingChannel;
-  rv = NS_NewChannel(getter_AddRefs(validatingChannel), mURI,
-                     mLoadInfo->LoadingPrincipal(), secFlags,
-                     mLoadInfo->InternalContentPolicyType(), cookieSettings,
-                     nullptr /* performance storage */, mLoadGroup, mCallbacks,
-                     LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS | LOAD_BACKGROUND |
-                         LOAD_BYPASS_SERVICE_WORKER);
-  if (NS_FAILED(rv)) {
-    LOG(("  failed to created the channel, rv=0x%08x",
-         static_cast<uint32_t>(rv)));
-    return;
-  }
-
-  nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
-  if (priority) {
-    priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
-  }
-
-  nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
-  if (cos) {
-    cos->AddClassFlags(nsIClassOfService::Tail);
-  }
-
-  RefPtr<BackgroundRevalidatingListener> listener =
-      new BackgroundRevalidatingListener();
-  rv = validatingChannel->AsyncOpen(listener);
-  if (NS_FAILED(rv)) {
-    LOG(("  failed to open the channel, rv=0x%08x", static_cast<uint32_t>(rv)));
-    return;
-  }
-
-  LOG(("  %p is re-validating with a new channel %p", this,
-       validatingChannel.get()));
-}
-
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -582,24 +582,16 @@ class nsHttpChannel final : public HttpB
   // Proxy release all members above on main thread.
   void ReleaseMainThreadOnlyReferences();
 
   // Called after the channel is made aware of its tracking status in order
   // to readjust the referrer if needed according to the referrer default
   // policy preferences.
   void ReEvaluateReferrerAfterTrackingStatusIsKnown();
 
-  // Create a dummy channel for the same principal, out of the load group
-  // just to revalidate the cache entry.  We don't care if this fails.
-  // This method can be called on any thread, and creates an idle task
-  // to perform the revalidation with delay.
-  void PerformBackgroundCacheRevalidation();
-  // This method can only be called on the main thread.
-  void PerformBackgroundCacheRevalidationNow();
-
  private:
   nsCOMPtr<nsICancelable> mProxyRequest;
 
   RefPtr<nsInputStreamPump> mTransactionPump;
   RefPtr<nsHttpTransaction> mTransaction;
 
   uint64_t mLogicalOffset;
 
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -354,21 +354,16 @@ class nsHttpHandler final : public nsIHt
     NotifyObservers(chan, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC);
   }
 
   // Called by the channel once headers have been merged with cached headers
   void OnExamineMergedResponse(nsIHttpChannel *chan) {
     NotifyObservers(chan, NS_HTTP_ON_EXAMINE_MERGED_RESPONSE_TOPIC);
   }
 
-  // Called by the channel once it made background cache revalidation
-  void OnBackgroundRevalidation(nsIHttpChannel *chan) {
-    NotifyObservers(chan, NS_HTTP_ON_BACKGROUND_REVALIDATION);
-  }
-
   // Called by channels before a redirect happens. This notifies both the
   // channel's and the global redirect observers.
   MOZ_MUST_USE nsresult AsyncOnChannelRedirect(
       nsIChannel *oldChan, nsIChannel *newChan, uint32_t flags,
       nsIEventTarget *mainThreadEventTarget = nullptr);
 
   // Called by the channel when the response is read from the cache without
   // communicating with the server.
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -748,46 +748,16 @@ bool nsHttpResponseHead::MustValidateIfE
   //  When the must-revalidate directive is present in a response received by a
   //  cache, that cache MUST NOT use the entry after it becomes stale to respond
   //  to a subsequent request without first revalidating it with the origin
   //  server.
   //
   return HasHeaderValue(nsHttp::Cache_Control, "must-revalidate");
 }
 
-bool nsHttpResponseHead::StaleWhileRevalidate(uint32_t now,
-                                              uint32_t expiration) {
-  nsresult rv;
-
-  if (expiration <= 0) {
-    return false;
-  }
-
-  uint32_t revalidateWindow;
-  rv = GetStaleWhileRevalidateValue(&revalidateWindow);
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-
-  // 'expiration' is the expiration time (an absolute unit), the swr window
-  // extends the expiration time.
-  CheckedInt<uint32_t> stallValidUntil = expiration;
-  stallValidUntil += revalidateWindow;
-  if (!stallValidUntil.isValid()) {
-    // overflow means an indefinite stale window
-    return true;
-  }
-
-  if (now > stallValidUntil.value()) {
-    return false;
-  }
-
-  return true;
-}
-
 bool nsHttpResponseHead::IsResumable() {
   RecursiveMutexAutoLock monitor(mRecursiveMutex);
   // even though some HTTP/1.0 servers may support byte range requests, we're
   // not going to bother with them, since those servers wouldn't understand
   // If-Range. Also, while in theory it may be possible to resume when the
   // status code is not 200, it is unlikely to be worth the trouble, especially
   // for non-2xx responses.
   return mStatus == 200 && mVersion >= HttpVersion::v1_1 &&
@@ -927,55 +897,16 @@ nsresult nsHttpResponseHead::GetMaxAgeVa
   while (*p == ' ' || *p == '\t') ++p;
 
   int maxAgeValue = atoi(p);
   if (maxAgeValue < 0) maxAgeValue = 0;
   *result = static_cast<uint32_t>(maxAgeValue);
   return NS_OK;
 }
 
-// Get the stale-while-revalidate directive value, if present
-nsresult nsHttpResponseHead::GetStaleWhileRevalidateValue(uint32_t *result) {
-  RecursiveMutexAutoLock monitor(mRecursiveMutex);
-  return GetStaleWhileRevalidateValue_locked(result);
-}
-
-nsresult nsHttpResponseHead::GetStaleWhileRevalidateValue_locked(
-    uint32_t *result) const {
-  const char *val = mHeaders.PeekHeader(nsHttp::Cache_Control);
-  if (!val) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // Rewrite (best all FindToken users) to mozilla::Tokenizer, bug 1542293.
-  const char *p = nsHttp::FindToken(val, "stale-while-revalidate",
-                                    HTTP_HEADER_VALUE_SEPS "=");
-  if (!p) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  p += 22;
-  while (*p == ' ' || *p == '\t') {
-    ++p;
-  }
-  if (*p != '=') {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  ++p;
-  while (*p == ' ' || *p == '\t') {
-    ++p;
-  }
-
-  int revalidateWindow = atoi(p);
-  if (revalidateWindow < 0) {
-    revalidateWindow = 0;
-  }
-  *result = static_cast<uint32_t>(revalidateWindow);
-  return NS_OK;
-}
-
 nsresult nsHttpResponseHead::GetDateValue(uint32_t *result) {
   RecursiveMutexAutoLock monitor(mRecursiveMutex);
   return GetDateValue_locked(result);
 }
 
 nsresult nsHttpResponseHead::GetExpiresValue(uint32_t *result) {
   RecursiveMutexAutoLock monitor(mRecursiveMutex);
   return GetExpiresValue_locked(result);
--- a/netwerk/protocol/http/nsHttpResponseHead.h
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -112,37 +112,31 @@ class nsHttpResponseHead {
 
   // cache validation support methods
   MOZ_MUST_USE nsresult ComputeFreshnessLifetime(uint32_t *);
   MOZ_MUST_USE nsresult ComputeCurrentAge(uint32_t now, uint32_t requestTime,
                                           uint32_t *result);
   bool MustValidate();
   bool MustValidateIfExpired();
 
-  // return true if the response contains a valid Cache-control:
-  // stale-while-revalidate and |now| is less than or equal |expiration +
-  // stale-while-revalidate|.  Otherwise false.
-  bool StaleWhileRevalidate(uint32_t now, uint32_t expiration);
-
   // returns true if the server appears to support byte range requests.
   bool IsResumable();
 
   // returns true if the Expires header has a value in the past relative to the
   // value of the Date header.
   bool ExpiresInPast();
 
   // update headers...
   MOZ_MUST_USE nsresult UpdateHeaders(nsHttpResponseHead *headers);
 
   // reset the response head to it's initial state
   void Reset();
 
   MOZ_MUST_USE nsresult GetAgeValue(uint32_t *result);
   MOZ_MUST_USE nsresult GetMaxAgeValue(uint32_t *result);
-  MOZ_MUST_USE nsresult GetStaleWhileRevalidateValue(uint32_t *result);
   MOZ_MUST_USE nsresult GetDateValue(uint32_t *result);
   MOZ_MUST_USE nsresult GetExpiresValue(uint32_t *result);
   MOZ_MUST_USE nsresult GetLastModifiedValue(uint32_t *result);
 
   bool operator==(const nsHttpResponseHead &aOther) const;
 
   // Using this function it is possible to itereate through all headers
   // automatically under one lock.
@@ -169,18 +163,16 @@ class nsHttpResponseHead {
   // these return failure if the header does not exist.
   MOZ_MUST_USE nsresult ParseDateHeader(nsHttpAtom header,
                                         uint32_t *result) const;
 
   bool ExpiresInPast_locked() const;
   MOZ_MUST_USE nsresult GetAgeValue_locked(uint32_t *result) const;
   MOZ_MUST_USE nsresult GetExpiresValue_locked(uint32_t *result) const;
   MOZ_MUST_USE nsresult GetMaxAgeValue_locked(uint32_t *result) const;
-  MOZ_MUST_USE nsresult
-  GetStaleWhileRevalidateValue_locked(uint32_t *result) const;
 
   MOZ_MUST_USE nsresult GetDateValue_locked(uint32_t *result) const {
     return ParseDateHeader(nsHttp::Date, result);
   }
 
   MOZ_MUST_USE nsresult GetLastModifiedValue_locked(uint32_t *result) const {
     return ParseDateHeader(nsHttp::Last_Modified, result);
   }
--- a/netwerk/protocol/http/nsIHttpProtocolHandler.idl
+++ b/netwerk/protocol/http/nsIHttpProtocolHandler.idl
@@ -135,24 +135,16 @@ interface nsIHttpProtocolHandler : nsIPr
 /**
  * The observer of this topic is notified after the received HTTP response
  * is merged with data from the browser cache.  This means that, among other
  * things, the Content-Type header will be set correctly.
  */
 #define NS_HTTP_ON_EXAMINE_MERGED_RESPONSE_TOPIC "http-on-examine-merged-response"
 
 /**
- * The observer of this topic is notified about a background revalidation that
- * started by hitting a request that fell into stale-while-revalidate window.
- * This notification points to the channel that performed the revalidation and
- * after this notification the cache entry has been validated or updated.
- */
-#define NS_HTTP_ON_BACKGROUND_REVALIDATION "http-on-background-revalidation"
-
-/**
  * The observer of this topic is notified before data is read from the cache.
  * The notification is sent if and only if there is no network communication
  * at all.
  */
 #define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response"
 
 /**
  * The observer of this topic is notified before before the response for a HTTP
deleted file mode 100644
--- a/netwerk/test/unit/test_stale-while-revalidate_max-age-0.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-
-Tests the Cache-control: stale-while-revalidate response directive.
-
-Purpose is to check we perform the background revalidation when max-age=0 but
-the window is set and we hit it.
-
-* Make request #1.
-  - response is from the server and version=1
-  - max-age=0, stale-while-revalidate=9999
-* Switch version of the data on the server and prolong the max-age to not let req #3
-  do a bck reval at the end of the test (prevent leaks/shutdown races.)
-* Make request #2 in 2 seconds (entry should be expired by that time, but fall into
-  the reval window.)
-  - response is from the cache, version=1
-  - a new background request should be made for the data
-* Wait for "http-on-background-revalidation" notifying finish of the background reval.
-* Make request #3.
-  - response is from the cache, version=2
-* Done.
-
-*/
-
-"use strict";
-
-const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
-const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
-
-function run_test() {
-  run_next_test();
-}
-
-let max_age;
-let version;
-let generate_response = ver => `response version=${ver}`;
-
-function test_handler(metadata, response) {
-  const originalBody = generate_response(version);
-  response.setHeader("Content-Type", "text/html", false);
-  response.setHeader("Cache-control", `max-age=${max_age}, stale-while-revalidate=9999`, false);
-  response.setStatusLine(metadata.httpVersion, 200, "OK");
-  response.bodyOutputStream.write(originalBody, originalBody.length);
-}
-
-function make_channel(url) {
-  return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
-                .QueryInterface(Ci.nsIHttpChannel);
-}
-
-async function get_response(channel, fromCache) {
-  return new Promise(resolve => {
-    channel.asyncOpen(new ChannelListener((request, buffer, ctx, isFromCache) => {
-      ok(fromCache == isFromCache, `got response from cache = ${fromCache}`);
-      resolve(buffer);
-    }));
-  });
-}
-
-async function sleep(time) {
-  return new Promise(resolve => {
-    do_timeout(time * 1000, resolve);
-  });
-}
-
-async function stop_server(httpserver) {
-  return new Promise(resolve => {
-    httpserver.stop(resolve);
-  });
-}
-
-async function background_reval_promise() {
-  return new Promise(resolve => {
-    Services.obs.addObserver(resolve, "http-on-background-revalidation");
-  });
-}
-
-add_task(async function() {
-  let httpserver = new HttpServer();
-  httpserver.registerPathHandler("/testdir", test_handler);
-  httpserver.start(-1);
-  const PORT = httpserver.identity.primaryPort;
-  const URI = `http://localhost:${PORT}/testdir`;
-
-  let response;
-
-  version = 1;
-  max_age = 0;
-  response = await get_response(make_channel(URI), false);
-  ok(response == generate_response(1), "got response ver 1");
-
-  await sleep(2);
-
-  // must specifically wait for the internal channel to finish the reval to make
-  // the test race-free.
-  let reval_done = background_reval_promise();
-
-  version = 2;
-  max_age = 100;
-  response = await get_response(make_channel(URI), true);
-  ok(response == generate_response(1), "got response ver 1");
-
-  await reval_done;
-
-  response = await get_response(make_channel(URI), true);
-  ok(response == generate_response(2), "got response ver 2");
-
-  await stop_server(httpserver);
-});
deleted file mode 100644
--- a/netwerk/test/unit/test_stale-while-revalidate_negative.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-
-Tests the Cache-control: stale-while-revalidate response directive.
-
-Purpose is to check we DON'T perform the background revalidation when we make the
-request past the reval window.
-
-* Make request #1.
-  - response is from the server and version=1
-  - max-age=1, stale-while-revalidate=1
-* Switch version of the data on the server.
-* Make request #2 in 3 seconds (entry should be expired by that time and no longer
-  fall into the reval window.)
-  - response is from the server, version=2
-* Done.
-
-*/
-
-"use strict";
-
-const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
-const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
-
-function run_test() {
-  run_next_test();
-}
-
-let max_age;
-let version;
-let generate_response = ver => `response version=${ver}`;
-
-function test_handler(metadata, response) {
-  const originalBody = generate_response(version);
-  response.setHeader("Content-Type", "text/html", false);
-  response.setHeader("Cache-control", `max-age=${max_age}, stale-while-revalidate=1`, false);
-  response.setStatusLine(metadata.httpVersion, 200, "OK");
-  response.bodyOutputStream.write(originalBody, originalBody.length);
-}
-
-function make_channel(url) {
-  return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
-                .QueryInterface(Ci.nsIHttpChannel);
-}
-
-async function get_response(channel, fromCache) {
-  return new Promise(resolve => {
-    channel.asyncOpen(new ChannelListener((request, buffer, ctx, isFromCache) => {
-      ok(fromCache == isFromCache, `got response from cache = ${fromCache}`);
-      resolve(buffer);
-    }));
-  });
-}
-
-async function sleep(time) {
-  return new Promise(resolve => {
-    do_timeout(time * 1000, resolve);
-  });
-}
-
-async function stop_server(httpserver) {
-  return new Promise(resolve => {
-    httpserver.stop(resolve);
-  });
-}
-
-add_task(async function() {
-  let httpserver = new HttpServer();
-  httpserver.registerPathHandler("/testdir", test_handler);
-  httpserver.start(-1);
-  const PORT = httpserver.identity.primaryPort;
-  const URI = `http://localhost:${PORT}/testdir`;
-
-  let response;
-
-  version = 1;
-  max_age = 1;
-  response = await get_response(make_channel(URI), false);
-  ok(response == generate_response(1), "got response ver 1");
-
-  await sleep(max_age + 1 /* stale window */ + 1 /* to expire the window */);
-
-  version = 2;
-  response = await get_response(make_channel(URI), false);
-  ok(response == generate_response(2), "got response ver 2");
-
-  await stop_server(httpserver);
-});
deleted file mode 100644
--- a/netwerk/test/unit/test_stale-while-revalidate_positive.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-
-Tests the Cache-control: stale-while-revalidate response directive.
-
-Purpose is to check we perform the background revalidation when the window is set
-and we hit it.
-
-* Make request #1.
-  - response is from the server and version=1
-  - max-age=1, stale-while-revalidate=9999
-* Switch version of the data on the server and prolong the max-age to not let req #3
-  do a bck reval at the end of the test (prevent leaks/shutdown races.)
-* Make request #2 in 2 seconds (entry should be expired by that time, but fall into
-  the reval window.)
-  - response is from the cache, version=1
-  - a new background request should be made for the data
-* Wait for "http-on-background-revalidation" notifying finish of the background reval.
-* Make request #3.
-  - response is from the cache, version=2
-* Done.
-
-*/
-
-"use strict";
-
-const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
-const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
-
-function run_test() {
-  run_next_test();
-}
-
-let max_age;
-let version;
-let generate_response = ver => `response version=${ver}`;
-
-function test_handler(metadata, response) {
-  const originalBody = generate_response(version);
-  response.setHeader("Content-Type", "text/html", false);
-  response.setHeader("Cache-control", `max-age=${max_age}, stale-while-revalidate=9999`, false);
-  response.setStatusLine(metadata.httpVersion, 200, "OK");
-  response.bodyOutputStream.write(originalBody, originalBody.length);
-}
-
-function make_channel(url) {
-  return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
-                .QueryInterface(Ci.nsIHttpChannel);
-}
-
-async function get_response(channel, fromCache) {
-  return new Promise(resolve => {
-    channel.asyncOpen(new ChannelListener((request, buffer, ctx, isFromCache) => {
-      ok(fromCache == isFromCache, `got response from cache = ${fromCache}`);
-      resolve(buffer);
-    }));
-  });
-}
-
-async function sleep(time) {
-  return new Promise(resolve => {
-    do_timeout(time * 1000, resolve);
-  });
-}
-
-async function stop_server(httpserver) {
-  return new Promise(resolve => {
-    httpserver.stop(resolve);
-  });
-}
-
-async function background_reval_promise() {
-  return new Promise(resolve => {
-    Services.obs.addObserver(resolve, "http-on-background-revalidation");
-  });
-}
-
-add_task(async function() {
-  let httpserver = new HttpServer();
-  httpserver.registerPathHandler("/testdir", test_handler);
-  httpserver.start(-1);
-  const PORT = httpserver.identity.primaryPort;
-  const URI = `http://localhost:${PORT}/testdir`;
-
-  let response;
-
-  version = 1;
-  max_age = 1;
-  response = await get_response(make_channel(URI), false);
-  ok(response == generate_response(1), "got response ver 1");
-
-  await sleep(max_age + 1);
-
-  // must specifically wait for the internal channel to finish the reval to make
-  // the test race-free.
-  let reval_done = background_reval_promise();
-
-  version = 2;
-  max_age = 100;
-  response = await get_response(make_channel(URI), true);
-  ok(response == generate_response(1), "got response ver 1");
-
-  await reval_done;
-
-  response = await get_response(make_channel(URI), true);
-  ok(response == generate_response(2), "got response ver 2");
-
-  await stop_server(httpserver);
-});
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -425,11 +425,8 @@ run-sequentially = node server exception
 [test_esni_dns_fetch.js]
 # http2-using tests require node available
 skip-if = os == "android" || (os == "win" && processor == "aarch64") # bug 1536211
 [test_network_connectivity_service.js]
 skip-if = os == "android" # DNSv6 issues on android
 [test_suspend_channel_on_authRetry.js]
 [test_suspend_channel_on_examine_merged_response.js]
 [test_bug1527293.js]
-[test_stale-while-revalidate_negative.js]
-[test_stale-while-revalidate_positive.js]
-[test_stale-while-revalidate_max-age-0.js]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/fetch/stale-while-revalidate/fetch-sw.https.tentative.html.ini
@@ -0,0 +1,4 @@
+[fetch-sw.https.tentative.html]
+  [Second fetch returns same response]
+    expected: FAIL
+
--- a/testing/web-platform/meta/fetch/stale-while-revalidate/fetch.tentative.html.ini
+++ b/testing/web-platform/meta/fetch/stale-while-revalidate/fetch.tentative.html.ini
@@ -1,4 +1,4 @@
 [fetch.tentative.html]
-  max-asserts: 1
-  [Second fetch does not return same response]
+  [Second fetch returns same response]
     expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/fetch/stale-while-revalidate/stale-image.tentative.html.ini
@@ -0,0 +1,4 @@
+[stale-image.tentative.html]
+  [Cache returns stale resource]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/fetch/stale-while-revalidate/stale-script.tentative.html.ini
@@ -0,0 +1,4 @@
+[stale-script.tentative.html]
+  [Cache returns stale resource]
+    expected: FAIL
+
--- a/testing/web-platform/tests/fetch/stale-while-revalidate/fetch-sw.https.tentative.html
+++ b/testing/web-platform/tests/fetch/stale-while-revalidate/fetch-sw.https.tentative.html
@@ -11,40 +11,36 @@ https://github.com/whatwg/fetch/pull/853
   <script src="/resources/testharnessreport.js"></script>
   <script src="../../service-workers/service-worker/resources/test-helpers.sub.js"></script>
   <script src="/common/utils.js"></script>
 </head>
 <body>
 <script>
 
   // Duplicating this resource to make service worker scoping simpler.
-  async function setupRegistrationAndWaitToBeControlled(t, scope) {
-    const controlled = new Promise((resolve) => {
-      navigator.serviceWorker.oncontrollerchange = () => { resolve(); };
-    });
+  async function setupRegistration(t, scope) {
     const reg = await navigator.serviceWorker.register('sw-intercept.js');
     await wait_for_state(t, reg.installing, 'activated');
-    await controlled;
     add_completion_callback(_ => reg.unregister());
     return reg;
   }
 
-  function wait250ms(test) {
+  function wait25ms(test) {
     return new Promise(resolve => {
       test.step_timeout(() => {
         resolve();
-      }, 250);
+      }, 25);
     });
   }
 
   promise_test(async (test) => {
     var request_token = token();
     const uri = 'stale-script.py?token=' + request_token;
 
-    await setupRegistrationAndWaitToBeControlled(test, 'stale-script.py');
+    await setupRegistration(test, 'stale-script.py');
 
     var service_worker_count = 0;
     navigator.serviceWorker.addEventListener('message', function once(event) {
       if (event.data.endsWith(uri)) {
         service_worker_count++;
       }
     });
 
@@ -53,15 +49,15 @@ https://github.com/whatwg/fetch/pull/853
     assert_equals(response.headers.get('Unique-Id'), response2.headers.get('Unique-Id'));
     while(true) {
       const revalidation_check = await fetch(`stale-script.py?query&token=` + request_token);
       if (revalidation_check.headers.get('Count') == '2') {
         // The service worker should not see the revalidation request.
         assert_equals(service_worker_count, 2);
         break;
       }
-      await wait250ms(test);
+      await wait25ms(test);
     }
   }, 'Second fetch returns same response');
 
 </script>
 </body>
 </html>