1e14391e94c850b8bd03680c23b38978db68687a8John Reck/*
2e14391e94c850b8bd03680c23b38978db68687a8John Reck * Copyright (C) 2010 Google Inc.  All rights reserved.
3e14391e94c850b8bd03680c23b38978db68687a8John Reck *
4e14391e94c850b8bd03680c23b38978db68687a8John Reck * Redistribution and use in source and binary forms, with or without
5e14391e94c850b8bd03680c23b38978db68687a8John Reck * modification, are permitted provided that the following conditions are
6e14391e94c850b8bd03680c23b38978db68687a8John Reck * met:
7e14391e94c850b8bd03680c23b38978db68687a8John Reck *
8e14391e94c850b8bd03680c23b38978db68687a8John Reck *     * Redistributions of source code must retain the above copyright
9e14391e94c850b8bd03680c23b38978db68687a8John Reck * notice, this list of conditions and the following disclaimer.
10e14391e94c850b8bd03680c23b38978db68687a8John Reck *     * Redistributions in binary form must reproduce the above
11e14391e94c850b8bd03680c23b38978db68687a8John Reck * copyright notice, this list of conditions and the following disclaimer
12e14391e94c850b8bd03680c23b38978db68687a8John Reck * in the documentation and/or other materials provided with the
13e14391e94c850b8bd03680c23b38978db68687a8John Reck * distribution.
14e14391e94c850b8bd03680c23b38978db68687a8John Reck *     * Neither the name of Google Inc. nor the names of its
15e14391e94c850b8bd03680c23b38978db68687a8John Reck * contributors may be used to endorse or promote products derived from
16e14391e94c850b8bd03680c23b38978db68687a8John Reck * this software without specific prior written permission.
17e14391e94c850b8bd03680c23b38978db68687a8John Reck *
18e14391e94c850b8bd03680c23b38978db68687a8John Reck * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19e14391e94c850b8bd03680c23b38978db68687a8John Reck * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20e14391e94c850b8bd03680c23b38978db68687a8John Reck * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21e14391e94c850b8bd03680c23b38978db68687a8John Reck * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22e14391e94c850b8bd03680c23b38978db68687a8John Reck * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23e14391e94c850b8bd03680c23b38978db68687a8John Reck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24e14391e94c850b8bd03680c23b38978db68687a8John Reck * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25e14391e94c850b8bd03680c23b38978db68687a8John Reck * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26e14391e94c850b8bd03680c23b38978db68687a8John Reck * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27e14391e94c850b8bd03680c23b38978db68687a8John Reck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28e14391e94c850b8bd03680c23b38978db68687a8John Reck * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29e14391e94c850b8bd03680c23b38978db68687a8John Reck */
30e14391e94c850b8bd03680c23b38978db68687a8John Reck
31e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "config.h"
32e14391e94c850b8bd03680c23b38978db68687a8John Reck
33e14391e94c850b8bd03680c23b38978db68687a8John Reck#if ENABLE(BLOB)
34e14391e94c850b8bd03680c23b38978db68687a8John Reck
35e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "FileReaderLoader.h"
36e14391e94c850b8bd03680c23b38978db68687a8John Reck
37e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ArrayBuffer.h"
38e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "Base64.h"
39e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "Blob.h"
40e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "BlobURL.h"
41e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "FileReaderLoaderClient.h"
42e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ResourceRequest.h"
43e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ResourceResponse.h"
44e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ScriptExecutionContext.h"
45e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "TextResourceDecoder.h"
46e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ThreadableBlobRegistry.h"
47e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "ThreadableLoader.h"
48e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <wtf/PassRefPtr.h>
49e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <wtf/RefPtr.h>
50e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <wtf/Vector.h>
51e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <wtf/text/StringBuilder.h>
52e14391e94c850b8bd03680c23b38978db68687a8John Reck
53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochusing namespace std;
54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
55e14391e94c850b8bd03680c23b38978db68687a8John Recknamespace WebCore {
56e14391e94c850b8bd03680c23b38978db68687a8John Reck
57e14391e94c850b8bd03680c23b38978db68687a8John ReckFileReaderLoader::FileReaderLoader(ReadType readType, FileReaderLoaderClient* client)
58e14391e94c850b8bd03680c23b38978db68687a8John Reck    : m_readType(readType)
59e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_client(client)
60e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_isRawDataConverted(false)
61e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_stringResult("")
62e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_bytesLoaded(0)
63e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_totalBytes(0)
64e14391e94c850b8bd03680c23b38978db68687a8John Reck    , m_errorCode(0)
65e14391e94c850b8bd03680c23b38978db68687a8John Reck{
66e14391e94c850b8bd03680c23b38978db68687a8John Reck}
67e14391e94c850b8bd03680c23b38978db68687a8John Reck
68e14391e94c850b8bd03680c23b38978db68687a8John ReckFileReaderLoader::~FileReaderLoader()
69e14391e94c850b8bd03680c23b38978db68687a8John Reck{
70e14391e94c850b8bd03680c23b38978db68687a8John Reck    terminate();
71e14391e94c850b8bd03680c23b38978db68687a8John Reck    ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading);
72e14391e94c850b8bd03680c23b38978db68687a8John Reck}
73e14391e94c850b8bd03680c23b38978db68687a8John Reck
74e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, Blob* blob)
75e14391e94c850b8bd03680c23b38978db68687a8John Reck{
76e14391e94c850b8bd03680c23b38978db68687a8John Reck    // The blob is read by routing through the request handling layer given a temporary public url.
77e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
782bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_urlForReading.isEmpty()) {
792bde8e466a4451c7319e3a072d118917957d6554Steve Block        failed(FileError::SECURITY_ERR);
802bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
812bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
82e14391e94c850b8bd03680c23b38978db68687a8John Reck    ThreadableBlobRegistry::registerBlobURL(m_urlForReading, blob->url());
83e14391e94c850b8bd03680c23b38978db68687a8John Reck
84e14391e94c850b8bd03680c23b38978db68687a8John Reck    // Construct and load the request.
85e14391e94c850b8bd03680c23b38978db68687a8John Reck    ResourceRequest request(m_urlForReading);
86e14391e94c850b8bd03680c23b38978db68687a8John Reck    request.setHTTPMethod("GET");
87e14391e94c850b8bd03680c23b38978db68687a8John Reck
88e14391e94c850b8bd03680c23b38978db68687a8John Reck    ThreadableLoaderOptions options;
89e14391e94c850b8bd03680c23b38978db68687a8John Reck    options.sendLoadCallbacks = true;
90e14391e94c850b8bd03680c23b38978db68687a8John Reck    options.sniffContent = false;
91e14391e94c850b8bd03680c23b38978db68687a8John Reck    options.forcePreflight = false;
92e14391e94c850b8bd03680c23b38978db68687a8John Reck    options.allowCredentials = true;
93e14391e94c850b8bd03680c23b38978db68687a8John Reck    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
94e14391e94c850b8bd03680c23b38978db68687a8John Reck
95e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_client)
96e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options);
97e14391e94c850b8bd03680c23b38978db68687a8John Reck    else
98e14391e94c850b8bd03680c23b38978db68687a8John Reck        ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options);
99e14391e94c850b8bd03680c23b38978db68687a8John Reck}
100e14391e94c850b8bd03680c23b38978db68687a8John Reck
101e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::cancel()
102e14391e94c850b8bd03680c23b38978db68687a8John Reck{
103e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_errorCode = FileError::ABORT_ERR;
104e14391e94c850b8bd03680c23b38978db68687a8John Reck    terminate();
105e14391e94c850b8bd03680c23b38978db68687a8John Reck}
106e14391e94c850b8bd03680c23b38978db68687a8John Reck
107e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::terminate()
108e14391e94c850b8bd03680c23b38978db68687a8John Reck{
109e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_loader) {
110e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_loader->cancel();
111e14391e94c850b8bd03680c23b38978db68687a8John Reck        cleanup();
112e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
113e14391e94c850b8bd03680c23b38978db68687a8John Reck}
114e14391e94c850b8bd03680c23b38978db68687a8John Reck
115e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::cleanup()
116e14391e94c850b8bd03680c23b38978db68687a8John Reck{
117e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_loader = 0;
118e14391e94c850b8bd03680c23b38978db68687a8John Reck
119e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If we get any error, we do not need to keep a buffer around.
120e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_errorCode) {
121e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_rawData = 0;
122e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_stringResult = "";
123e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
124e14391e94c850b8bd03680c23b38978db68687a8John Reck}
125e14391e94c850b8bd03680c23b38978db68687a8John Reck
126e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::didReceiveResponse(const ResourceResponse& response)
127e14391e94c850b8bd03680c23b38978db68687a8John Reck{
128e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (response.httpStatusCode() != 200) {
129e14391e94c850b8bd03680c23b38978db68687a8John Reck        failed(httpStatusCodeToErrorCode(response.httpStatusCode()));
130e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
131e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
132e14391e94c850b8bd03680c23b38978db68687a8John Reck
133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    unsigned long long length = response.expectedContentLength();
134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Check that we can cast to unsigned since we have to do
136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // so to call ArrayBuffer's create function.
137e14391e94c850b8bd03680c23b38978db68687a8John Reck    // FIXME: Support reading more than the current size limit of ArrayBuffer.
138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (length > numeric_limits<unsigned>::max()) {
139e14391e94c850b8bd03680c23b38978db68687a8John Reck        failed(FileError::NOT_READABLE_ERR);
140e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
141e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
142e14391e94c850b8bd03680c23b38978db68687a8John Reck
143e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(!m_rawData);
144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_rawData = ArrayBuffer::create(static_cast<unsigned>(length), 1);
145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_rawData) {
147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        failed(FileError::NOT_READABLE_ERR);
148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
149f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_totalBytes = static_cast<unsigned>(length);
152e14391e94c850b8bd03680c23b38978db68687a8John Reck
153e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_client)
154e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_client->didStartLoading();
155e14391e94c850b8bd03680c23b38978db68687a8John Reck}
156e14391e94c850b8bd03680c23b38978db68687a8John Reck
1572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid FileReaderLoader::didReceiveData(const char* data, int dataLength)
158e14391e94c850b8bd03680c23b38978db68687a8John Reck{
159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(data);
1602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(dataLength > 0);
161e14391e94c850b8bd03680c23b38978db68687a8John Reck
162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Bail out if we already encountered an error.
163e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_errorCode)
164e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
165e14391e94c850b8bd03680c23b38978db68687a8John Reck
1662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int length = dataLength;
167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    unsigned remainingBufferSpace = m_totalBytes - m_bytesLoaded;
168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (length > static_cast<long long>(remainingBufferSpace))
169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        length = static_cast<int>(remainingBufferSpace);
170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
171f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (length <= 0)
172f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    memcpy(static_cast<char*>(m_rawData->data()) + m_bytesLoaded, data, length);
175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bytesLoaded += length;
176e14391e94c850b8bd03680c23b38978db68687a8John Reck
177e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_isRawDataConverted = false;
178e14391e94c850b8bd03680c23b38978db68687a8John Reck
179e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_client)
180e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_client->didReceiveData();
181e14391e94c850b8bd03680c23b38978db68687a8John Reck}
182e14391e94c850b8bd03680c23b38978db68687a8John Reck
18381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid FileReaderLoader::didFinishLoading(unsigned long, double)
184e14391e94c850b8bd03680c23b38978db68687a8John Reck{
185e14391e94c850b8bd03680c23b38978db68687a8John Reck    cleanup();
186e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_client)
187e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_client->didFinishLoading();
188e14391e94c850b8bd03680c23b38978db68687a8John Reck}
189e14391e94c850b8bd03680c23b38978db68687a8John Reck
190e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::didFail(const ResourceError&)
191e14391e94c850b8bd03680c23b38978db68687a8John Reck{
192e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If we're aborting, do not proceed with normal error handling since it is covered in aborting code.
193e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_errorCode == FileError::ABORT_ERR)
194e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
195e14391e94c850b8bd03680c23b38978db68687a8John Reck
196e14391e94c850b8bd03680c23b38978db68687a8John Reck    failed(FileError::NOT_READABLE_ERR);
197e14391e94c850b8bd03680c23b38978db68687a8John Reck}
198e14391e94c850b8bd03680c23b38978db68687a8John Reck
199e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::failed(int errorCode)
200e14391e94c850b8bd03680c23b38978db68687a8John Reck{
201e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_errorCode = errorCode;
202e14391e94c850b8bd03680c23b38978db68687a8John Reck    cleanup();
203e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_client)
204e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_client->didFail(m_errorCode);
205e14391e94c850b8bd03680c23b38978db68687a8John Reck}
206e14391e94c850b8bd03680c23b38978db68687a8John Reck
207e14391e94c850b8bd03680c23b38978db68687a8John ReckFileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusCode)
208e14391e94c850b8bd03680c23b38978db68687a8John Reck{
209e14391e94c850b8bd03680c23b38978db68687a8John Reck    switch (httpStatusCode) {
210e14391e94c850b8bd03680c23b38978db68687a8John Reck    case 403:
211e14391e94c850b8bd03680c23b38978db68687a8John Reck        return FileError::SECURITY_ERR;
212e14391e94c850b8bd03680c23b38978db68687a8John Reck    case 404:
213e14391e94c850b8bd03680c23b38978db68687a8John Reck        return FileError::NOT_FOUND_ERR;
214e14391e94c850b8bd03680c23b38978db68687a8John Reck    default:
215e14391e94c850b8bd03680c23b38978db68687a8John Reck        return FileError::NOT_READABLE_ERR;
216e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
217e14391e94c850b8bd03680c23b38978db68687a8John Reck}
218e14391e94c850b8bd03680c23b38978db68687a8John Reck
219e14391e94c850b8bd03680c23b38978db68687a8John ReckPassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const
220e14391e94c850b8bd03680c23b38978db68687a8John Reck{
221e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(m_readType == ReadAsArrayBuffer);
222e14391e94c850b8bd03680c23b38978db68687a8John Reck
223e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If the loading is not started or an error occurs, return an empty result.
224e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_rawData || m_errorCode)
225e14391e94c850b8bd03680c23b38978db68687a8John Reck        return 0;
226e14391e94c850b8bd03680c23b38978db68687a8John Reck
227e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If completed, we can simply return our buffer.
228e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (isCompleted())
229e14391e94c850b8bd03680c23b38978db68687a8John Reck        return m_rawData;
230e14391e94c850b8bd03680c23b38978db68687a8John Reck
231e14391e94c850b8bd03680c23b38978db68687a8John Reck    // Otherwise, return a copy.
232e14391e94c850b8bd03680c23b38978db68687a8John Reck    return ArrayBuffer::create(m_rawData.get());
233e14391e94c850b8bd03680c23b38978db68687a8John Reck}
234e14391e94c850b8bd03680c23b38978db68687a8John Reck
235e14391e94c850b8bd03680c23b38978db68687a8John ReckString FileReaderLoader::stringResult()
236e14391e94c850b8bd03680c23b38978db68687a8John Reck{
237e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(m_readType != ReadAsArrayBuffer);
238e14391e94c850b8bd03680c23b38978db68687a8John Reck
239e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If the loading is not started or an error occurs, return an empty result.
240e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_rawData || m_errorCode)
241e14391e94c850b8bd03680c23b38978db68687a8John Reck        return m_stringResult;
242e14391e94c850b8bd03680c23b38978db68687a8John Reck
243e14391e94c850b8bd03680c23b38978db68687a8John Reck    // If already converted from the raw data, return the result now.
244e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (m_isRawDataConverted)
245e14391e94c850b8bd03680c23b38978db68687a8John Reck        return m_stringResult;
246e14391e94c850b8bd03680c23b38978db68687a8John Reck
247e14391e94c850b8bd03680c23b38978db68687a8John Reck    switch (m_readType) {
248e14391e94c850b8bd03680c23b38978db68687a8John Reck    case ReadAsArrayBuffer:
249e14391e94c850b8bd03680c23b38978db68687a8John Reck        // No conversion is needed.
250e14391e94c850b8bd03680c23b38978db68687a8John Reck        break;
251e14391e94c850b8bd03680c23b38978db68687a8John Reck    case ReadAsBinaryString:
252e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
253e14391e94c850b8bd03680c23b38978db68687a8John Reck        break;
254e14391e94c850b8bd03680c23b38978db68687a8John Reck    case ReadAsText:
255e14391e94c850b8bd03680c23b38978db68687a8John Reck        convertToText();
256e14391e94c850b8bd03680c23b38978db68687a8John Reck        break;
257e14391e94c850b8bd03680c23b38978db68687a8John Reck    case ReadAsDataURL:
258e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Partial data is not supported when reading as data URL.
259e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (isCompleted())
260e14391e94c850b8bd03680c23b38978db68687a8John Reck            convertToDataURL();
261e14391e94c850b8bd03680c23b38978db68687a8John Reck        break;
262e14391e94c850b8bd03680c23b38978db68687a8John Reck    default:
263e14391e94c850b8bd03680c23b38978db68687a8John Reck        ASSERT_NOT_REACHED();
264e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
265e14391e94c850b8bd03680c23b38978db68687a8John Reck
266e14391e94c850b8bd03680c23b38978db68687a8John Reck    return m_stringResult;
267e14391e94c850b8bd03680c23b38978db68687a8John Reck}
268e14391e94c850b8bd03680c23b38978db68687a8John Reck
269e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::convertToText()
270e14391e94c850b8bd03680c23b38978db68687a8John Reck{
271e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_bytesLoaded)
272e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
273e14391e94c850b8bd03680c23b38978db68687a8John Reck
274e14391e94c850b8bd03680c23b38978db68687a8John Reck    // Decode the data.
275e14391e94c850b8bd03680c23b38978db68687a8John Reck    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
276e14391e94c850b8bd03680c23b38978db68687a8John Reck    // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the
277e14391e94c850b8bd03680c23b38978db68687a8John Reck    // provided encoding.
278e14391e94c850b8bd03680c23b38978db68687a8John Reck    // FIXME: consider supporting incremental decoding to improve the perf.
279e14391e94c850b8bd03680c23b38978db68687a8John Reck    StringBuilder builder;
280e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_decoder)
281e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding());
282e14391e94c850b8bd03680c23b38978db68687a8John Reck    builder.append(m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded));
283e14391e94c850b8bd03680c23b38978db68687a8John Reck
284e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (isCompleted())
285e14391e94c850b8bd03680c23b38978db68687a8John Reck        builder.append(m_decoder->flush());
286e14391e94c850b8bd03680c23b38978db68687a8John Reck
287e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_stringResult = builder.toString();
288e14391e94c850b8bd03680c23b38978db68687a8John Reck}
289e14391e94c850b8bd03680c23b38978db68687a8John Reck
290e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::convertToDataURL()
291e14391e94c850b8bd03680c23b38978db68687a8John Reck{
292e14391e94c850b8bd03680c23b38978db68687a8John Reck    StringBuilder builder;
293e14391e94c850b8bd03680c23b38978db68687a8John Reck    builder.append("data:");
294e14391e94c850b8bd03680c23b38978db68687a8John Reck
295e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_bytesLoaded) {
296e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_stringResult = builder.toString();
297e14391e94c850b8bd03680c23b38978db68687a8John Reck        return;
298e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
299e14391e94c850b8bd03680c23b38978db68687a8John Reck
300e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!m_dataType.isEmpty()) {
301e14391e94c850b8bd03680c23b38978db68687a8John Reck        builder.append(m_dataType);
302e14391e94c850b8bd03680c23b38978db68687a8John Reck        builder.append(";base64,");
303e14391e94c850b8bd03680c23b38978db68687a8John Reck    } else
304e14391e94c850b8bd03680c23b38978db68687a8John Reck        builder.append("base64,");
305e14391e94c850b8bd03680c23b38978db68687a8John Reck
306e14391e94c850b8bd03680c23b38978db68687a8John Reck    Vector<char> out;
307e14391e94c850b8bd03680c23b38978db68687a8John Reck    base64Encode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded, out);
308e14391e94c850b8bd03680c23b38978db68687a8John Reck    out.append('\0');
309e14391e94c850b8bd03680c23b38978db68687a8John Reck    builder.append(out.data());
310e14391e94c850b8bd03680c23b38978db68687a8John Reck
311e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_stringResult = builder.toString();
312e14391e94c850b8bd03680c23b38978db68687a8John Reck}
313e14391e94c850b8bd03680c23b38978db68687a8John Reck
314e14391e94c850b8bd03680c23b38978db68687a8John Reckbool FileReaderLoader::isCompleted() const
315e14391e94c850b8bd03680c23b38978db68687a8John Reck{
316e14391e94c850b8bd03680c23b38978db68687a8John Reck    return m_bytesLoaded == m_totalBytes;
317e14391e94c850b8bd03680c23b38978db68687a8John Reck}
318e14391e94c850b8bd03680c23b38978db68687a8John Reck
319e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid FileReaderLoader::setEncoding(const String& encoding)
320e14391e94c850b8bd03680c23b38978db68687a8John Reck{
321e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!encoding.isEmpty())
322e14391e94c850b8bd03680c23b38978db68687a8John Reck        m_encoding = TextEncoding(encoding);
323e14391e94c850b8bd03680c23b38978db68687a8John Reck}
324e14391e94c850b8bd03680c23b38978db68687a8John Reck
325e14391e94c850b8bd03680c23b38978db68687a8John Reck} // namespace WebCore
326e14391e94c850b8bd03680c23b38978db68687a8John Reck
327e14391e94c850b8bd03680c23b38978db68687a8John Reck#endif // ENABLE(BLOB)
328