| Index: Source/core/fileapi/FileReader.cpp
|
| diff --git a/Source/core/fileapi/FileReader.cpp b/Source/core/fileapi/FileReader.cpp
|
| index 9a3f948c257b6e5611ea38534e2ebf2a3a674e65..88789491569d909d62e03d3610da9572637ade27 100644
|
| --- a/Source/core/fileapi/FileReader.cpp
|
| +++ b/Source/core/fileapi/FileReader.cpp
|
| @@ -75,11 +75,16 @@ const CString utf8FilePath(Blob* blob)
|
| static const size_t kMaxOutstandingRequestsPerThread = 100;
|
| static const double progressNotificationIntervalMS = 50;
|
|
|
| +// FIXME: Oilpan: if ExecutionContext is moved to the heap, consider
|
| +// making this object an ExecutionContext supplement (only.)
|
| class FileReader::ThrottlingController FINAL : public NoBaseWillBeGarbageCollectedFinalized<FileReader::ThrottlingController>, public WillBeHeapSupplement<LocalFrame>, public WillBeHeapSupplement<WorkerClients> {
|
| WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController);
|
| public:
|
| static ThrottlingController* from(ExecutionContext* context)
|
| {
|
| + if (!context)
|
| + return 0;
|
| +
|
| if (context->isDocument()) {
|
| Document* document = toDocument(context);
|
| if (!document->frame())
|
| @@ -109,6 +114,49 @@ public:
|
|
|
| enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders };
|
|
|
| + static void pushReader(ExecutionContext* context, FileReader* reader)
|
| + {
|
| + ThrottlingController* controller = from(context);
|
| + if (!controller)
|
| + return;
|
| +
|
| + controller->pushReader(reader);
|
| + }
|
| +
|
| + static FinishReaderType removeReader(ExecutionContext* context, FileReader* reader)
|
| + {
|
| + ThrottlingController* controller = from(context);
|
| + if (!controller)
|
| + return DoNotRunPendingReaders;
|
| +
|
| + return controller->removeReader(reader);
|
| + }
|
| +
|
| + static void finishReader(ExecutionContext* context, FileReader* reader, FinishReaderType nextStep)
|
| + {
|
| + ThrottlingController* controller = from(context);
|
| + if (!controller)
|
| + return;
|
| +
|
| + controller->finishReader(reader, nextStep);
|
| + }
|
| +
|
| + void trace(Visitor* visitor)
|
| + {
|
| +#if ENABLE(OILPAN)
|
| + visitor->trace(m_pendingReaders);
|
| + visitor->trace(m_runningReaders);
|
| +#endif
|
| + WillBeHeapSupplement<LocalFrame>::trace(visitor);
|
| + WillBeHeapSupplement<WorkerClients>::trace(visitor);
|
| + }
|
| +
|
| +private:
|
| + ThrottlingController()
|
| + : m_maxRunningReaders(kMaxOutstandingRequestsPerThread)
|
| + {
|
| + }
|
| +
|
| void pushReader(FileReader* reader)
|
| {
|
| if (m_pendingReaders.isEmpty()
|
| @@ -145,22 +193,6 @@ public:
|
| executeReaders();
|
| }
|
|
|
| - void trace(Visitor* visitor)
|
| - {
|
| -#if ENABLE(OILPAN)
|
| - visitor->trace(m_pendingReaders);
|
| - visitor->trace(m_runningReaders);
|
| -#endif
|
| - WillBeHeapSupplement<LocalFrame>::trace(visitor);
|
| - WillBeHeapSupplement<WorkerClients>::trace(visitor);
|
| - }
|
| -
|
| -private:
|
| - ThrottlingController()
|
| - : m_maxRunningReaders(kMaxOutstandingRequestsPerThread)
|
| - {
|
| - }
|
| -
|
| void executeReaders()
|
| {
|
| while (m_runningReaders.size() < m_maxRunningReaders) {
|
| @@ -209,7 +241,7 @@ const AtomicString& FileReader::interfaceName() const
|
| void FileReader::stop()
|
| {
|
| if (hasPendingActivity())
|
| - throttlingController()->finishReader(this, throttlingController()->removeReader(this));
|
| + ThrottlingController::finishReader(executionContext(), this, ThrottlingController::removeReader(executionContext(), this));
|
| terminate();
|
| }
|
|
|
| @@ -285,6 +317,11 @@ void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type, Excep
|
| return;
|
| }
|
|
|
| + if (!ThrottlingController::from(executionContext())) {
|
| + exceptionState.throwDOMException(AbortError, "Reading from a Document-detached FileReader is not supported.");
|
| + return;
|
| + }
|
| +
|
| // "Snapshot" the Blob data rather than the Blob itself as ongoing
|
| // read operations should not be affected if close() is called on
|
| // the Blob being read.
|
| @@ -294,7 +331,7 @@ void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type, Excep
|
| m_state = LOADING;
|
| m_loadingState = LoadingStatePending;
|
| m_error = nullptr;
|
| - throttlingController()->pushReader(this);
|
| + ThrottlingController::pushReader(executionContext(), this);
|
| }
|
|
|
| void FileReader::executePendingRead()
|
| @@ -338,14 +375,14 @@ void FileReader::doAbort()
|
| m_error = FileError::create(FileError::ABORT_ERR);
|
|
|
| // Unregister the reader.
|
| - ThrottlingController::FinishReaderType finalStep = throttlingController()->removeReader(this);
|
| + ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
|
|
|
| fireEvent(EventTypeNames::error);
|
| fireEvent(EventTypeNames::abort);
|
| fireEvent(EventTypeNames::loadend);
|
|
|
| // All possible events have fired and we're done, no more pending activity.
|
| - throttlingController()->finishReader(this, finalStep);
|
| + ThrottlingController::finishReader(executionContext(), this, finalStep);
|
| }
|
|
|
| void FileReader::terminate()
|
| @@ -392,13 +429,13 @@ void FileReader::didFinishLoading()
|
| m_state = DONE;
|
|
|
| // Unregister the reader.
|
| - ThrottlingController::FinishReaderType finalStep = throttlingController()->removeReader(this);
|
| + ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
|
|
|
| fireEvent(EventTypeNames::load);
|
| fireEvent(EventTypeNames::loadend);
|
|
|
| // All possible events have fired and we're done, no more pending activity.
|
| - throttlingController()->finishReader(this, finalStep);
|
| + ThrottlingController::finishReader(executionContext(), this, finalStep);
|
| }
|
|
|
| void FileReader::didFail(FileError::ErrorCode errorCode)
|
| @@ -414,13 +451,13 @@ void FileReader::didFail(FileError::ErrorCode errorCode)
|
| m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode));
|
|
|
| // Unregister the reader.
|
| - ThrottlingController::FinishReaderType finalStep = throttlingController()->removeReader(this);
|
| + ThrottlingController::FinishReaderType finalStep = ThrottlingController::removeReader(executionContext(), this);
|
|
|
| fireEvent(EventTypeNames::error);
|
| fireEvent(EventTypeNames::loadend);
|
|
|
| // All possible events have fired and we're done, no more pending activity.
|
| - throttlingController()->finishReader(this, finalStep);
|
| + ThrottlingController::finishReader(executionContext(), this, finalStep);
|
| }
|
|
|
| void FileReader::fireEvent(const AtomicString& type)
|
| @@ -436,11 +473,6 @@ void FileReader::fireEvent(const AtomicString& type)
|
| dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded(), 0));
|
| }
|
|
|
| -FileReader::ThrottlingController* FileReader::throttlingController()
|
| -{
|
| - return FileReader::ThrottlingController::from(executionContext());
|
| -}
|
| -
|
| PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const
|
| {
|
| if (!m_loader || m_error)
|
|
|