15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/FileReader.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionState.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/CrossThreadTask.h"
36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/Document.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ExceptionCode.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/ExecutionContext.h"
3906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/ProgressEvent.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/File.h"
41197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/frame/LocalFrame.h"
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h"
43197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/workers/WorkerClients.h"
44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/workers/WorkerGlobalScope.h"
451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h"
46197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/Supplementable.h"
47e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/ArrayBuffer.h"
48e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/CurrentTime.h"
49a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "wtf/Deque.h"
50a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "wtf/HashSet.h"
51e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/text/CString.h"
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)namespace {
5693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
5751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#if !LOG_DISABLED
581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)const CString utf8BlobUUID(Blob* blob)
5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
601e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return blob->uuid().utf8();
6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)const CString utf8FilePath(Blob* blob)
6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
6551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return blob->hasBackingFile() ? toFile(blob)->path().utf8() : "";
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif
6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} // namespace
7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
71a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// Embedders like chromium limit the number of simultaneous requests to avoid
72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// excessive IPC congestion. We limit this to 100 per thread to throttle the
73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// requests (the value is arbitrarily chosen).
74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static const size_t kMaxOutstandingRequestsPerThread = 100;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const double progressNotificationIntervalMS = 50;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// FIXME: Oilpan: if ExecutionContext is moved to the heap, consider
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// making this object an ExecutionContext supplement (only.)
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass FileReader::ThrottlingController FINAL : public NoBaseWillBeGarbageCollectedFinalized<FileReader::ThrottlingController>, public WillBeHeapSupplement<LocalFrame>, public WillBeHeapSupplement<WorkerClients> {
80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController);
81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)public:
82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static ThrottlingController* from(ExecutionContext* context)
83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
84197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!context)
85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return 0;
86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
87197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (context->isDocument()) {
88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            Document* document = toDocument(context);
89197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (!document->frame())
90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return 0;
91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            ThrottlingController* controller = static_cast<ThrottlingController*>(WillBeHeapSupplement<LocalFrame>::from(document->frame(), supplementName()));
93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (controller)
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                return controller;
95197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            controller = new ThrottlingController();
97197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            WillBeHeapSupplement<LocalFrame>::provideTo(*document->frame(), supplementName(), adoptPtrWillBeNoop(controller));
98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return controller;
99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(!isMainThread());
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(context->isWorkerGlobalScope());
102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ThrottlingController* controller = static_cast<ThrottlingController*>(WillBeHeapSupplement<WorkerClients>::from(workerGlobalScope->clients(), supplementName()));
104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (controller)
105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return controller;
106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
107197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        controller = new ThrottlingController();
108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WillBeHeapSupplement<WorkerClients>::provideTo(*workerGlobalScope->clients(), supplementName(), adoptPtrWillBeNoop(controller));
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return controller;
110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
112a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ~ThrottlingController() { }
113a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders };
115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static void pushReader(ExecutionContext* context, FileReader* reader)
117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ThrottlingController* controller = from(context);
119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!controller)
120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return;
121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        reader->m_asyncOperationId = InspectorInstrumentation::traceAsyncOperationStarting(context, "FileReader");
123197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        controller->pushReader(reader);
124197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
125197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static FinishReaderType removeReader(ExecutionContext* context, FileReader* reader)
127197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
128197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ThrottlingController* controller = from(context);
129197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!controller)
130197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return DoNotRunPendingReaders;
131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
132197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return controller->removeReader(reader);
133197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
135197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static void finishReader(ExecutionContext* context, FileReader* reader, FinishReaderType nextStep)
136197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        InspectorInstrumentation::traceAsyncOperationCompleted(context, reader->m_asyncOperationId);
138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
139197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ThrottlingController* controller = from(context);
140197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!controller)
141197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return;
142197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
143197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        controller->finishReader(reader, nextStep);
144197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
145197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
146197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void trace(Visitor* visitor)
147197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
148197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(OILPAN)
149197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        visitor->trace(m_pendingReaders);
150197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        visitor->trace(m_runningReaders);
151197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
152197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WillBeHeapSupplement<LocalFrame>::trace(visitor);
153197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WillBeHeapSupplement<WorkerClients>::trace(visitor);
154197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
155197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
156197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
157197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController()
158197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        : m_maxRunningReaders(kMaxOutstandingRequestsPerThread)
159197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
160197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
161197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
162a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    void pushReader(FileReader* reader)
163a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    {
164a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (m_pendingReaders.isEmpty()
165a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            && m_runningReaders.size() < m_maxRunningReaders) {
166a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            reader->executePendingRead();
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ASSERT(!m_runningReaders.contains(reader));
168a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            m_runningReaders.add(reader);
169a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            return;
170a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
171a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_pendingReaders.append(reader);
172a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        executeReaders();
173a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
174a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
175d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    FinishReaderType removeReader(FileReader* reader)
176a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    {
177197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WillBeHeapHashSet<RawPtrWillBeMember<FileReader> >::const_iterator hashIter = m_runningReaders.find(reader);
178a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (hashIter != m_runningReaders.end()) {
179a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            m_runningReaders.remove(hashIter);
180d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return RunPendingReaders;
181a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
182197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator dequeEnd = m_pendingReaders.end();
183197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        for (WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator it = m_pendingReaders.begin(); it != dequeEnd; ++it) {
184a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (*it == reader) {
185a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                m_pendingReaders.remove(it);
186d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                break;
187a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            }
188a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return DoNotRunPendingReaders;
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    void finishReader(FileReader* reader, FinishReaderType nextStep)
193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    {
194d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (nextStep == RunPendingReaders)
195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            executeReaders();
196a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
197a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
198a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    void executeReaders()
199a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    {
200a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        while (m_runningReaders.size() < m_maxRunningReaders) {
201a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (m_pendingReaders.isEmpty())
202a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                return;
203a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            FileReader* reader = m_pendingReaders.takeFirst();
204a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            reader->executePendingRead();
205a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            m_runningReaders.add(reader);
206a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
207a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
208a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
209197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static const char* supplementName() { return "FileReaderThrottlingController"; }
210197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
211a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const size_t m_maxRunningReaders;
212197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WillBeHeapDeque<RawPtrWillBeMember<FileReader> > m_pendingReaders;
213197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WillBeHeapHashSet<RawPtrWillBeMember<FileReader> > m_runningReaders;
214a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)};
215a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)PassRefPtrWillBeRawPtr<FileReader> FileReader::create(ExecutionContext* context)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
218197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RefPtrWillBeRawPtr<FileReader> fileReader(adoptRefWillBeNoop(new FileReader(context)));
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fileReader->suspendIfNeeded();
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fileReader.release();
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2231e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)FileReader::FileReader(ExecutionContext* context)
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : ActiveDOMObject(context)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_state(EMPTY)
2268abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    , m_loadingState(LoadingStateNone)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_readType(FileReaderLoader::ReadAsBinaryString)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_lastProgressNotificationTimeMS(0)
229c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_asyncOperationId(0)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FileReader::~FileReader()
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    terminate();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const AtomicString& FileReader::interfaceName() const
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return EventTargetNames::FileReader;
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::stop()
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    // The delayed abort task tidies up and advances to the DONE state.
2469e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (m_loadingState == LoadingStateAborted)
2479e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return;
2489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
249197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (hasPendingActivity())
250197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ThrottlingController::finishReader(executionContext(), this, ThrottlingController::removeReader(executionContext(), this));
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    terminate();
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
254197021e6b966cfb06891637935ef33fff06433d1Ben Murdochbool FileReader::hasPendingActivity() const
255197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
256197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return m_state == LOADING;
257197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
25951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState)
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(blob);
262a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(FileAPI, "FileReader: reading as array buffer: %s %s\n", utf8BlobUUID(blob).data(), utf8FilePath(blob).data());
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    readInternal(blob, FileReaderLoader::ReadAsArrayBuffer, exceptionState);
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readAsBinaryString(Blob* blob, ExceptionState& exceptionState)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(blob);
270a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(FileAPI, "FileReader: reading as binary: %s %s\n", utf8BlobUUID(blob).data(), utf8FilePath(blob).data());
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    readInternal(blob, FileReaderLoader::ReadAsBinaryString, exceptionState);
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readAsText(Blob* blob, const String& encoding, ExceptionState& exceptionState)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2779e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(blob);
278a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(FileAPI, "FileReader: reading as text: %s %s\n", utf8BlobUUID(blob).data(), utf8FilePath(blob).data());
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_encoding = encoding;
28151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    readInternal(blob, FileReaderLoader::ReadAsText, exceptionState);
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readAsText(Blob* blob, ExceptionState& exceptionState)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
28651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    readAsText(blob, String(), exceptionState);
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readAsDataURL(Blob* blob, ExceptionState& exceptionState)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2919e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(blob);
292a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", utf8BlobUUID(blob).data(), utf8FilePath(blob).data());
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    readInternal(blob, FileReaderLoader::ReadAsDataURL, exceptionState);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type, ExceptionState& exceptionState)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
299e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // If multiple concurrent read methods are called on the same FileReader, InvalidStateError should be thrown when the state is LOADING.
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_state == LOADING) {
30109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The object is already busy reading Blobs.");
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (blob->hasBeenClosed()) {
306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, String(blob->isFile() ? "File" : "Blob") + " has been closed.");
307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
310197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!ThrottlingController::from(executionContext())) {
311197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        exceptionState.throwDOMException(AbortError, "Reading from a Document-detached FileReader is not supported.");
312197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
313197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
314197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
315d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // "Snapshot" the Blob data rather than the Blob itself as ongoing
316d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // read operations should not be affected if close() is called on
317d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // the Blob being read.
318d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_blobDataHandle = blob->blobDataHandle();
319d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_blobType = blob->type();
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_readType = type;
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_state = LOADING;
322a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_loadingState = LoadingStatePending;
323d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_error = nullptr;
324197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::pushReader(executionContext(), this);
325a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
326a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
327a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void FileReader::executePendingRead()
328a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
329a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(m_loadingState == LoadingStatePending);
330a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_loadingState = LoadingStateLoading;
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_loader = adoptPtr(new FileReaderLoader(m_readType, this));
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_loader->setEncoding(m_encoding);
334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_loader->setDataType(m_blobType);
335d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_loader->start(executionContext(), m_blobDataHandle);
336d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_blobDataHandle = nullptr;
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static void delayedAbort(ExecutionContext*, FileReader* reader)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    reader->doAbort();
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::abort()
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
346a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(FileAPI, "FileReader: aborting\n");
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
348a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_loadingState != LoadingStateLoading
349a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        && m_loadingState != LoadingStatePending) {
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
351a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
3528abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_loadingState = LoadingStateAborted;
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Schedule to have the abort done later since abort() might be called from the event handler and we do not want the resource loading code to be in the stack.
3551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    executionContext()->postTask(
356197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        createCrossThreadTask(&delayedAbort, AllowAccessLater(this)));
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::doAbort()
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_state != DONE);
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    terminate();
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_error = FileError::create(FileError::ABORT_ERR);
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
367d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Unregister the reader.
368197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
369d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::error);
3711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::abort);
3721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::loadend);
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // All possible events have fired and we're done, no more pending activity.
375197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::finishReader(executionContext(), this, finalStep);
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::terminate()
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_loader) {
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_loader->cancel();
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_loader = nullptr;
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_state = DONE;
3858abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_loadingState = LoadingStateNone;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::didStartLoading()
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::loadstart);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::didReceiveData()
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fire the progress event at least every 50ms.
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double now = currentTimeMS();
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_lastProgressNotificationTimeMS)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_lastProgressNotificationTimeMS = now;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (now - m_lastProgressNotificationTimeMS > progressNotificationIntervalMS) {
4001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        fireEvent(EventTypeNames::progress);
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_lastProgressNotificationTimeMS = now;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::didFinishLoading()
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4078abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (m_loadingState == LoadingStateAborted)
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4098abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(m_loadingState == LoadingStateLoading);
4108abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
4118abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // It's important that we change m_loadingState before firing any events
4128abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // since any of the events could call abort(), which internally checks
4138abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // if we're still loading (therefore we need abort process) or not.
4148abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_loadingState = LoadingStateNone;
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::progress);
417e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_state != DONE);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_state = DONE;
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
421d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Unregister the reader.
422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
423d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
4241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::load);
4251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::loadend);
42602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // All possible events have fired and we're done, no more pending activity.
428197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::finishReader(executionContext(), this, finalStep);
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
431591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid FileReader::didFail(FileError::ErrorCode errorCode)
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4338abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (m_loadingState == LoadingStateAborted)
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4358abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(m_loadingState == LoadingStateLoading);
4368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_loadingState = LoadingStateNone;
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_state != DONE);
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_state = DONE;
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode));
442d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
443d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Unregister the reader.
444197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
445d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
4461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::error);
4471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    fireEvent(EventTypeNames::loadend);
44802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // All possible events have fired and we're done, no more pending activity.
450197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ThrottlingController::finishReader(executionContext(), this, finalStep);
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FileReader::fireEvent(const AtomicString& type)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
455c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncCallbackStarting(executionContext(), m_asyncOperationId);
456bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!m_loader) {
457bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        dispatchEvent(ProgressEvent::create(type, false, 0, 0));
458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
459bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
460bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
461bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
462bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (m_loader->totalBytes() >= 0)
463bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(), m_loader->totalBytes()));
464bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    else
465bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded(), 0));
466c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
467c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_loader || m_error)
473d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_loader->arrayBufferResult();
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String FileReader::stringResult()
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_loader || m_error)
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return String();
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_loader->stringResult();
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
484d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void FileReader::trace(Visitor* visitor)
485d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
486d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    visitor->trace(m_error);
487d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    EventTargetWithInlineData::trace(visitor);
488d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
489d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
490c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
491