Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(625)

Unified Diff: Source/modules/fetch/FetchManager.cpp

Issue 1279163005: Initial Fetch integration for Subresource Integrity (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/modules/fetch/FetchManager.cpp
diff --git a/Source/modules/fetch/FetchManager.cpp b/Source/modules/fetch/FetchManager.cpp
index 634370cc1daf4525dcf6ac9b0528a77a25634745..ce435be62d882e75d4b19acca8e0b4e56e200dc4 100644
--- a/Source/modules/fetch/FetchManager.cpp
+++ b/Source/modules/fetch/FetchManager.cpp
@@ -15,6 +15,7 @@
#include "core/fetch/FetchUtils.h"
#include "core/fileapi/Blob.h"
#include "core/frame/Frame.h"
+#include "core/frame/SubresourceIntegrity.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
@@ -57,6 +58,85 @@ public:
void start();
void dispose();
+ class IntegrityVerifiedDataConsumerHandle : public WebDataConsumerHandle {
+ public:
+ IntegrityVerifiedDataConsumerHandle(PassOwnPtr<WebDataConsumerHandle> handle, String integrityMetadata, const KURL& url, FetchManager::Loader* loader)
+ : m_handle(handle)
+ , m_integrityMetadata(integrityMetadata)
+ , m_url(url)
+ , m_loader(loader)
+ , m_response(nullptr)
+ {
+ }
+
+ void setResponse(Response* response) { m_response = response; }
+
+ private:
+ class ReaderImpl final : public WebDataConsumerHandle::Reader {
+ public:
+ ReaderImpl(PassOwnPtr<WebDataConsumerHandle::Reader> reader, String integrityMetadata, const KURL& url, FetchManager::Loader* loader, Response* response)
+ : m_reader(reader)
+ , m_integrityMetadata(integrityMetadata)
+ , m_url(url)
+ , m_loader(loader)
+ , m_response(response)
+ , m_firstRun(true)
+ {
+ }
+ Result read(void* data, size_t size, Flags flags, size_t* readSize) override
+ {
+ if (m_firstRun) {
+ m_firstRun = false;
+ String content;
+ char buf[1000];
+ size_t amt;
+ while (m_reader->read(buf, 1000, flags, &amt) == Ok)
yhirano 2015/08/11 09:22:08 Do you want to read all data from the pipe with th
jww 2015/08/12 16:40:14 This is addressed by your suggestion of implementi
yhirano 2015/08/13 18:10:36 Yes.
+ content.append(buf, amt);
+ String errorMessage;
+ if (!SubresourceIntegrity::CheckSubresourceIntegrity(m_integrityMetadata, content, m_url, *m_loader->document(), errorMessage)) {
yhirano 2015/08/11 09:22:08 This function can be called on a different thread
jww 2015/08/12 16:40:14 This is no longer a problem if your suggestion of
+ m_loader->performNetworkError(errorMessage);
+ return UnexpectedError;
+ }
+ m_loader->m_resolver->resolve(m_response);
+ m_loader->m_resolver.clear();
+ m_response = nullptr;
+ }
+
+ return m_reader->read(data, size, flags, readSize);
+ }
+
+ Result beginRead(const void** buffer, Flags flags, size_t* available) override
+ {
+ return m_reader->beginRead(buffer, flags, available);
+ }
+
+ Result endRead(size_t readSize) override
+ {
+ return m_reader->endRead(readSize);
+ }
+
+ private:
+ OwnPtr<WebDataConsumerHandle::Reader> m_reader;
+ String m_integrityMetadata;
+ KURL m_url;
+ FetchManager::Loader* m_loader;
+ Response* m_response;
+ bool m_firstRun;
+ };
+
+ Reader* obtainReaderInternal(Client* client) override
yhirano 2015/08/11 09:22:08 A difficult point is that obtainReaderInternal can
jww 2015/08/12 16:40:14 Acknowledged.
+ {
+ return new ReaderImpl(m_handle->obtainReader(client), m_integrityMetadata, m_url, m_loader, m_response);
+ }
+ const char* debugName() const override { return m_handle->debugName(); }
+
+ OwnPtr<WebDataConsumerHandle> m_handle;
+ String m_integrityMetadata;
+ KURL m_url;
+ FetchManager::Loader* m_loader;
+ Response* m_response;
+ };
+
private:
Loader(ExecutionContext*, FetchManager*, ScriptPromiseResolver*, FetchRequestData*);
@@ -122,7 +202,15 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
break;
}
}
- FetchResponseData* responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle)));
+
+ FetchResponseData* responseData;
+ IntegrityVerifiedDataConsumerHandle* integrityVerifier = nullptr;
+ if (m_request->integrity().isEmpty()) {
+ responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle)));
+ } else {
+ integrityVerifier = new IntegrityVerifiedDataConsumerHandle(handle, m_request->integrity(), m_request->url(), this);
+ responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(adoptPtr(integrityVerifier))));
+ }
responseData->setStatus(response.httpStatusCode());
responseData->setStatusMessage(response.httpStatusText());
for (auto& it : response.httpHeaderFields())
@@ -142,10 +230,16 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
taintedResponse = responseData->createOpaqueFilteredResponse();
break;
}
+
Response* r = Response::create(m_resolver->executionContext(), taintedResponse);
r->headers()->setGuard(Headers::ImmutableGuard);
- m_resolver->resolve(r);
- m_resolver.clear();
+
+ if (integrityVerifier) {
+ integrityVerifier->setResponse(r);
+ } else {
+ m_resolver->resolve(r);
+ m_resolver.clear();
+ }
}
void FetchManager::Loader::didFinishLoading(unsigned long, double)

Powered by Google App Engine
This is Rietveld 408576698