Bug 1203680 P5 Make ServiceWorkerManager ensure channel upload stream is cloneable. r=nsm

This commit is contained in:
Ben Kelly 2015-09-15 10:15:45 -07:00
Родитель 233c4ec7a9
Коммит 061dd411a3
1 изменённых файлов: 92 добавлений и 9 удалений

Просмотреть файл

@ -3867,6 +3867,82 @@ private:
}
};
namespace {
class ContinueDispatchFetchEventRunnable : public nsRunnable
{
WorkerPrivate* mWorkerPrivate;
nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
nsAutoPtr<ServiceWorkerClientInfo> mClientInfo;
bool mIsReload;
public:
ContinueDispatchFetchEventRunnable(WorkerPrivate* aWorkerPrivate,
nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
bool aIsReload)
: mWorkerPrivate(aWorkerPrivate)
, mChannel(aChannel)
, mServiceWorker(aServiceWorker)
, mClientInfo(aClientInfo)
, mIsReload(aIsReload)
{
}
void
HandleError()
{
MOZ_ASSERT(NS_IsMainThread());
NS_WARNING("Unexpected error while dispatching fetch event!");
DebugOnly<nsresult> rv = mChannel->ResetInterception();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to resume intercepted network request");
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIChannel> channel;
nsresult rv = mChannel->GetChannel(getter_AddRefs(channel));
if (NS_WARN_IF(NS_FAILED(rv))) {
HandleError();
return NS_OK;
}
// The channel might have encountered an unexpected error while ensuring
// the upload stream is cloneable. Check here and reset the interception
// if that happens.
nsresult status;
rv = channel->GetStatus(&status);
if (NS_WARN_IF(NS_FAILED(rv) || NS_FAILED(status))) {
HandleError();
return NS_OK;
}
nsRefPtr<FetchEventRunnable> event =
new FetchEventRunnable(mWorkerPrivate, mChannel, mServiceWorker,
mClientInfo, mIsReload);
rv = event->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
HandleError();
return NS_OK;
}
AutoJSAPI jsapi;
jsapi.Init();
if (NS_WARN_IF(!event->Dispatch(jsapi.cx()))) {
HandleError();
return NS_OK;
}
return NS_OK;
}
};
} // anonymous namespace
NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor)
void
@ -3940,21 +4016,28 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
nsMainThreadPtrHandle<ServiceWorker> serviceWorkerHandle(
new nsMainThreadPtrHolder<ServiceWorker>(sw));
// clientInfo is null if we don't have a controlled document
nsRefPtr<FetchEventRunnable> event =
new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle,
clientInfo, aIsReload);
aRv = event->Init();
nsCOMPtr<nsIRunnable> continueRunnable =
new ContinueDispatchFetchEventRunnable(sw->GetWorkerPrivate(), handle,
serviceWorkerHandle, clientInfo,
aIsReload);
nsCOMPtr<nsIChannel> innerChannel;
aRv = aChannel->GetChannel(getter_AddRefs(innerChannel));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
AutoJSAPI api;
api.Init();
if (NS_WARN_IF(!event->Dispatch(api.cx()))) {
aRv.Throw(NS_ERROR_FAILURE);
nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(innerChannel);
// If there is no upload stream, then continue immediately
if (!uploadChannel) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(continueRunnable->Run()));
return;
}
// Otherwise, ensure the upload stream can be cloned directly. This may
// require some async copying, so provide a callback.
aRv = uploadChannel->EnsureUploadStreamIsCloneable(continueRunnable);
}
bool