Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/html/canvas/CanvasAsyncBlobCreator.h" | 5 #include "core/html/canvas/CanvasAsyncBlobCreator.h" |
| 6 | 6 |
| 7 #include "core/fileapi/Blob.h" | 7 #include "core/fileapi/Blob.h" |
| 8 #include "platform/Histogram.h" | |
| 8 #include "platform/ThreadSafeFunctional.h" | 9 #include "platform/ThreadSafeFunctional.h" |
| 9 #include "platform/graphics/ImageBuffer.h" | 10 #include "platform/graphics/ImageBuffer.h" |
| 10 #include "platform/image-encoders/JPEGImageEncoder.h" | 11 #include "platform/image-encoders/JPEGImageEncoder.h" |
| 11 #include "platform/image-encoders/PNGImageEncoder.h" | 12 #include "platform/image-encoders/PNGImageEncoder.h" |
| 12 #include "platform/threading/BackgroundTaskRunner.h" | 13 #include "platform/threading/BackgroundTaskRunner.h" |
| 13 #include "public/platform/Platform.h" | 14 #include "public/platform/Platform.h" |
| 14 #include "public/platform/WebScheduler.h" | 15 #include "public/platform/WebScheduler.h" |
| 15 #include "public/platform/WebTaskRunner.h" | 16 #include "public/platform/WebTaskRunner.h" |
| 16 #include "public/platform/WebThread.h" | 17 #include "public/platform/WebThread.h" |
| 17 #include "public/platform/WebTraceLocation.h" | 18 #include "public/platform/WebTraceLocation.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 } else if (mimeType == "image/webp") { | 73 } else if (mimeType == "image/webp") { |
| 73 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp; | 74 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp; |
| 74 } else { | 75 } else { |
| 75 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported; | 76 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported; |
| 76 } | 77 } |
| 77 return mimeTypeEnum; | 78 return mimeTypeEnum; |
| 78 } | 79 } |
| 79 | 80 |
| 80 } // anonymous namespace | 81 } // anonymous namespace |
| 81 | 82 |
| 82 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unp remultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCall back* callback) | 83 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unp remultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCall back* callback, double startTime) |
| 83 { | 84 { |
| 84 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeT ypeStringToEnum(mimeType), size, callback); | 85 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeT ypeStringToEnum(mimeType), size, callback, startTime); |
| 85 } | 86 } |
| 86 | 87 |
| 87 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeT ype mimeType, const IntSize& size, BlobCallback* callback) | 88 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeT ype mimeType, const IntSize& size, BlobCallback* callback, double startTime) |
| 88 : m_data(data) | 89 : m_data(data) |
| 89 , m_size(size) | 90 , m_size(size) |
| 90 , m_mimeType(mimeType) | 91 , m_mimeType(mimeType) |
| 91 , m_callback(callback) | 92 , m_callback(callback) |
| 93 , m_startTime(startTime) | |
| 92 { | 94 { |
| 93 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4)); | 95 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4)); |
| 94 m_encodedImage = wrapUnique(new Vector<unsigned char>()); | 96 m_encodedImage = wrapUnique(new Vector<unsigned char>()); |
| 95 m_pixelRowStride = size.width() * NumChannelsPng; | 97 m_pixelRowStride = size.width() * NumChannelsPng; |
| 96 m_idleTaskStatus = IdleTaskNotSupported; | 98 m_idleTaskStatus = IdleTaskNotSupported; |
| 97 m_numRowsCompleted = 0; | 99 m_numRowsCompleted = 0; |
| 98 } | 100 } |
| 99 | 101 |
| 100 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() | 102 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() |
| 101 { | 103 { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 129 // There's no risk of concurrency as both tasks are on main thread. | 131 // There's no risk of concurrency as both tasks are on main thread. |
| 130 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay); | 132 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay); |
| 131 } else if (m_mimeType == MimeTypeWebp) { | 133 } else if (m_mimeType == MimeTypeWebp) { |
| 132 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa sk : BackgroundTaskRunner::TaskSizeShortRunningTask; | 134 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa sk : BackgroundTaskRunner::TaskSizeShortRunningTask; |
| 133 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist ent(this), quality), taskSize); | 135 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist ent(this), quality), taskSize); |
| 134 } | 136 } |
| 135 } | 137 } |
| 136 | 138 |
| 137 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality) | 139 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality) |
| 138 { | 140 { |
| 141 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); | |
| 139 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); | 142 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); |
| 140 } | 143 } |
| 141 | 144 |
| 142 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double deadlineSeconds) | 145 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double deadlineSeconds) |
| 143 { | 146 { |
| 144 ASSERT(isMainThread()); | 147 ASSERT(isMainThread()); |
| 148 m_initiateStartTime = WTF::monotonicallyIncreasingTime(); | |
| 149 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGInitiateEncodingCounter, ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50)); | |
| 150 toBlobJPEGInitiateEncodingCounter.count((m_initiateStartTime - m_scheduleIni tiateStartTime) * 1000000.0); | |
| 145 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { | 151 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
| 146 return; | 152 return; |
| 147 } | 153 } |
| 148 | 154 |
| 149 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); | 155 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
| 150 m_idleTaskStatus = IdleTaskStarted; | 156 m_idleTaskStatus = IdleTaskStarted; |
| 151 | 157 |
| 152 if (!initializeJpegStruct(quality)) { | 158 if (!initializeJpegStruct(quality)) { |
| 153 m_idleTaskStatus = IdleTaskFailed; | 159 m_idleTaskStatus = IdleTaskFailed; |
| 154 return; | 160 return; |
| 155 } | 161 } |
| 156 this->idleEncodeRowsJpeg(deadlineSeconds); | 162 this->idleEncodeRowsJpeg(deadlineSeconds); |
| 157 } | 163 } |
| 158 | 164 |
| 159 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() | 165 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() |
| 160 { | 166 { |
| 167 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); | |
| 161 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); | 168 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); |
| 162 } | 169 } |
| 163 | 170 |
| 164 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) | 171 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) |
| 165 { | 172 { |
| 166 ASSERT(isMainThread()); | 173 ASSERT(isMainThread()); |
| 174 m_initiateStartTime = WTF::monotonicallyIncreasingTime(); | |
| 175 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGInitiateEncodingCounter, ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50)); | |
| 176 toBlobPNGInitiateEncodingCounter.count((m_initiateStartTime - m_scheduleInit iateStartTime) * 1000000.0); | |
| 167 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { | 177 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
| 168 return; | 178 return; |
| 169 } | 179 } |
| 170 | 180 |
| 171 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); | 181 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
| 172 m_idleTaskStatus = IdleTaskStarted; | 182 m_idleTaskStatus = IdleTaskStarted; |
| 173 | 183 |
| 174 if (!initializePngStruct()) { | 184 if (!initializePngStruct()) { |
| 175 m_idleTaskStatus = IdleTaskFailed; | 185 m_idleTaskStatus = IdleTaskFailed; |
| 176 return; | 186 return; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 194 } | 204 } |
| 195 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get()); | 205 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get()); |
| 196 inputPixels += m_pixelRowStride; | 206 inputPixels += m_pixelRowStride; |
| 197 } | 207 } |
| 198 m_numRowsCompleted = m_size.height(); | 208 m_numRowsCompleted = m_size.height(); |
| 199 PNGImageEncoder::finalizePng(m_pngEncoderState.get()); | 209 PNGImageEncoder::finalizePng(m_pngEncoderState.get()); |
| 200 | 210 |
| 201 m_idleTaskStatus = IdleTaskCompleted; | 211 m_idleTaskStatus = IdleTaskCompleted; |
| 202 | 212 |
| 203 if (isDeadlineNearOrPassed(deadlineSeconds)) { | 213 if (isDeadlineNearOrPassed(deadlineSeconds)) { |
| 214 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - m_initiateStartTi me); | |
|
Justin Novosad
2016/06/22 14:38:57
At each Idle slice, you are adding the time since
xidachen
2016/06/22 15:40:41
The new patch should have that fixed.
| |
| 204 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR OM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); | 215 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR OM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); |
| 205 } else { | 216 } else { |
| 217 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGIdleEncodeCounter, (" Blink.Canvas.ToBlob.IdleEncodeDuration.PNG", 0, 10000000, 50)); | |
| 218 toBlobPNGIdleEncodeCounter.count(m_elapsedTime * 1000000.0); | |
| 206 this->createBlobAndInvokeCallback(); | 219 this->createBlobAndInvokeCallback(); |
| 207 } | 220 } |
| 208 } | 221 } |
| 209 | 222 |
| 210 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) | 223 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) |
| 211 { | 224 { |
| 212 ASSERT(isMainThread()); | 225 ASSERT(isMainThread()); |
| 213 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { | 226 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
| 214 return; | 227 return; |
| 215 } | 228 } |
| 216 | 229 |
| 217 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper(m_jpe gEncoderState.get(), m_data->data(), m_numRowsCompleted, SlackBeforeDeadline, de adlineSeconds); | 230 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper(m_jpe gEncoderState.get(), m_data->data(), m_numRowsCompleted, SlackBeforeDeadline, de adlineSeconds); |
| 218 if (m_numRowsCompleted == m_size.height()) { | 231 if (m_numRowsCompleted == m_size.height()) { |
| 219 m_idleTaskStatus = IdleTaskCompleted; | 232 m_idleTaskStatus = IdleTaskCompleted; |
| 220 if (isDeadlineNearOrPassed(deadlineSeconds)) { | 233 if (isDeadlineNearOrPassed(deadlineSeconds)) { |
| 234 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - m_initiateSta rtTime); | |
|
Justin Novosad
2016/06/22 14:38:57
Not correct.
| |
| 221 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLIN K_FROM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); | 235 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLIN K_FROM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); |
| 222 } else { | 236 } else { |
| 237 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGIdleEncodeCounte r, ("Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50)); | |
| 238 toBlobJPEGIdleEncodeCounter.count(m_elapsedTime * 1000000.0); | |
| 223 this->createBlobAndInvokeCallback(); | 239 this->createBlobAndInvokeCallback(); |
| 224 } | 240 } |
| 225 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) { | 241 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) { |
| 226 m_idleTaskStatus = IdleTaskFailed; | 242 m_idleTaskStatus = IdleTaskFailed; |
| 227 this->createNullAndInvokeCallback(); | 243 this->createNullAndInvokeCallback(); |
| 228 } else { | 244 } else { |
| 229 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FR OM_HERE, bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg, this)); | 245 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FR OM_HERE, bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg, this)); |
| 230 } | 246 } |
| 231 } | 247 } |
| 232 | 248 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 256 } else { | 272 } else { |
| 257 this->createNullAndInvokeCallback(); | 273 this->createNullAndInvokeCallback(); |
| 258 } | 274 } |
| 259 | 275 |
| 260 this->signalAlternativeCodePathFinishedForTesting(); | 276 this->signalAlternativeCodePathFinishedForTesting(); |
| 261 } | 277 } |
| 262 | 278 |
| 263 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() | 279 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() |
| 264 { | 280 { |
| 265 ASSERT(isMainThread()); | 281 ASSERT(isMainThread()); |
| 282 DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus, ("Blink.Canv as.ToBlob.IdleTaskStatus", IdleTaskNotSupported)); | |
|
xidachen
2016/06/22 14:01:25
xlai@: you are correct. I change the enum histogra
| |
| 283 toBlobIdleTaskStatus.count(m_idleTaskStatus); | |
| 284 | |
| 285 double elapsedTime = WTF::monotonicallyIncreasingTime() - m_startTime; | |
| 286 if (m_mimeType == MimeTypePng) { | |
| 287 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGCounter, ("Blink.Canv as.ToBlobDuration.PNG", 0, 10000000, 50)); | |
| 288 toBlobPNGCounter.count(elapsedTime * 1000000.0); | |
| 289 } else if (m_mimeType == MimeTypeJpeg) { | |
| 290 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGCounter, ("Blink.Can vas.ToBlobDuration.JPEG", 0, 10000000, 50)); | |
| 291 toBlobJPEGCounter.count(elapsedTime * 1000000.0); | |
| 292 } else { | |
| 293 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobWEBPCounter, ("Blink.Can vas.ToBlobDuration.WEBP", 0, 10000000, 50)); | |
| 294 toBlobWEBPCounter.count(elapsedTime * 1000000.0); | |
| 295 } | |
| 266 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size (), convertMimeTypeEnumToString(m_mimeType)); | 296 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size (), convertMimeTypeEnumToString(m_mimeType)); |
| 267 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob)); | 297 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob)); |
| 268 // Avoid unwanted retention, see dispose(). | 298 // Avoid unwanted retention, see dispose(). |
| 269 dispose(); | 299 dispose(); |
| 270 } | 300 } |
| 271 | 301 |
| 272 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() | 302 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() |
| 273 { | 303 { |
| 274 ASSERT(isMainThread()); | 304 ASSERT(isMainThread()); |
| 275 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); | 305 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 Platform::current()->mainThread()->getWebTaskRunner()->postTask( BLINK_FROM_HERE, bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, this) ); | 365 Platform::current()->mainThread()->getWebTaskRunner()->postTask( BLINK_FROM_HERE, bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, this) ); |
| 336 } else { | 366 } else { |
| 337 // Failing in initialization of jpeg struct | 367 // Failing in initialization of jpeg struct |
| 338 this->signalAlternativeCodePathFinishedForTesting(); | 368 this->signalAlternativeCodePathFinishedForTesting(); |
| 339 } | 369 } |
| 340 } | 370 } |
| 341 } else { | 371 } else { |
| 342 ASSERT(m_idleTaskStatus == IdleTaskFailed || m_idleTaskStatus == IdleTas kCompleted); | 372 ASSERT(m_idleTaskStatus == IdleTaskFailed || m_idleTaskStatus == IdleTas kCompleted); |
| 343 this->signalAlternativeCodePathFinishedForTesting(); | 373 this->signalAlternativeCodePathFinishedForTesting(); |
| 344 } | 374 } |
| 345 | |
| 346 } | 375 } |
| 347 | 376 |
| 348 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() | 377 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() |
| 349 { | 378 { |
| 350 ASSERT(m_idleTaskStatus != IdleTaskNotStarted); | 379 ASSERT(m_idleTaskStatus != IdleTaskNotStarted); |
| 351 | 380 |
| 352 if (m_idleTaskStatus == IdleTaskStarted) { | 381 if (m_idleTaskStatus == IdleTaskStarted) { |
| 353 // It has taken too long to complete for the idle task. | 382 // It has taken too long to complete for the idle task. |
| 354 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask; | 383 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask; |
| 355 signalTaskSwitchInCompleteTimeoutEventForTesting(); | 384 signalTaskSwitchInCompleteTimeoutEventForTesting(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 366 } | 395 } |
| 367 } | 396 } |
| 368 | 397 |
| 369 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation& location, std::unique_ptr<SameThreadClosure> task, double delayMs) | 398 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation& location, std::unique_ptr<SameThreadClosure> task, double delayMs) |
| 370 { | 399 { |
| 371 DCHECK(isMainThread()); | 400 DCHECK(isMainThread()); |
| 372 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat ion, std::move(task), delayMs); | 401 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat ion, std::move(task), delayMs); |
| 373 } | 402 } |
| 374 | 403 |
| 375 } // namespace blink | 404 } // namespace blink |
| OLD | NEW |