Bug 1174078 - Calling "fetch" inside Service Worker's "onfetch" handler in b2g causes "onfetch" again that leads to an infinite loop. r=nsm
authorFernando Jimenez <ferjmoreno@gmail.com>
Wed, 17 Jun 2015 11:50:07 +0200
changeset 280095 e8d2c117e4b194f0d3154d51b367af567f8ecd1d
parent 280094 6e3419fdcd80f97c025f05f3f699ffde9575d57d
child 280096 9ea2dfc3325d47a4198f54a3d9ff7f8b081e592e
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnsm
bugs1174078
milestone41.0a1
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
Bug 1174078 - Calling "fetch" inside Service Worker's "onfetch" handler in b2g causes "onfetch" again that leads to an infinite loop. r=nsm
dom/fetch/FetchDriver.cpp
modules/libjar/nsIJARChannel.idl
modules/libjar/nsJARChannel.cpp
modules/libjar/nsJARChannel.h
netwerk/protocol/app/AppProtocolHandler.cpp
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -483,16 +483,21 @@ FetchDriver::HttpFetch(bool aCORSFlag, b
 
   // Set skip serviceworker flag.
   // While the spec also gates on the client being a ServiceWorker, we can't
   // infer that here. Instead we rely on callers to set the flag correctly.
   if (mRequest->SkipServiceWorker()) {
     if (httpChan) {
       nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(httpChan);
       internalChan->ForceNoIntercept();
+    } else {
+      nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(chan);
+      // If it is not an http channel, it has to be a jar one.
+      MOZ_ASSERT(jarChannel);
+      jarChannel->ForceNoIntercept();
     }
   }
 
   nsCOMPtr<nsIStreamListener> listener = this;
 
   // Unless the cors mode is explicitly no-cors, we set up a cors proxy even in
   // the same-origin case, since the proxy does not enforce cors header checks
   // in the same-origin case.
--- a/modules/libjar/nsIJARChannel.idl
+++ b/modules/libjar/nsIJARChannel.idl
@@ -3,17 +3,17 @@
  * 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 "nsIChannel.idl"
 
 interface nsIFile;
 interface nsIZipEntry;
 
-[scriptable, builtinclass, uuid(6b438dc3-9ba0-4f5f-b83f-82e1d7b98604)]
+[scriptable, builtinclass, uuid(fbdfaa6b-72dc-465e-af56-572fd13f153c)]
 interface nsIJARChannel : nsIChannel
 {
     /**
      * Returns TRUE if the JAR file is not safe (if the content type reported
      * by the server for a remote JAR is not of an expected type).  Scripting,
      * redirects, and plugins should be disabled when loading from this
      * channel.
      */
@@ -43,9 +43,15 @@ interface nsIJARChannel : nsIChannel
      * Note that the file descriptor returned by NSPRFileDesc() is duplicated
      * from the original, which shares its file offset with the original.  If
      * the file offset is modified (ex: by lseek/read/write) on one of the
      * shared descriptors, the offset is also changed for the other.
      * It can be safely used only with operations that take absolute offsets,
      * such as mmap/pread/pwrite.
      */
     void ensureChildFd();
+
+    /**
+     * Force the channel to skip any chack for possible interception and
+     * proceed immediately to the network.
+     */
+    void forceNoIntercept();
 };
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -198,16 +198,17 @@ nsJARChannel::nsJARChannel()
     , mContentLength(-1)
     , mLoadFlags(LOAD_NORMAL)
     , mStatus(NS_OK)
     , mIsPending(false)
     , mIsUnsafe(true)
     , mOpeningRemote(false)
     , mEnsureChildFd(false)
     , mSynthesizedStreamLength(0)
+    , mForceNoIntercept(false)
 {
     if (!gJarProtocolLog)
         gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
 
     // hold an owning reference to the jar handler
     NS_ADDREF(gJarHandler);
 }
 
@@ -873,17 +874,17 @@ nsJARChannel::ShouldIntercept()
       return false;
     }
 
     nsCOMPtr<nsINetworkInterceptController> controller;
     NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
                                   NS_GET_IID(nsINetworkInterceptController),
                                   getter_AddRefs(controller));
     bool shouldIntercept = false;
-    if (controller) {
+    if (controller && !mForceNoIntercept) {
       bool isNavigation = mLoadFlags & LOAD_DOCUMENT_URI;
       nsresult rv = controller->ShouldPrepareForIntercept(mAppURI,
                                                           isNavigation,
                                                           &shouldIntercept);
       NS_ENSURE_SUCCESS(rv, false);
     }
 
     return shouldIntercept;
@@ -1088,16 +1089,23 @@ nsJARChannel::GetZipEntry(nsIZipEntry **
 
 NS_IMETHODIMP
 nsJARChannel::EnsureChildFd()
 {
     mEnsureChildFd = true;
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsJARChannel::ForceNoIntercept()
+{
+    mForceNoIntercept = true;
+    return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // mozilla::net::MemoryDownloader::IObserver
 //-----------------------------------------------------------------------------
 
 void
 nsJARChannel::OnDownloadComplete(MemoryDownloader* aDownloader,
                                  nsIRequest    *request,
                                  nsISupports   *context,
--- a/modules/libjar/nsJARChannel.h
+++ b/modules/libjar/nsJARChannel.h
@@ -129,15 +129,18 @@ private:
     // mRequest is only non-null during OnStartRequest, so we'll have a pointer
     // to the request if we get called back via RetargetDeliveryTo.
     nsCOMPtr<nsIRequest>            mRequest;
     nsCOMPtr<nsIFile>               mJarFile;
     nsCOMPtr<nsIURI>                mJarBaseURI;
     nsCString                       mJarEntry;
     nsCString                       mInnerJarEntry;
 
-    nsRefPtr<nsInputStreamPump> mSynthesizedResponsePump;
-    int64_t mSynthesizedStreamLength;
+    nsRefPtr<nsInputStreamPump>     mSynthesizedResponsePump;
+    int64_t                         mSynthesizedStreamLength;
+
+    // True if this channel should skip any interception checks.
+    bool                            mForceNoIntercept;
 
     friend class mozilla::net::InterceptedJARChannel;
 };
 
 #endif // nsJARChannel_h__
--- a/netwerk/protocol/app/AppProtocolHandler.cpp
+++ b/netwerk/protocol/app/AppProtocolHandler.cpp
@@ -291,16 +291,21 @@ NS_IMETHODIMP DummyChannel::SetContentDi
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP DummyChannel::ForceNoIntercept()
+{
+  return NS_OK;
+}
+
 /**
   * app:// protocol implementation.
   */
 
 AppProtocolHandler::AppProtocolHandler() {
 }
 
 AppProtocolHandler::~AppProtocolHandler() {