1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "FetchManager.h"
#include "bindings/v8/ScriptPromiseResolverWithContext.h"
#include "bindings/v8/ScriptState.h"
#include "bindings/v8/V8ThrowException.h"
#include "core/dom/ExceptionCode.h"
#include "core/fileapi/Blob.h"
#include "core/loader/ThreadableLoader.h"
#include "core/loader/ThreadableLoaderClient.h"
#include "modules/serviceworkers/Response.h"
#include "platform/network/ResourceRequest.h"
#include "wtf/HashSet.h"
namespace WebCore {
class FetchManager::Loader : public ThreadableLoaderClient {
public:
Loader(ExecutionContext*, FetchManager*, PassRefPtr<ScriptPromiseResolverWithContext>, PassOwnPtr<ResourceRequest>);
~Loader();
virtual void didReceiveResponse(unsigned long, const ResourceResponse&);
virtual void didFinishLoading(unsigned long, double);
virtual void didFail(const ResourceError&);
virtual void didFailAccessControlCheck(const ResourceError&);
virtual void didFailRedirectCheck();
virtual void didDownloadData(int);
void start();
void cleanup();
private:
void failed();
void notifyFinished();
ExecutionContext* m_executionContext;
FetchManager* m_fetchManager;
RefPtr<ScriptPromiseResolverWithContext> m_resolver;
OwnPtr<ResourceRequest> m_request;
RefPtr<ThreadableLoader> m_loader;
ResourceResponse m_response;
long long m_downloadedBlobLength;
bool m_failed;
};
FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* fetchManager, PassRefPtr<ScriptPromiseResolverWithContext> resolver, PassOwnPtr<ResourceRequest> request)
: m_executionContext(executionContext)
, m_fetchManager(fetchManager)
, m_resolver(resolver)
, m_request(request)
, m_downloadedBlobLength(0)
, m_failed(false)
{
}
FetchManager::Loader::~Loader()
{
if (m_loader)
m_loader->cancel();
}
void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceResponse& response)
{
m_response = response;
}
void FetchManager::Loader::didFinishLoading(unsigned long, double)
{
OwnPtr<BlobData> blobData = BlobData::create();
String filePath = m_response.downloadedFilePath();
if (!filePath.isEmpty() && m_downloadedBlobLength) {
blobData->appendFile(filePath);
// FIXME: Set the ContentType correctly.
}
Dictionary options;
// FIXME: fill options.
RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), m_downloadedBlobLength));
// FIXME: Handle response status correctly.
m_resolver->resolve(Response::create(blob.get(), options));
notifyFinished();
}
void FetchManager::Loader::didFail(const ResourceError& error)
{
failed();
}
void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error)
{
failed();
}
void FetchManager::Loader::didFailRedirectCheck()
{
failed();
}
void FetchManager::Loader::didDownloadData(int dataLength)
{
m_downloadedBlobLength += dataLength;
}
void FetchManager::Loader::start()
{
m_request->setDownloadToFile(true);
ThreadableLoaderOptions options;
// FIXME: Fill options.
ResourceLoaderOptions resourceLoaderOptions;
resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
// FIXME: Fill resourceLoaderOptions.
m_loader = ThreadableLoader::create(*m_executionContext, this, *m_request, options, resourceLoaderOptions);
}
void FetchManager::Loader::cleanup()
{
// Prevent notification
m_fetchManager = 0;
if (m_loader) {
m_loader->cancel();
m_loader.clear();
}
}
void FetchManager::Loader::failed()
{
if (m_failed)
return;
m_failed = true;
ScriptState* state = m_resolver->scriptState();
ScriptState::Scope scope(state);
m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", state->isolate()));
notifyFinished();
}
void FetchManager::Loader::notifyFinished()
{
if (m_fetchManager)
m_fetchManager->onLoaderFinished(this);
}
FetchManager::FetchManager(ExecutionContext* executionContext)
: m_executionContext(executionContext)
{
}
FetchManager::~FetchManager()
{
for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_loaders.end(); ++it) {
(*it)->cleanup();
}
}
ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassOwnPtr<ResourceRequest> request)
{
RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState);
ScriptPromise promise = resolver->promise();
OwnPtr<Loader> loader(adoptPtr(new Loader(m_executionContext, this, resolver.release(), request)));
(*m_loaders.add(loader.release()).storedValue)->start();
return promise;
}
void FetchManager::onLoaderFinished(Loader* loader)
{
m_loaders.remove(loader);
}
} // namespace WebCore
|