Index: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
index 562b71804a99ec8c68e101b0b88e245be86b8542..6d1eff20d0ca5ba303079d7c23f4d0be79022061 100644 |
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
@@ -275,17 +275,13 @@ void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(const double& quality) { |
NOTREACHED(); |
} |
- // TODO: Enforce OffscreenCanvas.convertToBlob to finish within deadline. |
- // See crbug.com/657102. |
- if (m_functionType == HTMLCanvasToBlobCallback) { |
- // We post the below task to check if the above idle task isn't late. |
- // There's no risk of concurrency as both tasks are on main thread. |
- this->postDelayedTaskToMainThread( |
- BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent, |
- wrapPersistent(this), quality), |
- IdleTaskStartTimeoutDelay); |
- } |
+ // We post the below task to check if the above idle task isn't late. |
+ // There's no risk of concurrency as both tasks are on the same thread. |
+ this->postDelayedTaskToCurrentThread( |
+ BLINK_FROM_HERE, |
+ WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent, |
+ wrapPersistent(this), quality), |
+ IdleTaskStartTimeoutDelay); |
} |
} |
@@ -412,7 +408,7 @@ void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) { |
} |
} |
-void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() { |
+void CanvasAsyncBlobCreator::forceEncodeRowsPngOnCurrentThread() { |
DCHECK(m_idleTaskStatus == IdleTaskSwitchedToImmediateTask); |
// Continue encoding from the last completed row |
@@ -423,20 +419,39 @@ void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() { |
inputPixels += m_pixelRowStride; |
} |
PNGImageEncoder::finalizePng(m_pngEncoderState.get()); |
- this->createBlobAndReturnResult(); |
+ |
+ if (isMainThread()) { |
+ this->createBlobAndReturnResult(); |
+ } else { |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask( |
+ BLINK_FROM_HERE, |
+ crossThreadBind(&CanvasAsyncBlobCreator::createBlobAndReturnResult, |
+ wrapCrossThreadPersistent(this))); |
+ } |
this->signalAlternativeCodePathFinishedForTesting(); |
} |
-void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() { |
+void CanvasAsyncBlobCreator::forceEncodeRowsJpegOnCurrentThread() { |
DCHECK(m_idleTaskStatus == IdleTaskSwitchedToImmediateTask); |
// Continue encoding from the last completed row |
+ void (CanvasAsyncBlobCreator::*functionToBeCalled)(void); |
if (JPEGImageEncoder::encodeWithPreInitializedState( |
std::move(m_jpegEncoderState), m_data->data(), m_numRowsCompleted)) { |
- this->createBlobAndReturnResult(); |
+ functionToBeCalled = &CanvasAsyncBlobCreator::createBlobAndReturnResult; |
} else { |
- this->createNullAndReturnResult(); |
+ functionToBeCalled = &CanvasAsyncBlobCreator::createNullAndReturnResult; |
+ } |
+ |
+ if (isMainThread()) { |
+ (this->*functionToBeCalled)(); |
+ } else { |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask(BLINK_FROM_HERE, |
+ crossThreadBind(functionToBeCalled, |
+ wrapCrossThreadPersistent(this))); |
} |
this->signalAlternativeCodePathFinishedForTesting(); |
@@ -523,7 +538,7 @@ bool CanvasAsyncBlobCreator::initializeJpegStruct(double quality) { |
void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) { |
if (m_idleTaskStatus == IdleTaskStarted) { |
// Even if the task started quickly, we still want to ensure completion |
- this->postDelayedTaskToMainThread( |
+ this->postDelayedTaskToCurrentThread( |
BLINK_FROM_HERE, |
WTF::bind(&CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent, |
wrapPersistent(this)), |
@@ -540,8 +555,9 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, |
- wrapPersistent(this))); |
+ WTF::bind( |
+ &CanvasAsyncBlobCreator::forceEncodeRowsPngOnCurrentThread, |
+ wrapPersistent(this))); |
} else { |
// Failing in initialization of png struct |
this->signalAlternativeCodePathFinishedForTesting(); |
@@ -552,8 +568,9 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, |
- wrapPersistent(this))); |
+ WTF::bind( |
+ &CanvasAsyncBlobCreator::forceEncodeRowsJpegOnCurrentThread, |
+ wrapPersistent(this))); |
} else { |
// Failing in initialization of jpeg struct |
this->signalAlternativeCodePathFinishedForTesting(); |
@@ -578,15 +595,17 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, |
- wrapPersistent(this))); |
+ WTF::bind( |
+ &CanvasAsyncBlobCreator::forceEncodeRowsPngOnCurrentThread, |
+ wrapPersistent(this))); |
} else { |
DCHECK(m_mimeType == MimeTypeJpeg); |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, |
- wrapPersistent(this))); |
+ WTF::bind( |
+ &CanvasAsyncBlobCreator::forceEncodeRowsJpegOnCurrentThread, |
+ wrapPersistent(this))); |
} |
} else { |
DCHECK(m_idleTaskStatus == IdleTaskFailed || |
@@ -595,11 +614,10 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { |
} |
} |
-void CanvasAsyncBlobCreator::postDelayedTaskToMainThread( |
+void CanvasAsyncBlobCreator::postDelayedTaskToCurrentThread( |
const WebTraceLocation& location, |
std::unique_ptr<WTF::Closure> task, |
double delayMs) { |
- DCHECK(isMainThread()); |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postDelayedTask(location, std::move(task), delayMs); |
} |