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 |