| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 #include "core/dom/ExceptionCode.h" | 38 #include "core/dom/ExceptionCode.h" |
| 39 #include "core/dom/ExecutionContext.h" | 39 #include "core/dom/ExecutionContext.h" |
| 40 #include "core/events/ProgressEvent.h" | 40 #include "core/events/ProgressEvent.h" |
| 41 #include "core/fileapi/File.h" | 41 #include "core/fileapi/File.h" |
| 42 #include "core/inspector/InspectorInstrumentation.h" | 42 #include "core/inspector/InspectorInstrumentation.h" |
| 43 #include "platform/Logging.h" | 43 #include "platform/Logging.h" |
| 44 #include "platform/Supplementable.h" | 44 #include "platform/Supplementable.h" |
| 45 #include "wtf/CurrentTime.h" | 45 #include "wtf/CurrentTime.h" |
| 46 #include "wtf/Deque.h" | 46 #include "wtf/Deque.h" |
| 47 #include "wtf/HashSet.h" | 47 #include "wtf/HashSet.h" |
| 48 #include "wtf/TemporaryChange.h" |
| 48 #include "wtf/text/CString.h" | 49 #include "wtf/text/CString.h" |
| 49 | 50 |
| 50 namespace blink { | 51 namespace blink { |
| 51 | 52 |
| 52 namespace { | 53 namespace { |
| 53 | 54 |
| 54 const CString utf8BlobUUID(Blob* blob) | 55 const CString utf8BlobUUID(Blob* blob) |
| 55 { | 56 { |
| 56 return blob->uuid().utf8(); | 57 return blob->uuid().utf8(); |
| 57 } | 58 } |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 FileReader* fileReader = new FileReader(context); | 193 FileReader* fileReader = new FileReader(context); |
| 193 fileReader->suspendIfNeeded(); | 194 fileReader->suspendIfNeeded(); |
| 194 return fileReader; | 195 return fileReader; |
| 195 } | 196 } |
| 196 | 197 |
| 197 FileReader::FileReader(ExecutionContext* context) | 198 FileReader::FileReader(ExecutionContext* context) |
| 198 : ActiveScriptWrappable(this) | 199 : ActiveScriptWrappable(this) |
| 199 , ActiveDOMObject(context) | 200 , ActiveDOMObject(context) |
| 200 , m_state(EMPTY) | 201 , m_state(EMPTY) |
| 201 , m_loadingState(LoadingStateNone) | 202 , m_loadingState(LoadingStateNone) |
| 203 , m_stillFiringEvents(false) |
| 202 , m_readType(FileReaderLoader::ReadAsBinaryString) | 204 , m_readType(FileReaderLoader::ReadAsBinaryString) |
| 203 , m_lastProgressNotificationTimeMS(0) | 205 , m_lastProgressNotificationTimeMS(0) |
| 204 { | 206 { |
| 205 } | 207 } |
| 206 | 208 |
| 207 FileReader::~FileReader() | 209 FileReader::~FileReader() |
| 208 { | 210 { |
| 209 terminate(); | 211 terminate(); |
| 210 } | 212 } |
| 211 | 213 |
| 212 const AtomicString& FileReader::interfaceName() const | 214 const AtomicString& FileReader::interfaceName() const |
| 213 { | 215 { |
| 214 return EventTargetNames::FileReader; | 216 return EventTargetNames::FileReader; |
| 215 } | 217 } |
| 216 | 218 |
| 217 void FileReader::stop() | 219 void FileReader::stop() |
| 218 { | 220 { |
| 219 // The delayed abort task tidies up and advances to the DONE state. | 221 // The delayed abort task tidies up and advances to the DONE state. |
| 220 if (m_loadingState == LoadingStateAborted) | 222 if (m_loadingState == LoadingStateAborted) |
| 221 return; | 223 return; |
| 222 | 224 |
| 223 if (hasPendingActivity()) | 225 if (hasPendingActivity()) |
| 224 ThrottlingController::finishReader(getExecutionContext(), this, Throttli
ngController::removeReader(getExecutionContext(), this)); | 226 ThrottlingController::finishReader(getExecutionContext(), this, Throttli
ngController::removeReader(getExecutionContext(), this)); |
| 225 terminate(); | 227 terminate(); |
| 226 } | 228 } |
| 227 | 229 |
| 228 bool FileReader::hasPendingActivity() const | 230 bool FileReader::hasPendingActivity() const |
| 229 { | 231 { |
| 230 return m_state == LOADING; | 232 return m_state == LOADING || m_stillFiringEvents; |
| 231 } | 233 } |
| 232 | 234 |
| 233 void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState) | 235 void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState) |
| 234 { | 236 { |
| 235 ASSERT(blob); | 237 ASSERT(blob); |
| 236 DVLOG(1) << "reading as array buffer: " << utf8BlobUUID(blob).data() << " "
<< utf8FilePath(blob).data(); | 238 DVLOG(1) << "reading as array buffer: " << utf8BlobUUID(blob).data() << " "
<< utf8FilePath(blob).data(); |
| 237 | 239 |
| 238 readInternal(blob, FileReaderLoader::ReadAsArrayBuffer, exceptionState); | 240 readInternal(blob, FileReaderLoader::ReadAsArrayBuffer, exceptionState); |
| 239 } | 241 } |
| 240 | 242 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 m_loadingState = LoadingStateAborted; | 336 m_loadingState = LoadingStateAborted; |
| 335 | 337 |
| 336 // 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 stac
k. | 338 // 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 stac
k. |
| 337 getExecutionContext()->postTask( | 339 getExecutionContext()->postTask( |
| 338 BLINK_FROM_HERE, createSameThreadTask(&delayedAbort, wrapPersistent(this
))); | 340 BLINK_FROM_HERE, createSameThreadTask(&delayedAbort, wrapPersistent(this
))); |
| 339 } | 341 } |
| 340 | 342 |
| 341 void FileReader::doAbort() | 343 void FileReader::doAbort() |
| 342 { | 344 { |
| 343 ASSERT(m_state != DONE); | 345 ASSERT(m_state != DONE); |
| 346 TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); |
| 344 | 347 |
| 345 terminate(); | 348 terminate(); |
| 346 | 349 |
| 347 m_error = FileError::create(FileError::ABORT_ERR); | 350 m_error = FileError::create(FileError::ABORT_ERR); |
| 348 | 351 |
| 349 // Unregister the reader. | 352 // Unregister the reader. |
| 350 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); | 353 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); |
| 351 | 354 |
| 352 fireEvent(EventTypeNames::error); | 355 fireEvent(EventTypeNames::error); |
| 353 fireEvent(EventTypeNames::abort); | 356 fireEvent(EventTypeNames::abort); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 373 if (m_loader) { | 376 if (m_loader) { |
| 374 m_loader->cancel(); | 377 m_loader->cancel(); |
| 375 m_loader = nullptr; | 378 m_loader = nullptr; |
| 376 } | 379 } |
| 377 m_state = DONE; | 380 m_state = DONE; |
| 378 m_loadingState = LoadingStateNone; | 381 m_loadingState = LoadingStateNone; |
| 379 } | 382 } |
| 380 | 383 |
| 381 void FileReader::didStartLoading() | 384 void FileReader::didStartLoading() |
| 382 { | 385 { |
| 386 TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); |
| 383 fireEvent(EventTypeNames::loadstart); | 387 fireEvent(EventTypeNames::loadstart); |
| 384 } | 388 } |
| 385 | 389 |
| 386 void FileReader::didReceiveData() | 390 void FileReader::didReceiveData() |
| 387 { | 391 { |
| 388 // Fire the progress event at least every 50ms. | 392 // Fire the progress event at least every 50ms. |
| 389 double now = currentTimeMS(); | 393 double now = currentTimeMS(); |
| 390 if (!m_lastProgressNotificationTimeMS) { | 394 if (!m_lastProgressNotificationTimeMS) { |
| 391 m_lastProgressNotificationTimeMS = now; | 395 m_lastProgressNotificationTimeMS = now; |
| 392 } else if (now - m_lastProgressNotificationTimeMS > progressNotificationInte
rvalMS) { | 396 } else if (now - m_lastProgressNotificationTimeMS > progressNotificationInte
rvalMS) { |
| 397 TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); |
| 393 fireEvent(EventTypeNames::progress); | 398 fireEvent(EventTypeNames::progress); |
| 394 m_lastProgressNotificationTimeMS = now; | 399 m_lastProgressNotificationTimeMS = now; |
| 395 } | 400 } |
| 396 } | 401 } |
| 397 | 402 |
| 398 void FileReader::didFinishLoading() | 403 void FileReader::didFinishLoading() |
| 399 { | 404 { |
| 400 if (m_loadingState == LoadingStateAborted) | 405 if (m_loadingState == LoadingStateAborted) |
| 401 return; | 406 return; |
| 402 ASSERT(m_loadingState == LoadingStateLoading); | 407 ASSERT(m_loadingState == LoadingStateLoading); |
| 403 | 408 |
| 409 // TODO(jochen): When we set m_state to DONE below, we still need to fire |
| 410 // the load and loadend events. To avoid GC to collect this FileReader, we |
| 411 // use this separate variable to keep the wrapper of this FileReader alive. |
| 412 // An alternative would be to keep any active DOM object alive that is on |
| 413 // the stack. |
| 414 TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); |
| 415 |
| 404 // It's important that we change m_loadingState before firing any events | 416 // It's important that we change m_loadingState before firing any events |
| 405 // since any of the events could call abort(), which internally checks | 417 // since any of the events could call abort(), which internally checks |
| 406 // if we're still loading (therefore we need abort process) or not. | 418 // if we're still loading (therefore we need abort process) or not. |
| 407 m_loadingState = LoadingStateNone; | 419 m_loadingState = LoadingStateNone; |
| 408 | 420 |
| 409 fireEvent(EventTypeNames::progress); | 421 fireEvent(EventTypeNames::progress); |
| 410 | 422 |
| 411 ASSERT(m_state != DONE); | 423 ASSERT(m_state != DONE); |
| 412 m_state = DONE; | 424 m_state = DONE; |
| 413 | 425 |
| 414 // Unregister the reader. | 426 // Unregister the reader. |
| 415 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); | 427 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); |
| 416 | 428 |
| 417 fireEvent(EventTypeNames::load); | 429 fireEvent(EventTypeNames::load); |
| 418 fireEvent(EventTypeNames::loadend); | 430 fireEvent(EventTypeNames::loadend); |
| 419 | 431 |
| 420 // All possible events have fired and we're done, no more pending activity. | 432 // All possible events have fired and we're done, no more pending activity. |
| 421 ThrottlingController::finishReader(getExecutionContext(), this, finalStep); | 433 ThrottlingController::finishReader(getExecutionContext(), this, finalStep); |
| 422 } | 434 } |
| 423 | 435 |
| 424 void FileReader::didFail(FileError::ErrorCode errorCode) | 436 void FileReader::didFail(FileError::ErrorCode errorCode) |
| 425 { | 437 { |
| 426 if (m_loadingState == LoadingStateAborted) | 438 if (m_loadingState == LoadingStateAborted) |
| 427 return; | 439 return; |
| 440 |
| 441 TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); |
| 442 |
| 428 ASSERT(m_loadingState == LoadingStateLoading); | 443 ASSERT(m_loadingState == LoadingStateLoading); |
| 429 m_loadingState = LoadingStateNone; | 444 m_loadingState = LoadingStateNone; |
| 430 | 445 |
| 431 ASSERT(m_state != DONE); | 446 ASSERT(m_state != DONE); |
| 432 m_state = DONE; | 447 m_state = DONE; |
| 433 | 448 |
| 434 m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); | 449 m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); |
| 435 | 450 |
| 436 // Unregister the reader. | 451 // Unregister the reader. |
| 437 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); | 452 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem
oveReader(getExecutionContext(), this); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 458 } | 473 } |
| 459 | 474 |
| 460 DEFINE_TRACE(FileReader) | 475 DEFINE_TRACE(FileReader) |
| 461 { | 476 { |
| 462 visitor->trace(m_error); | 477 visitor->trace(m_error); |
| 463 EventTargetWithInlineData::trace(visitor); | 478 EventTargetWithInlineData::trace(visitor); |
| 464 ActiveDOMObject::trace(visitor); | 479 ActiveDOMObject::trace(visitor); |
| 465 } | 480 } |
| 466 | 481 |
| 467 } // namespace blink | 482 } // namespace blink |
| OLD | NEW |