Commit d59edfa8 authored by Reilly Grant's avatar Reilly Grant Committed by Commit Bot

Attach BarcodeDetectionProviderPtr to an ExecutionContext supplement

This change creates a new class, BarcodeDetectorStatics, which owns the
connection to BarcodeDetectionProvider. This allows it to implement the
static methods on BarcodeDetector such as getSupportedFormats() without
needing to create an instance of BarcodeDetector.

This fixes an issue where getSupportedFormats() would reject when
BarcodeDetection is unimplemented even if a successful connection to
BarcodeDetectionProvider is made. It also avoids recreating the
provider connection for every new BarcodeDetector.

Bug: 983910
Change-Id: I7c7ea7df84f68bbed9b2bfc600852e4f4e5356cc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1706893
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Ovidio de Jesús Ruiz-Henríquez <odejesush@chromium.org>
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarOvidio de Jesús Ruiz-Henríquez <odejesush@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680560}
parent 814ff679
...@@ -8,6 +8,8 @@ blink_modules_sources("shapedetection") { ...@@ -8,6 +8,8 @@ blink_modules_sources("shapedetection") {
sources = [ sources = [
"barcode_detector.cc", "barcode_detector.cc",
"barcode_detector.h", "barcode_detector.h",
"barcode_detector_statics.cc",
"barcode_detector_statics.h",
"detected_barcode.cc", "detected_barcode.cc",
"detected_barcode.h", "detected_barcode.h",
"detected_face.cc", "detected_face.cc",
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <utility> #include <utility>
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h"
...@@ -15,6 +13,7 @@ ...@@ -15,6 +13,7 @@
#include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/imagecapture/point_2d.h" #include "third_party/blink/renderer/modules/imagecapture/point_2d.h"
#include "third_party/blink/renderer/modules/shapedetection/barcode_detector_options.h" #include "third_party/blink/renderer/modules/shapedetection/barcode_detector_options.h"
#include "third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_barcode.h" #include "third_party/blink/renderer/modules/shapedetection/detected_barcode.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
...@@ -86,70 +85,33 @@ BarcodeDetector::BarcodeDetector(ExecutionContext* context, ...@@ -86,70 +85,33 @@ BarcodeDetector::BarcodeDetector(ExecutionContext* context,
// See https://bit.ly/2S0zRAS for task types. // See https://bit.ly/2S0zRAS for task types.
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI); auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
auto request = mojo::MakeRequest(&barcode_provider_, task_runner);
if (auto* interface_provider = context->GetInterfaceProvider()) {
interface_provider->GetInterface(std::move(request));
}
barcode_provider_->CreateBarcodeDetection( BarcodeDetectorStatics::From(context)->CreateBarcodeDetection(
mojo::MakeRequest(&barcode_service_, task_runner), mojo::MakeRequest(&service_, task_runner),
std::move(barcode_detector_options)); std::move(barcode_detector_options));
service_.set_connection_error_handler(
barcode_service_.set_connection_error_handler( WTF::Bind(&BarcodeDetector::OnConnectionError, WrapWeakPersistent(this)));
WTF::Bind(&BarcodeDetector::OnBarcodeServiceConnectionError,
WrapWeakPersistent(this)));
} }
ScriptPromise BarcodeDetector::getSupportedFormats(ScriptState* script_state) { ScriptPromise BarcodeDetector::getSupportedFormats(ScriptState* script_state) {
ExecutionContext* context = ExecutionContext::From(script_state); ExecutionContext* context = ExecutionContext::From(script_state);
NonThrowableExceptionState exception_state; return BarcodeDetectorStatics::From(context)->EnumerateSupportedFormats(
BarcodeDetector* detector = BarcodeDetector::Create( script_state);
context, BarcodeDetectorOptions::Create(), exception_state);
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
if (!detector->barcode_service_) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError,
"Barcode detection service unavailable."));
return promise;
}
detector->barcode_service_requests_.insert(resolver);
detector->barcode_provider_->EnumerateSupportedFormats(
WTF::Bind(&BarcodeDetector::OnEnumerateSupportedFormats,
WrapPersistent(detector), WrapPersistent(resolver)));
return promise;
}
void BarcodeDetector::OnEnumerateSupportedFormats(
ScriptPromiseResolver* resolver,
const Vector<shape_detection::mojom::blink::BarcodeFormat>&
format_results) {
DCHECK(barcode_service_requests_.Contains(resolver));
barcode_service_requests_.erase(resolver);
Vector<WTF::String> formats;
formats.ReserveInitialCapacity(format_results.size());
for (const auto& format : format_results)
formats.push_back(DetectedBarcode::BarcodeFormatToString(format));
resolver->Resolve(formats);
} }
ScriptPromise BarcodeDetector::DoDetect(ScriptPromiseResolver* resolver, ScriptPromise BarcodeDetector::DoDetect(ScriptPromiseResolver* resolver,
SkBitmap bitmap) { SkBitmap bitmap) {
ScriptPromise promise = resolver->Promise(); ScriptPromise promise = resolver->Promise();
if (!barcode_service_) { if (!service_) {
resolver->Reject(MakeGarbageCollected<DOMException>( resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, DOMExceptionCode::kNotSupportedError,
"Barcode detection service unavailable.")); "Barcode detection service unavailable."));
return promise; return promise;
} }
barcode_service_requests_.insert(resolver); detect_requests_.insert(resolver);
barcode_service_->Detect( service_->Detect(std::move(bitmap),
std::move(bitmap), WTF::Bind(&BarcodeDetector::OnDetectBarcodes,
WTF::Bind(&BarcodeDetector::OnDetectBarcodes, WrapPersistent(this), WrapPersistent(this), WrapPersistent(resolver)));
WrapPersistent(resolver)));
return promise; return promise;
} }
...@@ -157,8 +119,8 @@ void BarcodeDetector::OnDetectBarcodes( ...@@ -157,8 +119,8 @@ void BarcodeDetector::OnDetectBarcodes(
ScriptPromiseResolver* resolver, ScriptPromiseResolver* resolver,
Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr> Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr>
barcode_detection_results) { barcode_detection_results) {
DCHECK(barcode_service_requests_.Contains(resolver)); DCHECK(detect_requests_.Contains(resolver));
barcode_service_requests_.erase(resolver); detect_requests_.erase(resolver);
HeapVector<Member<DetectedBarcode>> detected_barcodes; HeapVector<Member<DetectedBarcode>> detected_barcodes;
for (const auto& barcode : barcode_detection_results) { for (const auto& barcode : barcode_detection_results) {
...@@ -180,20 +142,21 @@ void BarcodeDetector::OnDetectBarcodes( ...@@ -180,20 +142,21 @@ void BarcodeDetector::OnDetectBarcodes(
resolver->Resolve(detected_barcodes); resolver->Resolve(detected_barcodes);
} }
void BarcodeDetector::OnBarcodeServiceConnectionError() { void BarcodeDetector::OnConnectionError() {
for (const auto& request : barcode_service_requests_) { service_.reset();
request->Reject(MakeGarbageCollected<DOMException>(
HeapHashSet<Member<ScriptPromiseResolver>> resolvers;
resolvers.swap(detect_requests_);
for (const auto& resolver : resolvers) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, DOMExceptionCode::kNotSupportedError,
"Barcode Detection not implemented.")); "Barcode Detection not implemented."));
} }
barcode_service_requests_.clear();
barcode_service_.reset();
barcode_provider_.reset();
} }
void BarcodeDetector::Trace(blink::Visitor* visitor) { void BarcodeDetector::Trace(blink::Visitor* visitor) {
ShapeDetector::Trace(visitor); ShapeDetector::Trace(visitor);
visitor->Trace(barcode_service_requests_); visitor->Trace(detect_requests_);
} }
} // namespace blink } // namespace blink
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_H_
#include "services/shape_detection/public/mojom/barcodedetection.mojom-blink.h" #include "services/shape_detection/public/mojom/barcodedetection.mojom-blink.h"
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h"
...@@ -38,21 +37,16 @@ class MODULES_EXPORT BarcodeDetector final : public ShapeDetector { ...@@ -38,21 +37,16 @@ class MODULES_EXPORT BarcodeDetector final : public ShapeDetector {
private: private:
~BarcodeDetector() override = default; ~BarcodeDetector() override = default;
void OnEnumerateSupportedFormats(
ScriptPromiseResolver*,
const Vector<shape_detection::mojom::blink::BarcodeFormat>&);
ScriptPromise DoDetect(ScriptPromiseResolver*, SkBitmap) override; ScriptPromise DoDetect(ScriptPromiseResolver*, SkBitmap) override;
void OnDetectBarcodes( void OnDetectBarcodes(
ScriptPromiseResolver*, ScriptPromiseResolver*,
Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr>); Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr>);
void OnBarcodeServiceConnectionError(); void OnConnectionError();
shape_detection::mojom::blink::BarcodeDetectionPtr barcode_service_; shape_detection::mojom::blink::BarcodeDetectionPtr service_;
shape_detection::mojom::blink::BarcodeDetectionProviderPtr barcode_provider_;
HeapHashSet<Member<ScriptPromiseResolver>> barcode_service_requests_; HeapHashSet<Member<ScriptPromiseResolver>> detect_requests_;
}; };
} // namespace blink } // namespace blink
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_barcode.h"
namespace blink {
// static
const char BarcodeDetectorStatics::kSupplementName[] = "BarcodeDetectorStatics";
// static
BarcodeDetectorStatics* BarcodeDetectorStatics::From(
ExecutionContext* document) {
DCHECK(document);
BarcodeDetectorStatics* statics =
Supplement<ExecutionContext>::From<BarcodeDetectorStatics>(*document);
if (!statics) {
statics = MakeGarbageCollected<BarcodeDetectorStatics>(*document);
Supplement<ExecutionContext>::ProvideTo(*document, statics);
}
return statics;
}
BarcodeDetectorStatics::BarcodeDetectorStatics(ExecutionContext& document)
: Supplement<ExecutionContext>(document) {}
BarcodeDetectorStatics::~BarcodeDetectorStatics() = default;
void BarcodeDetectorStatics::CreateBarcodeDetection(
shape_detection::mojom::blink::BarcodeDetectionRequest request,
shape_detection::mojom::blink::BarcodeDetectorOptionsPtr options) {
EnsureServiceConnection();
service_->CreateBarcodeDetection(std::move(request), std::move(options));
}
ScriptPromise BarcodeDetectorStatics::EnumerateSupportedFormats(
ScriptState* script_state) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
get_supported_format_requests_.insert(resolver);
EnsureServiceConnection();
service_->EnumerateSupportedFormats(
WTF::Bind(&BarcodeDetectorStatics::OnEnumerateSupportedFormats,
WrapPersistent(this), WrapPersistent(resolver)));
return promise;
}
void BarcodeDetectorStatics::Trace(Visitor* visitor) {
Supplement<ExecutionContext>::Trace(visitor);
visitor->Trace(get_supported_format_requests_);
}
void BarcodeDetectorStatics::EnsureServiceConnection() {
if (service_)
return;
ExecutionContext* context = GetSupplementable();
// See https://bit.ly/2S0zRAS for task types.
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
auto request = mojo::MakeRequest(&service_, task_runner);
context->GetInterfaceProvider()->GetInterface(std::move(request));
service_.set_connection_error_handler(WTF::Bind(
&BarcodeDetectorStatics::OnConnectionError, WrapWeakPersistent(this)));
}
void BarcodeDetectorStatics::OnEnumerateSupportedFormats(
ScriptPromiseResolver* resolver,
const Vector<shape_detection::mojom::blink::BarcodeFormat>& formats) {
DCHECK(get_supported_format_requests_.Contains(resolver));
get_supported_format_requests_.erase(resolver);
Vector<WTF::String> results;
results.ReserveInitialCapacity(results.size());
for (const auto& format : formats)
results.push_back(DetectedBarcode::BarcodeFormatToString(format));
resolver->Resolve(results);
}
void BarcodeDetectorStatics::OnConnectionError() {
service_.reset();
HeapHashSet<Member<ScriptPromiseResolver>> resolvers;
resolvers.swap(get_supported_format_requests_);
for (const auto& resolver : resolvers) {
// Return an empty list to indicate that no barcode formats are supported
// since this connection failure indicates barcode detection is, in general,
// not supported by the platform.
resolver->Resolve(Vector<String>());
}
}
} // namespace blink
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_STATICS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_STATICS_H_
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
class ExecutionContext;
class ScriptPromiseResolver;
// This class owns the BarcodeDetectionProvider connection used to create the
// BarcodeDetector instances for this ExecutionContext.
class BarcodeDetectorStatics final
: public GarbageCollectedFinalized<BarcodeDetectorStatics>,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(BarcodeDetectorStatics);
public:
static const char kSupplementName[];
static BarcodeDetectorStatics* From(ExecutionContext*);
explicit BarcodeDetectorStatics(ExecutionContext&);
~BarcodeDetectorStatics();
void CreateBarcodeDetection(
shape_detection::mojom::blink::BarcodeDetectionRequest,
shape_detection::mojom::blink::BarcodeDetectorOptionsPtr);
ScriptPromise EnumerateSupportedFormats(ScriptState*);
void Trace(Visitor*) override;
private:
void EnsureServiceConnection();
void OnEnumerateSupportedFormats(
ScriptPromiseResolver*,
const Vector<shape_detection::mojom::blink::BarcodeFormat>&);
void OnConnectionError();
shape_detection::mojom::blink::BarcodeDetectionProviderPtr service_;
// Holds Promises returned by EnumerateSupportedFormats() so that they can be
// resolve in the case of a Mojo connection error.
HeapHashSet<Member<ScriptPromiseResolver>> get_supported_format_requests_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_STATICS_H_
<!DOCTYPE html>
<link rel="help" href="https://wicg.github.io/shape-detection-api/#dom-barcodedetector-getsupportedformats">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/services/shape_detection/public/mojom/barcodedetection_provider.mojom.js"></script>
<script>
promise_test(async t => {
// Disable built-in support for barcode detection to test fallback handling.
const interceptor = new MojoInterfaceInterceptor(
shapeDetection.mojom.BarcodeDetectionProvider.name);
interceptor.oninterfacerequest = e => e.handle.close();
interceptor.start();
const result = await BarcodeDetector.getSupportedFormats();
assert_equals(result.length, 0, 'result.length');
interceptor.stop();
}, 'getSupportedFormats() resolves with empty list when unsupported');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment