File: FetchManager.cpp

package info (click to toggle)
chromium-browser 37.0.2062.120-1~deb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,707,260 kB
  • sloc: cpp: 8,976,677; ansic: 3,473,199; python: 586,578; asm: 449,013; xml: 184,195; java: 142,924; sh: 118,496; perl: 81,467; makefile: 27,557; yacc: 10,506; objc: 8,886; tcl: 3,186; cs: 2,252; lex: 2,213; sql: 1,198; pascal: 1,170; lisp: 790; awk: 407; ruby: 155; php: 83; sed: 52; exp: 11
file content (172 lines) | stat: -rw-r--r-- 5,003 bytes parent folder | download
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