Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: Source/core/fileapi/FileReader.cpp

Issue 399863002: Gracefully handle FileReader() read operations when in a detached state. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Throw AbortError (instead of InvalidStateError.) Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/fileapi/FileReader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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(AbortError, "Reading from a Document-de tached FileReader is not supported.");
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
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
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
OLDNEW
« no previous file with comments | « Source/core/fileapi/FileReader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698