Bug 1156847 - Part 6: When calling FetchEvent.respondWith(), fall back to the security info of the service worker if the Response object that we are responding with doesn't have its own security info; r=nsm
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 23 Apr 2015 19:18:41 -0400
changeset 241721 e3a415d282b0e91b0ce5ee57b3f37a48ae11a424
parent 241720 970c30fdca491d9132f571ed0f40e2f9c708e1a9
child 241722 a59eaeaeb8b4c8c1a3bec1b2a72b87ab6f3b4c8c
push id28669
push userryanvm@gmail.com
push dateThu, 30 Apr 2015 17:57:05 +0000
treeherdermozilla-central@7723b15ea695 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnsm
bugs1156847
milestone40.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 1156847 - Part 6: When calling FetchEvent.respondWith(), fall back to the security info of the service worker if the Response object that we are responding with doesn't have its own security info; r=nsm This case will only happen if we're responding with a synthesized Response object. Response objects obtained through fetch() already have their correct security info.
dom/workers/ServiceWorkerEvents.cpp
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -13,16 +13,17 @@
 #include "nsContentUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStreamUtils.h"
 #include "nsNetCID.h"
 #include "nsSerializationHelper.h"
 #include "nsQueryObject.h"
 
+#include "mozilla/Preferences.h"
 #include "mozilla/dom/FetchEventBinding.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/workers/bindings/ServiceWorker.h"
 
 #include "WorkerPrivate.h"
@@ -92,31 +93,40 @@ public:
     return NS_OK;
   }
 };
 
 class FinishResponse final : public nsRunnable
 {
   nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
   nsRefPtr<InternalResponse> mInternalResponse;
+  nsCString mWorkerSecurityInfo;
 public:
   FinishResponse(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
-                 InternalResponse* aInternalResponse)
+                 InternalResponse* aInternalResponse,
+                 const nsCString& aWorkerSecurityInfo)
     : mChannel(aChannel)
     , mInternalResponse(aInternalResponse)
+    , mWorkerSecurityInfo(aWorkerSecurityInfo)
   {
   }
 
   NS_IMETHOD
   Run()
   {
     AssertIsOnMainThread();
 
     nsCOMPtr<nsISupports> infoObj;
-    nsresult rv = NS_DeserializeObject(mInternalResponse->GetSecurityInfo(), getter_AddRefs(infoObj));
+    nsAutoCString securityInfo(mInternalResponse->GetSecurityInfo());
+    if (securityInfo.IsEmpty()) {
+      // We are dealing with a synthesized response here, so fall back to the
+      // security info for the worker script.
+      securityInfo = mWorkerSecurityInfo;
+    }
+    nsresult rv = NS_DeserializeObject(securityInfo, getter_AddRefs(infoObj));
     if (NS_SUCCEEDED(rv)) {
       rv = mChannel->SetSecurityInfo(infoObj);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     mChannel->SynthesizeStatus(mInternalResponse->GetStatus(), mInternalResponse->GetStatusText());
@@ -154,31 +164,36 @@ public:
 
   void CancelRequest();
 };
 
 struct RespondWithClosure
 {
   nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
   nsRefPtr<InternalResponse> mInternalResponse;
+  nsCString mWorkerSecurityInfo;
 
   RespondWithClosure(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
-                     InternalResponse* aInternalResponse)
+                     InternalResponse* aInternalResponse,
+                     const nsCString& aWorkerSecurityInfo)
     : mInterceptedChannel(aChannel)
     , mInternalResponse(aInternalResponse)
+    , mWorkerSecurityInfo(aWorkerSecurityInfo)
   {
   }
 };
 
 void RespondWithCopyComplete(void* aClosure, nsresult aStatus)
 {
   nsAutoPtr<RespondWithClosure> data(static_cast<RespondWithClosure*>(aClosure));
   nsCOMPtr<nsIRunnable> event;
   if (NS_SUCCEEDED(aStatus)) {
-    event = new FinishResponse(data->mInterceptedChannel, data->mInternalResponse);
+    event = new FinishResponse(data->mInterceptedChannel,
+                               data->mInternalResponse,
+                               data->mWorkerSecurityInfo);
   } else {
     event = new CancelChannelRunnable(data->mInterceptedChannel);
   }
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(event)));
 }
 
 class MOZ_STACK_CLASS AutoCancel
 {
@@ -229,17 +244,22 @@ RespondWithHandler::ResolvedCallback(JSC
     return;
   }
 
   nsRefPtr<InternalResponse> ir = response->GetInternalResponse();
   if (NS_WARN_IF(!ir)) {
     return;
   }
 
-  nsAutoPtr<RespondWithClosure> closure(new RespondWithClosure(mInterceptedChannel, ir));
+  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
+  MOZ_ASSERT(worker);
+  worker->AssertIsOnWorkerThread();
+
+  nsAutoPtr<RespondWithClosure> closure(
+      new RespondWithClosure(mInterceptedChannel, ir, worker->GetSecurityInfo()));
   nsCOMPtr<nsIInputStream> body;
   response->GetBody(getter_AddRefs(body));
   // Errors and redirects may not have a body.
   if (body) {
     response->SetBodyUsed();
 
     nsCOMPtr<nsIOutputStream> responseBody;
     rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));