#ifndef CONTENT_RENDERER_ACCESSIBILITY_ANNOTATIONS_AX_IMAGE_ANNOTATOR_H_
#define CONTENT_RENDERER_ACCESSIBILITY_ANNOTATIONS_AX_IMAGE_ANNOTATOR_H_
#include <optional>
#include <string>
#include <unordered_map>
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list_types.h"
#include "content/common/content_export.h"
#include "content/renderer/accessibility/annotations/ax_annotator.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/image_annotation/public/cpp/image_processor.h"
#include "services/image_annotation/public/mojom/image_annotation.mojom-forward.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/ax_enums.mojom.h"
namespace blink {
class WebAXObject;
class WebDocument;
}
namespace content {
class ContentClient;
class CONTENT_EXPORT AXImageAnnotator : public AXAnnotator,
public base::CheckedObserver {
public:
explicit AXImageAnnotator(
RenderAccessibilityImpl* const render_accessibility);
AXImageAnnotator(const AXImageAnnotator&) = delete;
AXImageAnnotator& operator=(const AXImageAnnotator&) = delete;
~AXImageAnnotator() override;
void Annotate(const blink::WebDocument& document,
ui::AXTreeUpdate* update,
bool load_complete) override;
void EnableAnnotations() override;
void CancelAnnotations() override;
uint32_t GetAXModeToEnableAnnotations() override;
bool HasAXActionToEnableAnnotations() override;
ax::mojom::Action GetAXActionToEnableAnnotations() override;
void AddDebuggingAttributes(
const std::vector<ui::AXTreeUpdate>& updates) override;
static void IgnoreProtocolChecksForTesting();
private:
friend class AXImageAnnotatorTest;
class ImageInfo final {
public:
ImageInfo(const blink::WebAXObject& image);
~ImageInfo();
mojo::PendingRemote<image_annotation::mojom::ImageProcessor>
GetImageProcessor();
bool HasAnnotation() const;
ax::mojom::ImageAnnotationStatus status() const { return status_; }
void set_status(ax::mojom::ImageAnnotationStatus status) {
DCHECK_NE(status, ax::mojom::ImageAnnotationStatus::kNone);
status_ = status;
}
std::string annotation() const {
return annotation_.value_or("");
}
void set_annotation(std::string annotation) { annotation_ = annotation; }
private:
image_annotation::ImageProcessor image_processor_;
ax::mojom::ImageAnnotationStatus status_;
std::optional<std::string> annotation_;
};
void BindAnnotatorForTesting(
mojo::PendingRemote<image_annotation::mojom::Annotator> annotator);
void AddImageAnnotations(const blink::WebDocument& document,
ui::AXTreeUpdate* update);
void AddImageAnnotationsForNode(blink::WebAXObject& src, ui::AXNodeData* dst);
std::string GetImageAnnotation(blink::WebAXObject& image) const;
ax::mojom::ImageAnnotationStatus GetImageAnnotationStatus(
blink::WebAXObject& image) const;
bool HasAnnotationInCache(blink::WebAXObject& image) const;
bool HasImageInCache(const blink::WebAXObject& image) const;
void OnImageAdded(blink::WebAXObject& image);
void OnImageUpdated(blink::WebAXObject& image);
void OnImageRemoved(blink::WebAXObject& image);
static int GetLengthAfterRemovingStopwords(const std::string& image_name);
static bool ImageNameHasMostlyStopwords(const std::string& image_name);
static SkBitmap GetImageData(const blink::WebAXObject& image);
virtual ContentClient* GetContentClient() const;
virtual std::string GenerateImageSourceId(
const blink::WebAXObject& image) const;
void MarkDirty(const blink::WebAXObject& image) const;
void OnImageAnnotated(const blink::WebAXObject& image,
image_annotation::mojom::AnnotateImageResultPtr result);
std::string GetDocumentUrl() const;
const raw_ptr<RenderAccessibilityImpl> render_accessibility_;
mojo::Remote<image_annotation::mojom::Annotator> annotator_remote_;
std::unordered_map<int, ImageInfo> image_annotations_;
bool has_injected_stylesheet_ = false;
base::WeakPtrFactory<AXImageAnnotator> weak_factory_{this};
};
}
#endif