0

[PDF Ink Signatures] Disable form and selection in annotation mode

Disable form filling, links, and text selection in annotation mode. This
is similar to read-only mode, but annotation-related input handlers
should be allowed.

Fixed: 353923998
Change-Id: Ie0db9e535d9832a125a293d8627a600a3a350b01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5841317
Commit-Queue: Andy Phan <andyphan@chromium.org>
Reviewed-by: Alan Screen <awscreen@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1353635}
This commit is contained in:
Andy Phan
2024-09-10 22:42:48 +00:00
committed by Chromium LUCI CQ
parent 6870913c68
commit f96d0478df
14 changed files with 149 additions and 3 deletions

@ -657,6 +657,7 @@ void PdfInkModule::HandleSetAnnotationBrushMessage(
void PdfInkModule::HandleSetAnnotationModeMessage(
const base::Value::Dict& message) {
enabled_ = message.FindBool("enable").value();
client_->OnAnnotationModeToggled(enabled_);
MaybeSetCursor();
}

@ -88,6 +88,9 @@ class PdfInkModule {
// Returns whether the page at `page_index` is visible or not.
virtual bool IsPageVisible(int page_index) = 0;
// Notifies the client whether annotation mode is enabled or not.
virtual void OnAnnotationModeToggled(bool enable) {}
// Notifies the client that a stroke has finished drawing or erasing.
virtual void StrokeFinished() {}

@ -1349,6 +1349,12 @@ bool PdfViewWebPlugin::IsValidLink(const std::string& url) {
return base::Value(url).is_string();
}
#if BUILDFLAG(ENABLE_PDF_INK2)
bool PdfViewWebPlugin::IsInAnnotationMode() const {
return ink_module_ && ink_module_->enabled();
}
#endif // BUILDFLAG(ENABLE_PDF_INK2)
void PdfViewWebPlugin::SetCaretPosition(const gfx::PointF& position) {
engine_->SetCaretPosition(FrameToPdfCoordinates(position));
}
@ -2072,6 +2078,15 @@ bool PdfViewWebPlugin::IsPageVisible(int page_index) {
return engine_->IsPageVisible(page_index);
}
#if BUILDFLAG(ENABLE_PDF_INK2)
void PdfViewWebPlugin::OnAnnotationModeToggled(bool enable) {
engine_->SetFormHighlight(/*enable_form=*/!enable);
if (enable) {
engine_->ClearTextSelection();
}
}
#endif // BUILDFLAG(ENABLE_PDF_INK2)
void PdfViewWebPlugin::StrokeFinished() {
base::Value::Dict message;
message.Set("type", "finishInkStroke");
@ -2219,6 +2234,11 @@ bool PdfViewWebPlugin::HandleWebInputEvent(const blink::WebInputEvent& event) {
if (ink_module_ && ink_module_->HandleInputEvent(event_to_handle)) {
return true;
}
if (IsInAnnotationMode()) {
// When in annotation mode, only handle ink input events.
return false;
}
#endif
if (engine_->HandleInputEvent(event_to_handle))

@ -363,6 +363,9 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
void SetSelectedText(const std::string& selected_text) override;
void SetLinkUnderCursor(const std::string& link_under_cursor) override;
bool IsValidLink(const std::string& url) override;
#if BUILDFLAG(ENABLE_PDF_INK2)
bool IsInAnnotationMode() const override;
#endif // BUILDFLAG(ENABLE_PDF_INK2)
// pdf::mojom::PdfListener:
void SetCaretPosition(const gfx::PointF& position) override;
@ -410,6 +413,7 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
gfx::Vector2dF GetViewportOriginOffset() override;
float GetZoom() const override;
bool IsPageVisible(int page_index) override;
void OnAnnotationModeToggled(bool enable) override;
void StrokeFinished() override;
void UpdateInkCursorImage(SkBitmap bitmap) override;
void UpdateThumbnail(int page_index) override;

@ -2669,6 +2669,20 @@ TEST_F(PdfViewWebPluginInkTest, VisiblePageIndexFromPoint) {
EXPECT_EQ(12, plugin_->VisiblePageIndexFromPoint(kPage12Bottom));
EXPECT_EQ(-1, plugin_->VisiblePageIndexFromPoint(kPageBelowLast));
}
TEST_F(PdfViewWebPluginInkTest, AnnotationModeSetsFormAndClearsText) {
EXPECT_CALL(*engine_ptr_, SetFormHighlight(false));
EXPECT_CALL(*engine_ptr_, ClearTextSelection());
plugin_->OnMessage(CreateSetAnnotationModeMessageForTesting(/*enable=*/true));
EXPECT_TRUE(plugin_->IsInAnnotationMode());
EXPECT_CALL(*engine_ptr_, SetFormHighlight(true));
plugin_->OnMessage(
CreateSetAnnotationModeMessageForTesting(/*enable=*/false));
EXPECT_FALSE(plugin_->IsInAnnotationMode());
}
#endif // BUILDFLAG(ENABLE_PDF_INK2)
} // namespace chrome_pdf

@ -1082,8 +1082,12 @@ void PDFiumEngine::KillFormFocus() {
}
void PDFiumEngine::UpdateFocus(bool has_focus) {
bool can_focus = !IsReadOnly();
#if BUILDFLAG(ENABLE_PDF_INK2)
can_focus = can_focus && !client_->IsInAnnotationMode();
#endif // BUILDFLAG(ENABLE_PDF_INK2)
base::AutoReset<bool> updating_focus_guard(&updating_focus_, true);
if (has_focus && !IsReadOnly()) {
if (has_focus && can_focus) {
UpdateFocusElementType(last_focused_element_type_);
if (focus_element_type_ == FocusElementType::kPage &&
PageIndexInBounds(last_focused_page_) &&
@ -2353,6 +2357,12 @@ void PDFiumEngine::SelectAll() {
if (IsReadOnly())
return;
#if BUILDFLAG(ENABLE_PDF_INK2)
if (client_->IsInAnnotationMode()) {
return;
}
#endif // BUILDFLAG(ENABLE_PDF_INK2)
if (focus_field_type_ == FocusFieldType::kText) {
if (PageIndexInBounds(last_focused_page_))
FORM_SelectAllText(form(), pages_[last_focused_page_]->GetPage());

@ -243,7 +243,7 @@ class PDFiumEngine : public DocumentLoader::Client, public IFSDK_PAUSE {
virtual void SelectAll();
void ClearTextSelection();
virtual void ClearTextSelection();
// Gets the list of DocumentAttachmentInfo from the document.
virtual const std::vector<DocumentAttachmentInfo>&
@ -431,7 +431,7 @@ class PDFiumEngine : public DocumentLoader::Client, public IFSDK_PAUSE {
bool IsValidLink(const std::string& url);
// Sets whether form highlight should be enabled or cleared.
void SetFormHighlight(bool enable_form);
virtual void SetFormHighlight(bool enable_form);
private:
// This helper class is used to detect the difference in selection between

@ -13,6 +13,7 @@
#include <vector>
#include "base/functional/callback.h"
#include "pdf/buildflags.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/base/window_open_disposition.h"
@ -195,6 +196,11 @@ class PDFiumEngineClient {
// viewers.
// See https://crbug.com/312882 for an example.
virtual bool IsValidLink(const std::string& url) = 0;
#if BUILDFLAG(ENABLE_PDF_INK2)
// Returns true if the client is in annotation mode.
virtual bool IsInAnnotationMode() const = 0;
#endif // BUILDFLAG(ENABLE_PDF_INK2)
};
} // namespace chrome_pdf

@ -24,6 +24,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "pdf/buildflags.h"
#include "pdf/document_attachment_info.h"
#include "pdf/document_layout.h"
#include "pdf/document_metadata.h"
@ -116,6 +117,9 @@ class MockTestClient : public TestClient {
MOCK_METHOD(bool, IsPrintPreview, (), (const override));
MOCK_METHOD(void, DocumentFocusChanged, (bool), (override));
MOCK_METHOD(void, SetLinkUnderCursor, (const std::string&), (override));
#if BUILDFLAG(ENABLE_PDF)
MOCK_METHOD(bool, IsInAnnotationMode, (), (const override));
#endif // BUILDFLAG(ENABLE_PDF)
};
} // namespace
@ -1851,4 +1855,62 @@ TEST_P(PDFiumEngineReadOnlyTest, UnselectText) {
INSTANTIATE_TEST_SUITE_P(All, PDFiumEngineReadOnlyTest, testing::Bool());
#if BUILDFLAG(ENABLE_PDF_INK2)
class AnnotationModeTestClient : public MockTestClient {
public:
AnnotationModeTestClient() = default;
AnnotationModeTestClient(const AnnotationModeTestClient&) = delete;
AnnotationModeTestClient& operator=(const AnnotationModeTestClient&) = delete;
~AnnotationModeTestClient() override = default;
// PDFiumEngineClient overrides:
bool IsInAnnotationMode() const override { return annotation_mode_; }
void set_annotation_mode(bool annotation_mode) {
annotation_mode_ = annotation_mode;
}
private:
bool annotation_mode_ = false;
};
using PDFiumEngineAnnotationModeTest = PDFiumTestBase;
TEST_P(PDFiumEngineAnnotationModeTest, KillFormFocus) {
NiceMock<AnnotationModeTestClient> client;
std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
&client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
ASSERT_TRUE(engine);
client.set_annotation_mode(true);
// Attempting to focus in annotation mode should once more trigger a killing
// of form focus.
EXPECT_CALL(client, FormFieldFocusChange(
PDFiumEngineClient::FocusFieldType::kNoFocus));
engine->UpdateFocus(true);
}
TEST_P(PDFiumEngineAnnotationModeTest, CannotSelectText) {
NiceMock<AnnotationModeTestClient> client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
ASSERT_TRUE(engine);
EXPECT_THAT(engine->GetSelectedText(), IsEmpty());
// Update the plugin size so that all the text is visible by
// `SelectionChangeInvalidator`.
engine->PluginSizeUpdated({500, 500});
client.set_annotation_mode(true);
// Attempting to select text should do nothing in annotation mode.
engine->SelectAll();
EXPECT_THAT(engine->GetSelectedText(), IsEmpty());
}
INSTANTIATE_TEST_SUITE_P(All, PDFiumEngineAnnotationModeTest, testing::Bool());
#endif // BUILDFLAG(ENABLE_PDF_INK2)
} // namespace chrome_pdf

@ -13,6 +13,7 @@
#include "base/functional/callback.h"
#include "base/notreached.h"
#include "base/time/time.h"
#include "pdf/buildflags.h"
#include "pdf/document_layout.h"
#include "pdf/loader/url_loader.h"
#include "third_party/skia/include/core/SkColor.h"
@ -171,4 +172,10 @@ bool PreviewModeClient::IsValidLink(const std::string& url) {
NOTREACHED();
}
#if BUILDFLAG(ENABLE_PDF_INK2)
bool PreviewModeClient::IsInAnnotationMode() const {
NOTREACHED();
}
#endif // BUILDFLAG(ENABLE_PDF_INK2)
} // namespace chrome_pdf

@ -12,6 +12,7 @@
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "pdf/buildflags.h"
#include "pdf/pdfium/pdfium_engine_client.h"
namespace chrome_pdf {
@ -73,6 +74,9 @@ class PreviewModeClient : public PDFiumEngineClient {
void SetSelectedText(const std::string& selected_text) override;
void SetLinkUnderCursor(const std::string& link_under_cursor) override;
bool IsValidLink(const std::string& url) override;
#if BUILDFLAG(ENABLE_PDF_INK2)
bool IsInAnnotationMode() const override;
#endif // BUILDFLAG(ENABLE_PDF_INK2)
private:
const raw_ptr<Client> client_;

@ -7,6 +7,7 @@
#include <memory>
#include "base/time/time.h"
#include "pdf/buildflags.h"
#include "pdf/document_layout.h"
#include "pdf/loader/url_loader.h"
#include "pdf/pdfium/pdfium_engine.h"
@ -71,4 +72,10 @@ bool TestClient::IsValidLink(const std::string& url) {
return !url.empty();
}
#if BUILDFLAG(ENABLE_PDF)
bool TestClient::IsInAnnotationMode() const {
return false;
}
#endif // BUILDFLAG(ENABLE_PDF)
} // namespace chrome_pdf

@ -9,6 +9,7 @@
#include <vector>
#include "base/memory/raw_ptr.h"
#include "pdf/buildflags.h"
#include "pdf/pdfium/pdfium_engine_client.h"
namespace chrome_pdf {
@ -43,6 +44,9 @@ class TestClient : public PDFiumEngineClient {
void SetSelectedText(const std::string& selected_text) override;
void SetLinkUnderCursor(const std::string& link_under_cursor) override;
bool IsValidLink(const std::string& url) override;
#if BUILDFLAG(ENABLE_PDF)
bool IsInAnnotationMode() const override;
#endif // BUILDFLAG(ENABLE_PDF)
private:
// Not owned. Expected to dangle briefly, as the engine usually is destroyed

@ -107,6 +107,10 @@ class TestPDFiumEngine : public PDFiumEngine {
MOCK_METHOD(void, OnDocumentCanceled, (), (override));
MOCK_METHOD(void, SetFormHighlight, (bool), (override));
MOCK_METHOD(void, ClearTextSelection, (), (override));
protected:
std::vector<DocumentAttachmentInfo>& doc_attachment_info_list() {
return doc_attachment_info_list_;