| Index: third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
|
| diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
|
| index 9f7100f852d2c4b2cae09b6e5dcec0929f0eeca3..680983ace1a1558e1680320c1d6cb7e95d21329d 100644
|
| --- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
|
| +++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
|
| @@ -4,22 +4,130 @@
|
|
|
| #include "modules/shapedetection/FaceDetector.h"
|
|
|
| -#include "bindings/core/v8/ScriptPromiseResolver.h"
|
| #include "core/dom/DOMException.h"
|
| +#include "core/dom/DOMRect.h"
|
| +#include "core/dom/Document.h"
|
| +#include "core/fetch/ImageResource.h"
|
| +#include "core/frame/LocalFrame.h"
|
| +#include "core/html/HTMLImageElement.h"
|
| +#include "platform/graphics/Image.h"
|
| +#include "public/platform/InterfaceProvider.h"
|
| +#include "third_party/skia/include/core/SkImage.h"
|
| +#include "third_party/skia/include/core/SkImageInfo.h"
|
|
|
| namespace blink {
|
|
|
| -FaceDetector* FaceDetector::create()
|
| +namespace {
|
| +
|
| +mojo::ScopedSharedBufferHandle getSharedBufferHandle(const HTMLImageElement* img)
|
| +{
|
| + ImageResource* const imgResource = img->cachedImage();
|
| + if (!imgResource) {
|
| + DLOG(ERROR) << "Failed to convert HTMLImageElement to ImageSource.";
|
| + return mojo::ScopedSharedBufferHandle();
|
| + }
|
| +
|
| + Image* const blinkImage = imgResource->getImage();
|
| + if (!blinkImage) {
|
| + DLOG(ERROR) << "Failed to convert ImageSource to blink::Image.";
|
| + return mojo::ScopedSharedBufferHandle();
|
| + }
|
| +
|
| + const sk_sp<SkImage> skiaImg = blinkImage->imageForCurrentFrame();
|
| + DCHECK_EQ(img->naturalWidth(), skiaImg->width());
|
| + DCHECK_EQ(img->naturalHeight(), skiaImg->height());
|
| +
|
| + if (!skiaImg) {
|
| + DLOG(ERROR) << "Failed to convert blink::Image to sk_sp<SkImage>.";
|
| + return mojo::ScopedSharedBufferHandle();
|
| + }
|
| +
|
| + const SkImageInfo skiaInfo = SkImageInfo::MakeN32(skiaImg->width(), skiaImg->height(), skiaImg->alphaType());
|
| +
|
| + const uint32_t allocationSize = skiaInfo.getSafeSize(skiaInfo.minRowBytes());
|
| + mojo::ScopedSharedBufferHandle sharedBufferHandle = mojo::SharedBufferHandle::Create(allocationSize);
|
| + const mojo::ScopedSharedBufferMapping mappingPtr = sharedBufferHandle->Map(allocationSize);
|
| + DCHECK(mappingPtr);
|
| +
|
| + const SkPixmap pixmap(skiaInfo, mappingPtr.get(), skiaInfo.minRowBytes());
|
| + if (!skiaImg->readPixels(pixmap, 0, 0)) {
|
| + DLOG(ERROR) << "Failed to read pixels from sk_sp<SkImage>.";
|
| + return mojo::ScopedSharedBufferHandle();
|
| + }
|
| +
|
| + return sharedBufferHandle;
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +FaceDetector* FaceDetector::create(const Document& document)
|
| +{
|
| + return new FaceDetector(*document.frame());
|
| +}
|
| +
|
| +FaceDetector::FaceDetector(LocalFrame& frame)
|
| {
|
| - return new FaceDetector();
|
| + DCHECK(!m_service.is_bound());
|
| + DCHECK(frame.interfaceProvider());
|
| + frame.interfaceProvider()->getInterface(mojo::GetProxy(&m_service));
|
| }
|
|
|
| -ScriptPromise FaceDetector::detect(ScriptState* scriptState, const HTMLImageElement* image)
|
| +ScriptPromise FaceDetector::detect(ScriptState* scriptState, const HTMLImageElement* img)
|
| {
|
| ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| ScriptPromise promise = resolver->promise();
|
| - resolver->reject(DOMException::create(NotSupportedError, "Not implemented"));
|
| +
|
| + if (!m_service) {
|
| + resolver->reject(DOMException::create(NotFoundError, "Face detection service unavailable."));
|
| + return promise;
|
| + }
|
| +
|
| + if (!img) {
|
| + resolver->reject(DOMException::create(SyntaxError, "The provided HTMLImageElement is empty."));
|
| + return promise;
|
| + }
|
| +
|
| + // TODO(xianglu): Add security check when the spec is ready. https://crbug.com/646083
|
| + mojo::ScopedSharedBufferHandle sharedBufferHandle = getSharedBufferHandle(img);
|
| + if (!sharedBufferHandle->is_valid()) {
|
| + resolver->reject(DOMException::create(SyntaxError, "Failed to get sharedBufferHandle."));
|
| + return promise;
|
| + }
|
| +
|
| + m_serviceRequests.add(resolver);
|
| + DCHECK(m_service.is_bound());
|
| + m_service->DetectFace(
|
| + std::move(sharedBufferHandle),
|
| + img->naturalWidth(),
|
| + img->naturalHeight(),
|
| + convertToBaseCallback(WTF::bind(&FaceDetector::onDetectFace, wrapPersistent(this), wrapPersistent(resolver)))
|
| + );
|
| + sharedBufferHandle.reset();
|
| return promise;
|
| }
|
|
|
| +
|
| +void FaceDetector::onDetectFace(ScriptPromiseResolver* resolver, mojo::WTFArray<mojom::blink::BoundingBoxPtr> boundingBoxes)
|
| +{
|
| + if (!m_serviceRequests.contains(resolver))
|
| + return;
|
| +
|
| + HeapVector<Member<DOMRect>> detectedFaces;
|
| + for (size_t i = 0; i < boundingBoxes.size(); i++) {
|
| + detectedFaces.append(DOMRect::create(
|
| + boundingBoxes.at(i)->x,
|
| + boundingBoxes.at(i)->y,
|
| + boundingBoxes.at(i)->width,
|
| + boundingBoxes.at(i)->height));
|
| + }
|
| +
|
| + resolver->resolve(detectedFaces);
|
| + m_serviceRequests.remove(resolver);
|
| +}
|
| +
|
| +DEFINE_TRACE(FaceDetector)
|
| +{
|
| + visitor->trace(m_serviceRequests);
|
| +}
|
| +
|
| } // namespace blink
|
|
|