[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:

committed by
Chromium LUCI CQ

parent
6870913c68
commit
f96d0478df
@ -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_;
|
||||
|
Reference in New Issue
Block a user