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

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp

Issue 1414553002: Fix out-of-memory crashes related to ArrayBuffer allocation Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reverting some behavior changes Created 5 years, 1 month 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 455
456 // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread). 456 // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
457 if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncod ing(lowercaseMimeType)) 457 if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncod ing(lowercaseMimeType))
458 lowercaseMimeType = "image/png"; 458 lowercaseMimeType = "image/png";
459 459
460 return lowercaseMimeType; 460 return lowercaseMimeType;
461 } 461 }
462 462
463 const AtomicString HTMLCanvasElement::imageSourceURL() const 463 const AtomicString HTMLCanvasElement::imageSourceURL() const
464 { 464 {
465 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer)); 465 NonThrowableExceptionState exceptionState;
466 AtomicString dataURL(toDataURLInternal("image/png", 0, FrontBuffer, exceptio nState));
467 if (exceptionState.hadException())
468 return AtomicString("data:,");
469 return dataURL;
466 } 470 }
467 471
468 void HTMLCanvasElement::prepareSurfaceForPaintingIfNeeded() const 472 void HTMLCanvasElement::prepareSurfaceForPaintingIfNeeded() const
469 { 473 {
470 ASSERT(m_context && m_context->is2d()); // This function is called by the 2d context 474 ASSERT(m_context && m_context->is2d()); // This function is called by the 2d context
471 if (buffer()) 475 if (buffer())
472 m_imageBuffer->prepareSurfaceForPaintingIfNeeded(); 476 m_imageBuffer->prepareSurfaceForPaintingIfNeeded();
473 } 477 }
474 478
475 ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer) cons t 479 ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer, Exce ptionState& exceptionState) const
476 { 480 {
477 ImageData* imageData; 481 ImageData* imageData;
478 if (is3D()) { 482 if (is3D()) {
479 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL(). 483 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL().
480 imageData = m_context->paintRenderingResultsToImageData(sourceBuffer); 484 imageData = m_context->paintRenderingResultsToImageData(sourceBuffer);
481 if (imageData) 485 if (imageData)
482 return imageData; 486 return imageData;
483 487
484 m_context->paintRenderingResultsToCanvas(sourceBuffer); 488 m_context->paintRenderingResultsToCanvas(sourceBuffer);
485 imageData = ImageData::create(m_size); 489 imageData = ImageData::create(m_size, exceptionState);
490 // Note: we rethrow exceptions from ImageData creation, which is not
491 // mandated by the specification because using an ImageData intermediate
492 // for toBlob and toDataURL is an implementation choice. As a result of
493 // this rethrow, a RangeError exception may be thrown when there is
494 // insufficient available memory. Even though the exception is unspec'ed ,
495 // it was ascertained that to throw from here will generally result in a
496 // better outcome than to crash the process.
497 if (exceptionState.hadException())
498 return nullptr;
486 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAccelera tion); 499 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAccelera tion);
487 if (snapshot) { 500 if (snapshot) {
488 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8 888_SkColorType, kUnpremul_SkAlphaType); 501 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8 888_SkColorType, kUnpremul_SkAlphaType);
489 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo .minRowBytes(), 0, 0); 502 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo .minRowBytes(), 0, 0);
490 } 503 }
491 return imageData; 504 return imageData;
492 } 505 }
493 506
494 imageData = ImageData::create(m_size); 507 imageData = ImageData::create(m_size, exceptionState);
508 if (exceptionState.hadException())
509 return nullptr;
495 510
496 if (!m_context) 511 if (!m_context)
497 return imageData; 512 return imageData;
498 513
499 ASSERT(m_context->is2d()); 514 ASSERT(m_context->is2d());
500 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration ); 515 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration );
501 if (snapshot) { 516 if (snapshot) {
502 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_ SkColorType, kUnpremul_SkAlphaType); 517 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_ SkColorType, kUnpremul_SkAlphaType);
503 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.min RowBytes(), 0, 0); 518 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.min RowBytes(), 0, 0);
504 } 519 }
505 520
506 return imageData; 521 return imageData;
507 } 522 }
508 523
509 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double & quality, SourceDrawingBuffer sourceBuffer) const 524 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double & quality, SourceDrawingBuffer sourceBuffer, ExceptionState& exceptionState) con st
510 { 525 {
511 if (!isPaintable()) 526 if (!isPaintable())
512 return String("data:,"); 527 return String("data:,");
513 528
514 String encodingMimeType = toEncodingMimeType(mimeType); 529 String encodingMimeType = toEncodingMimeType(mimeType);
515 530
516 ImageData* imageData = toImageData(sourceBuffer); 531 ImageData* imageData = toImageData(sourceBuffer, exceptionState);
532 if (exceptionState.hadException())
533 return String();
534
517 ScopedDisposal<ImageData> disposer(imageData); 535 ScopedDisposal<ImageData> disposer(imageData);
518 536
519 return ImageDataBuffer(imageData->size(), imageData->data()->data()).toDataU RL(encodingMimeType, quality); 537 return ImageDataBuffer(imageData->size(), imageData->data()->data()).toDataU RL(encodingMimeType, quality);
520 } 538 }
521 539
522 String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q ualityArgument, ExceptionState& exceptionState) const 540 String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q ualityArgument, ExceptionState& exceptionState) const
523 { 541 {
524 if (!originClean()) { 542 if (!originClean()) {
525 exceptionState.throwSecurityError("Tainted canvases may not be exported. "); 543 exceptionState.throwSecurityError("Tainted canvases may not be exported. ");
526 return String(); 544 return String();
527 } 545 }
528 double quality = UndefinedQualityValue; 546 double quality = UndefinedQualityValue;
529 if (!qualityArgument.isEmpty()) { 547 if (!qualityArgument.isEmpty()) {
530 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); 548 v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
531 if (v8Value->IsNumber()) { 549 if (v8Value->IsNumber()) {
532 quality = v8Value.As<v8::Number>()->Value(); 550 quality = v8Value.As<v8::Number>()->Value();
533 } 551 }
534 } 552 }
535 return toDataURLInternal(mimeType, quality, BackBuffer); 553 return toDataURLInternal(mimeType, quality, BackBuffer, exceptionState);
536 } 554 }
537 555
538 void HTMLCanvasElement::encodeImageAsync(DOMUint8ClampedArray* imageData, IntSiz e imageSize, FileCallback* callback, const String& mimeType, double quality) 556 void HTMLCanvasElement::encodeImageAsync(DOMUint8ClampedArray* imageData, IntSiz e imageSize, FileCallback* callback, const String& mimeType, double quality)
539 { 557 {
540 OwnPtr<Vector<char>> encodedImage(adoptPtr(new Vector<char>())); 558 OwnPtr<Vector<char>> encodedImage(adoptPtr(new Vector<char>()));
541 559
542 if (!ImageDataBuffer(imageSize, imageData->data()).encodeImage(mimeType, qua lity, encodedImage.get())) { 560 if (!ImageDataBuffer(imageSize, imageData->data()).encodeImage(mimeType, qua lity, encodedImage.get())) {
543 Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HER E, bind(&FileCallback::handleEvent, callback, nullptr)); 561 Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HER E, bind(&FileCallback::handleEvent, callback, nullptr));
544 } else { 562 } else {
545 Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HER E, threadSafeBind(&HTMLCanvasElement::createBlobAndCall, encodedImage.release(), mimeType, AllowCrossThreadAccess(callback))); 563 Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HER E, threadSafeBind(&HTMLCanvasElement::createBlobAndCall, encodedImage.release(), mimeType, AllowCrossThreadAccess(callback)));
(...skipping 25 matching lines...) Expand all
571 double quality = UndefinedQualityValue; 589 double quality = UndefinedQualityValue;
572 if (!qualityArgument.isEmpty()) { 590 if (!qualityArgument.isEmpty()) {
573 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); 591 v8::Local<v8::Value> v8Value = qualityArgument.v8Value();
574 if (v8Value->IsNumber()) { 592 if (v8Value->IsNumber()) {
575 quality = v8Value.As<v8::Number>()->Value(); 593 quality = v8Value.As<v8::Number>()->Value();
576 } 594 }
577 } 595 }
578 596
579 String encodingMimeType = toEncodingMimeType(mimeType); 597 String encodingMimeType = toEncodingMimeType(mimeType);
580 598
581 ImageData* imageData = toImageData(BackBuffer); 599 ImageData* imageData = toImageData(BackBuffer, exceptionState);
582 // imageData unref its data, which we still keep alive for the async toBlob thread 600 if (exceptionState.hadException())
601 return;
602
603 // ImageData unrefs its data, which we still keep alive for the async toBlob thread
583 ScopedDisposal<ImageData> disposer(imageData); 604 ScopedDisposal<ImageData> disposer(imageData);
584 605
585 // Add a ref to keep image data alive until completion of encoding 606 // Add a ref to keep image data alive until completion of encoding
586 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data()); 607 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data());
587 608
588 getToBlobThreadInstance()->taskRunner()->postTask(BLINK_FROM_HERE, new Task( threadSafeBind(&HTMLCanvasElement::encodeImageAsync, AllowCrossThreadAccess(imag eDataRef.release().leakRef()), imageData->size(), AllowCrossThreadAccess(callbac k), encodingMimeType, quality))); 609 getToBlobThreadInstance()->taskRunner()->postTask(BLINK_FROM_HERE, new Task( threadSafeBind(&HTMLCanvasElement::encodeImageAsync, AllowCrossThreadAccess(imag eDataRef.release().leakRef()), imageData->size(), AllowCrossThreadAccess(callbac k), encodingMimeType, quality)));
589 } 610 }
590 611
591 SecurityOrigin* HTMLCanvasElement::securityOrigin() const 612 SecurityOrigin* HTMLCanvasElement::securityOrigin() const
592 { 613 {
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 { 964 {
944 return FloatSize(width(), height()); 965 return FloatSize(width(), height());
945 } 966 }
946 967
947 bool HTMLCanvasElement::isOpaque() const 968 bool HTMLCanvasElement::isOpaque() const
948 { 969 {
949 return m_context && !m_context->hasAlpha(); 970 return m_context && !m_context->hasAlpha();
950 } 971 }
951 972
952 } // blink 973 } // blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698