Chromium Code Reviews| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 #endif | 68 #endif |
| 69 | 69 |
| 70 } // namespace | 70 } // namespace |
| 71 | 71 |
| 72 // Embedders like chromium limit the number of simultaneous requests to avoid | 72 // Embedders like chromium limit the number of simultaneous requests to avoid |
| 73 // excessive IPC congestion. We limit this to 100 per thread to throttle the | 73 // excessive IPC congestion. We limit this to 100 per thread to throttle the |
| 74 // requests (the value is arbitrarily chosen). | 74 // requests (the value is arbitrarily chosen). |
| 75 static const size_t kMaxOutstandingRequestsPerThread = 100; | 75 static const size_t kMaxOutstandingRequestsPerThread = 100; |
| 76 static const double progressNotificationIntervalMS = 50; | 76 static const double progressNotificationIntervalMS = 50; |
| 77 | 77 |
| 78 // FIXME: Oilpan: if ExecutionContext is moved to the heap, consider | |
| 79 // making this object an ExecutionContext supplement (only.) | |
| 78 class FileReader::ThrottlingController FINAL : public NoBaseWillBeGarbageCollect edFinalized<FileReader::ThrottlingController>, public WillBeHeapSupplement<Local Frame>, public WillBeHeapSupplement<WorkerClients> { | 80 class FileReader::ThrottlingController FINAL : public NoBaseWillBeGarbageCollect edFinalized<FileReader::ThrottlingController>, public WillBeHeapSupplement<Local Frame>, public WillBeHeapSupplement<WorkerClients> { |
| 79 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController); | 81 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController); |
| 80 public: | 82 public: |
| 81 static ThrottlingController* from(ExecutionContext* context) | 83 static ThrottlingController* from(ExecutionContext* context) |
| 82 { | 84 { |
| 85 if (!context) | |
| 86 return 0; | |
| 87 | |
| 83 if (context->isDocument()) { | 88 if (context->isDocument()) { |
| 84 Document* document = toDocument(context); | 89 Document* document = toDocument(context); |
| 85 if (!document->frame()) | 90 if (!document->frame()) |
| 86 return 0; | 91 return 0; |
| 87 | 92 |
| 88 ThrottlingController* controller = static_cast<ThrottlingController* >(WillBeHeapSupplement<LocalFrame>::from(document->frame(), supplementName())); | 93 ThrottlingController* controller = static_cast<ThrottlingController* >(WillBeHeapSupplement<LocalFrame>::from(document->frame(), supplementName())); |
| 89 if (controller) | 94 if (controller) |
| 90 return controller; | 95 return controller; |
| 91 | 96 |
| 92 controller = new ThrottlingController(); | 97 controller = new ThrottlingController(); |
| 93 WillBeHeapSupplement<LocalFrame>::provideTo(*document->frame(), supp lementName(), adoptPtrWillBeNoop(controller)); | 98 WillBeHeapSupplement<LocalFrame>::provideTo(*document->frame(), supp lementName(), adoptPtrWillBeNoop(controller)); |
| 94 return controller; | 99 return controller; |
| 95 } | 100 } |
| 96 ASSERT(!isMainThread()); | 101 ASSERT(!isMainThread()); |
| 97 ASSERT(context->isWorkerGlobalScope()); | 102 ASSERT(context->isWorkerGlobalScope()); |
| 98 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); | 103 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); |
| 99 ThrottlingController* controller = static_cast<ThrottlingController*>(Wi llBeHeapSupplement<WorkerClients>::from(workerGlobalScope->clients(), supplement Name())); | 104 ThrottlingController* controller = static_cast<ThrottlingController*>(Wi llBeHeapSupplement<WorkerClients>::from(workerGlobalScope->clients(), supplement Name())); |
| 100 if (controller) | 105 if (controller) |
| 101 return controller; | 106 return controller; |
| 102 | 107 |
| 103 controller = new ThrottlingController(); | 108 controller = new ThrottlingController(); |
| 104 WillBeHeapSupplement<WorkerClients>::provideTo(*workerGlobalScope->clien ts(), supplementName(), adoptPtrWillBeNoop(controller)); | 109 WillBeHeapSupplement<WorkerClients>::provideTo(*workerGlobalScope->clien ts(), supplementName(), adoptPtrWillBeNoop(controller)); |
| 105 return controller; | 110 return controller; |
| 106 } | 111 } |
| 107 | 112 |
| 108 ~ThrottlingController() { } | 113 ~ThrottlingController() { } |
| 109 | 114 |
| 110 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; | 115 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; |
| 111 | 116 |
| 117 static void pushReader(ExecutionContext* context, FileReader* reader) | |
| 118 { | |
| 119 ThrottlingController* controller = from(context); | |
| 120 if (!controller) | |
| 121 return; | |
| 122 | |
| 123 controller->pushReader(reader); | |
| 124 } | |
| 125 | |
| 126 static FinishReaderType removeReader(ExecutionContext* context, FileReader* reader) | |
| 127 { | |
| 128 ThrottlingController* controller = from(context); | |
| 129 if (!controller) | |
| 130 return DoNotRunPendingReaders; | |
| 131 | |
| 132 return controller->removeReader(reader); | |
| 133 } | |
| 134 | |
| 135 static void finishReader(ExecutionContext* context, FileReader* reader, Fini shReaderType nextStep) | |
| 136 { | |
| 137 ThrottlingController* controller = from(context); | |
| 138 if (!controller) | |
| 139 return; | |
| 140 | |
| 141 controller->finishReader(reader, nextStep); | |
| 142 } | |
| 143 | |
| 144 void trace(Visitor* visitor) | |
| 145 { | |
| 146 #if ENABLE(OILPAN) | |
| 147 visitor->trace(m_pendingReaders); | |
| 148 visitor->trace(m_runningReaders); | |
| 149 #endif | |
| 150 WillBeHeapSupplement<LocalFrame>::trace(visitor); | |
| 151 WillBeHeapSupplement<WorkerClients>::trace(visitor); | |
| 152 } | |
| 153 | |
| 154 private: | |
| 155 ThrottlingController() | |
| 156 : m_maxRunningReaders(kMaxOutstandingRequestsPerThread) | |
| 157 { | |
| 158 } | |
| 159 | |
| 112 void pushReader(FileReader* reader) | 160 void pushReader(FileReader* reader) |
| 113 { | 161 { |
| 114 if (m_pendingReaders.isEmpty() | 162 if (m_pendingReaders.isEmpty() |
| 115 && m_runningReaders.size() < m_maxRunningReaders) { | 163 && m_runningReaders.size() < m_maxRunningReaders) { |
| 116 reader->executePendingRead(); | 164 reader->executePendingRead(); |
| 117 ASSERT(!m_runningReaders.contains(reader)); | 165 ASSERT(!m_runningReaders.contains(reader)); |
| 118 m_runningReaders.add(reader); | 166 m_runningReaders.add(reader); |
| 119 return; | 167 return; |
| 120 } | 168 } |
| 121 m_pendingReaders.append(reader); | 169 m_pendingReaders.append(reader); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 138 } | 186 } |
| 139 return DoNotRunPendingReaders; | 187 return DoNotRunPendingReaders; |
| 140 } | 188 } |
| 141 | 189 |
| 142 void finishReader(FileReader* reader, FinishReaderType nextStep) | 190 void finishReader(FileReader* reader, FinishReaderType nextStep) |
| 143 { | 191 { |
| 144 if (nextStep == RunPendingReaders) | 192 if (nextStep == RunPendingReaders) |
| 145 executeReaders(); | 193 executeReaders(); |
| 146 } | 194 } |
| 147 | 195 |
| 148 void trace(Visitor* visitor) | |
| 149 { | |
| 150 #if ENABLE(OILPAN) | |
| 151 visitor->trace(m_pendingReaders); | |
| 152 visitor->trace(m_runningReaders); | |
| 153 #endif | |
| 154 WillBeHeapSupplement<LocalFrame>::trace(visitor); | |
| 155 WillBeHeapSupplement<WorkerClients>::trace(visitor); | |
| 156 } | |
| 157 | |
| 158 private: | |
| 159 ThrottlingController() | |
| 160 : m_maxRunningReaders(kMaxOutstandingRequestsPerThread) | |
| 161 { | |
| 162 } | |
| 163 | |
| 164 void executeReaders() | 196 void executeReaders() |
| 165 { | 197 { |
| 166 while (m_runningReaders.size() < m_maxRunningReaders) { | 198 while (m_runningReaders.size() < m_maxRunningReaders) { |
| 167 if (m_pendingReaders.isEmpty()) | 199 if (m_pendingReaders.isEmpty()) |
| 168 return; | 200 return; |
| 169 FileReader* reader = m_pendingReaders.takeFirst(); | 201 FileReader* reader = m_pendingReaders.takeFirst(); |
| 170 reader->executePendingRead(); | 202 reader->executePendingRead(); |
| 171 m_runningReaders.add(reader); | 203 m_runningReaders.add(reader); |
| 172 } | 204 } |
| 173 } | 205 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 202 } | 234 } |
| 203 | 235 |
| 204 const AtomicString& FileReader::interfaceName() const | 236 const AtomicString& FileReader::interfaceName() const |
| 205 { | 237 { |
| 206 return EventTargetNames::FileReader; | 238 return EventTargetNames::FileReader; |
| 207 } | 239 } |
| 208 | 240 |
| 209 void FileReader::stop() | 241 void FileReader::stop() |
| 210 { | 242 { |
| 211 if (hasPendingActivity()) | 243 if (hasPendingActivity()) |
| 212 throttlingController()->finishReader(this, throttlingController()->remov eReader(this)); | 244 ThrottlingController::finishReader(executionContext(), this, ThrottlingC ontroller::removeReader(executionContext(), this)); |
| 213 terminate(); | 245 terminate(); |
| 214 } | 246 } |
| 215 | 247 |
| 216 bool FileReader::hasPendingActivity() const | 248 bool FileReader::hasPendingActivity() const |
| 217 { | 249 { |
| 218 return m_state == LOADING; | 250 return m_state == LOADING; |
| 219 } | 251 } |
| 220 | 252 |
| 221 void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState) | 253 void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState) |
| 222 { | 254 { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 if (m_state == LOADING) { | 310 if (m_state == LOADING) { |
| 279 exceptionState.throwDOMException(InvalidStateError, "The object is alrea dy busy reading Blobs."); | 311 exceptionState.throwDOMException(InvalidStateError, "The object is alrea dy busy reading Blobs."); |
| 280 return; | 312 return; |
| 281 } | 313 } |
| 282 | 314 |
| 283 if (blob->hasBeenClosed()) { | 315 if (blob->hasBeenClosed()) { |
| 284 exceptionState.throwDOMException(InvalidStateError, String(blob->isFile( ) ? "File" : "Blob") + " has been closed."); | 316 exceptionState.throwDOMException(InvalidStateError, String(blob->isFile( ) ? "File" : "Blob") + " has been closed."); |
| 285 return; | 317 return; |
| 286 } | 318 } |
| 287 | 319 |
| 320 if (!ThrottlingController::from(executionContext())) { | |
| 321 exceptionState.throwDOMException(InvalidStateError, "Reading from a Docu ment-detached FileReader is not supported."); | |
|
haraken
2014/07/18 01:01:53
Looks like kinuko-san prefers AbortError?
nhiroki
2014/07/18 01:54:42
I'd prefer AbortError, too.
sof
2014/07/18 05:26:37
ok, let's throw that instead. Switched over.
| |
| 322 return; | |
| 323 } | |
| 324 | |
| 288 // "Snapshot" the Blob data rather than the Blob itself as ongoing | 325 // "Snapshot" the Blob data rather than the Blob itself as ongoing |
| 289 // read operations should not be affected if close() is called on | 326 // read operations should not be affected if close() is called on |
| 290 // the Blob being read. | 327 // the Blob being read. |
| 291 m_blobDataHandle = blob->blobDataHandle(); | 328 m_blobDataHandle = blob->blobDataHandle(); |
| 292 m_blobType = blob->type(); | 329 m_blobType = blob->type(); |
| 293 m_readType = type; | 330 m_readType = type; |
| 294 m_state = LOADING; | 331 m_state = LOADING; |
| 295 m_loadingState = LoadingStatePending; | 332 m_loadingState = LoadingStatePending; |
| 296 m_error = nullptr; | 333 m_error = nullptr; |
| 297 throttlingController()->pushReader(this); | 334 ThrottlingController::pushReader(executionContext(), this); |
| 298 } | 335 } |
| 299 | 336 |
| 300 void FileReader::executePendingRead() | 337 void FileReader::executePendingRead() |
| 301 { | 338 { |
| 302 ASSERT(m_loadingState == LoadingStatePending); | 339 ASSERT(m_loadingState == LoadingStatePending); |
| 303 m_loadingState = LoadingStateLoading; | 340 m_loadingState = LoadingStateLoading; |
| 304 | 341 |
| 305 m_loader = adoptPtr(new FileReaderLoader(m_readType, this)); | 342 m_loader = adoptPtr(new FileReaderLoader(m_readType, this)); |
| 306 m_loader->setEncoding(m_encoding); | 343 m_loader->setEncoding(m_encoding); |
| 307 m_loader->setDataType(m_blobType); | 344 m_loader->setDataType(m_blobType); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 331 | 368 |
| 332 void FileReader::doAbort() | 369 void FileReader::doAbort() |
| 333 { | 370 { |
| 334 ASSERT(m_state != DONE); | 371 ASSERT(m_state != DONE); |
| 335 | 372 |
| 336 terminate(); | 373 terminate(); |
| 337 | 374 |
| 338 m_error = FileError::create(FileError::ABORT_ERR); | 375 m_error = FileError::create(FileError::ABORT_ERR); |
| 339 | 376 |
| 340 // Unregister the reader. | 377 // Unregister the reader. |
| 341 ThrottlingController::FinishReaderType finalStep = throttlingController()->r emoveReader(this); | 378 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem oveReader(executionContext(), this); |
| 342 | 379 |
| 343 fireEvent(EventTypeNames::error); | 380 fireEvent(EventTypeNames::error); |
| 344 fireEvent(EventTypeNames::abort); | 381 fireEvent(EventTypeNames::abort); |
| 345 fireEvent(EventTypeNames::loadend); | 382 fireEvent(EventTypeNames::loadend); |
| 346 | 383 |
| 347 // All possible events have fired and we're done, no more pending activity. | 384 // All possible events have fired and we're done, no more pending activity. |
| 348 throttlingController()->finishReader(this, finalStep); | 385 ThrottlingController::finishReader(executionContext(), this, finalStep); |
| 349 } | 386 } |
| 350 | 387 |
| 351 void FileReader::terminate() | 388 void FileReader::terminate() |
| 352 { | 389 { |
| 353 if (m_loader) { | 390 if (m_loader) { |
| 354 m_loader->cancel(); | 391 m_loader->cancel(); |
| 355 m_loader = nullptr; | 392 m_loader = nullptr; |
| 356 } | 393 } |
| 357 m_state = DONE; | 394 m_state = DONE; |
| 358 m_loadingState = LoadingStateNone; | 395 m_loadingState = LoadingStateNone; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 385 // since any of the events could call abort(), which internally checks | 422 // since any of the events could call abort(), which internally checks |
| 386 // if we're still loading (therefore we need abort process) or not. | 423 // if we're still loading (therefore we need abort process) or not. |
| 387 m_loadingState = LoadingStateNone; | 424 m_loadingState = LoadingStateNone; |
| 388 | 425 |
| 389 fireEvent(EventTypeNames::progress); | 426 fireEvent(EventTypeNames::progress); |
| 390 | 427 |
| 391 ASSERT(m_state != DONE); | 428 ASSERT(m_state != DONE); |
| 392 m_state = DONE; | 429 m_state = DONE; |
| 393 | 430 |
| 394 // Unregister the reader. | 431 // Unregister the reader. |
| 395 ThrottlingController::FinishReaderType finalStep = throttlingController()->r emoveReader(this); | 432 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem oveReader(executionContext(), this); |
| 396 | 433 |
| 397 fireEvent(EventTypeNames::load); | 434 fireEvent(EventTypeNames::load); |
| 398 fireEvent(EventTypeNames::loadend); | 435 fireEvent(EventTypeNames::loadend); |
| 399 | 436 |
| 400 // All possible events have fired and we're done, no more pending activity. | 437 // All possible events have fired and we're done, no more pending activity. |
| 401 throttlingController()->finishReader(this, finalStep); | 438 ThrottlingController::finishReader(executionContext(), this, finalStep); |
| 402 } | 439 } |
| 403 | 440 |
| 404 void FileReader::didFail(FileError::ErrorCode errorCode) | 441 void FileReader::didFail(FileError::ErrorCode errorCode) |
| 405 { | 442 { |
| 406 if (m_loadingState == LoadingStateAborted) | 443 if (m_loadingState == LoadingStateAborted) |
| 407 return; | 444 return; |
| 408 ASSERT(m_loadingState == LoadingStateLoading); | 445 ASSERT(m_loadingState == LoadingStateLoading); |
| 409 m_loadingState = LoadingStateNone; | 446 m_loadingState = LoadingStateNone; |
| 410 | 447 |
| 411 ASSERT(m_state != DONE); | 448 ASSERT(m_state != DONE); |
| 412 m_state = DONE; | 449 m_state = DONE; |
| 413 | 450 |
| 414 m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); | 451 m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode)); |
| 415 | 452 |
| 416 // Unregister the reader. | 453 // Unregister the reader. |
| 417 ThrottlingController::FinishReaderType finalStep = throttlingController()->r emoveReader(this); | 454 ThrottlingController::FinishReaderType finalStep = ThrottlingController::rem oveReader(executionContext(), this); |
| 418 | 455 |
| 419 fireEvent(EventTypeNames::error); | 456 fireEvent(EventTypeNames::error); |
| 420 fireEvent(EventTypeNames::loadend); | 457 fireEvent(EventTypeNames::loadend); |
| 421 | 458 |
| 422 // All possible events have fired and we're done, no more pending activity. | 459 // All possible events have fired and we're done, no more pending activity. |
| 423 throttlingController()->finishReader(this, finalStep); | 460 ThrottlingController::finishReader(executionContext(), this, finalStep); |
| 424 } | 461 } |
| 425 | 462 |
| 426 void FileReader::fireEvent(const AtomicString& type) | 463 void FileReader::fireEvent(const AtomicString& type) |
| 427 { | 464 { |
| 428 if (!m_loader) { | 465 if (!m_loader) { |
| 429 dispatchEvent(ProgressEvent::create(type, false, 0, 0)); | 466 dispatchEvent(ProgressEvent::create(type, false, 0, 0)); |
| 430 return; | 467 return; |
| 431 } | 468 } |
| 432 | 469 |
| 433 if (m_loader->totalBytes() >= 0) | 470 if (m_loader->totalBytes() >= 0) |
| 434 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(), m_loader->totalBytes())); | 471 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(), m_loader->totalBytes())); |
| 435 else | 472 else |
| 436 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded() , 0)); | 473 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded() , 0)); |
| 437 } | 474 } |
| 438 | 475 |
| 439 FileReader::ThrottlingController* FileReader::throttlingController() | |
| 440 { | |
| 441 return FileReader::ThrottlingController::from(executionContext()); | |
| 442 } | |
| 443 | |
| 444 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const | 476 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const |
| 445 { | 477 { |
| 446 if (!m_loader || m_error) | 478 if (!m_loader || m_error) |
| 447 return nullptr; | 479 return nullptr; |
| 448 return m_loader->arrayBufferResult(); | 480 return m_loader->arrayBufferResult(); |
| 449 } | 481 } |
| 450 | 482 |
| 451 String FileReader::stringResult() | 483 String FileReader::stringResult() |
| 452 { | 484 { |
| 453 if (!m_loader || m_error) | 485 if (!m_loader || m_error) |
| 454 return String(); | 486 return String(); |
| 455 return m_loader->stringResult(); | 487 return m_loader->stringResult(); |
| 456 } | 488 } |
| 457 | 489 |
| 458 void FileReader::trace(Visitor* visitor) | 490 void FileReader::trace(Visitor* visitor) |
| 459 { | 491 { |
| 460 visitor->trace(m_error); | 492 visitor->trace(m_error); |
| 461 EventTargetWithInlineData::trace(visitor); | 493 EventTargetWithInlineData::trace(visitor); |
| 462 } | 494 } |
| 463 | 495 |
| 464 } // namespace WebCore | 496 } // namespace WebCore |
| OLD | NEW |