0

Enhance tabbing support to include links and highlights

This CL adds ability to tab across links and highlights (along with
already supported widgets) behind a newly added feature flag
kTabAcrossPDFAnnotations. This is done by calling the newly added
PDFium API FPDFAnnot_SetFocusableSubtypes().
A unit test has also been added to validate the added support.
Here is the related CL:
https://pdfium-review.googlesource.com/c/pdfium/+/60011/

Bug: 994500
Change-Id: I00312c00f3e6373949a4723cc65778fdb32ab963
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1783695
Reviewed-by: Ian Prest <iapres@microsoft.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Neha Gupta <negupta@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#759380}
This commit is contained in:
Neha Gupta
2020-04-15 20:05:53 +00:00
committed by Commit Bot
parent 097ea71169
commit 96e2f2bd4b
6 changed files with 247 additions and 0 deletions

@ -32,5 +32,8 @@ const base::Feature kSaveEditedPDFForm = {"SaveEditedPDFForm",
#endif // defined(OS_CHROMEOS)
};
const base::Feature kTabAcrossPDFAnnotations = {
"TabAcrossPDFAnnotations", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace chrome_pdf

@ -18,6 +18,7 @@ extern const base::Feature kAccessiblePDFHighlight;
extern const base::Feature kPDFAnnotations;
extern const base::Feature kPDFTwoUpView;
extern const base::Feature kSaveEditedPDFForm;
extern const base::Feature kTabAcrossPDFAnnotations;
} // namespace features
} // namespace chrome_pdf

@ -16,6 +16,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@ -29,6 +30,7 @@
#include "pdf/document_loader_impl.h"
#include "pdf/draw_utils/coordinates.h"
#include "pdf/draw_utils/shadow.h"
#include "pdf/pdf_features.h"
#include "pdf/pdf_transform.h"
#include "pdf/pdfium/pdfium_api_string_buffer_adapter.h"
#include "pdf/pdfium/pdfium_document.h"
@ -2709,6 +2711,14 @@ void PDFiumEngine::LoadForm() {
FPDF_SetFormFieldHighlightColor(form(), FPDF_FORMFIELD_UNKNOWN,
kFormHighlightColor);
FPDF_SetFormFieldHighlightAlpha(form(), kFormHighlightAlpha);
if (base::FeatureList::IsEnabled(features::kTabAcrossPDFAnnotations)) {
static constexpr FPDF_ANNOTATION_SUBTYPE kFocusableAnnotSubtypes[] = {
FPDF_ANNOT_LINK, FPDF_ANNOT_HIGHLIGHT, FPDF_ANNOT_WIDGET};
FPDF_BOOL ret = FPDFAnnot_SetFocusableSubtypes(
form(), kFocusableAnnotSubtypes, base::size(kFocusableAnnotSubtypes));
DCHECK(ret);
}
}
}

@ -4,9 +4,11 @@
#include "pdf/pdfium/pdfium_engine.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "pdf/document_layout.h"
#include "pdf/document_metadata.h"
#include "pdf/pdf_features.h"
#include "pdf/pdfium/pdfium_page.h"
#include "pdf/pdfium/pdfium_test_base.h"
#include "pdf/test/test_client.h"
@ -258,6 +260,62 @@ class PDFiumEngineTabbingTest : public PDFiumTestBase {
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
};
TEST_F(PDFiumEngineTabbingTest, TabbingSupportedAnnots) {
/*
* Document structure
* Document
* ++ Page 1
* ++++ Widget annotation
* ++++ Widget annotation
* ++++ Highlight annotation
* ++++ Link annotation
*/
// Enable feature flag.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
chrome_pdf::features::kTabAcrossPDFAnnotations);
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("annots.pdf"));
ASSERT_TRUE(engine);
ASSERT_EQ(1, engine->GetNumberOfPages());
ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
GetFocusedElementType(engine.get()));
EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kDocument,
GetFocusedElementType(engine.get()));
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
ASSERT_TRUE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kPage,
GetFocusedElementType(engine.get()));
EXPECT_EQ(0, GetLastFocusedPage(engine.get()));
ASSERT_FALSE(HandleTabEvent(engine.get(), 0));
EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
GetFocusedElementType(engine.get()));
}
TEST_F(PDFiumEngineTabbingTest, TabbingForwardTest) {
/*
* Document structure

80
pdf/test/data/annots.in Normal file

@ -0,0 +1,80 @@
{{header}}
{{object 1 0}} <<
/Type /Catalog
/Pages 2 0 R
/AcroForm [5 0 R 6 0 R]
>>
endobj
{{object 2 0}} <<
/Type /Pages
/Count 1
/Kids [3 0 R]
>>
endobj
{{object 3 0}} <<
/Type /Page
/Parent 2 0 R
/Annots [5 0 R 6 0 R 7 0 R 8 0 R]
/Contents 4 0 R
/Tabs /R
>>
endobj
{{object 4 0}} <<
{{streamlen}}
>>
stream
BT
70 340 Td
14 Tf
(External Link ) Tj
ET
endstream
endobj
{{object 5 0}} <<
/Type /Annot
/Subtype /Widget
/FT /Tx
/Parent 3 0 R
/T (TextField)
/Rect [69 670 220 690]
>>
endobj
{{object 6 0}} <<
/Type /Annot
/Subtype /Widget
/FT /Btn
/Rect [69 360 220 380]
/A <<
/URI (https://www.google.com)
/S /URI
>>
/F 4
/T (button)
/Ff 65536
>>
endobj
{{object 7 0}} <<
/Type /Annot
/Subtype /Link
/Rect [69 338 180 358]
/A <<
/Type /Action
/S /URI
/URI (https://www.google.com/)
>>
/F 4
>>
endobj
{{object 8 0}} <<
/Type /Annot
/Subtype /Highlight
/F 4
/QuadPoints [120 358 150 358 120 338 150 338]
/C [1 0.90196 0]
/Rect [120 338 150 358]
>>
endobj
{{xref}}
{{trailer}}
{{startxref}}
%%EOF

95
pdf/test/data/annots.pdf Normal file

@ -0,0 +1,95 @@
%PDF-1.7
%<25><><EFBFBD><EFBFBD>
1 0 obj <<
/Type /Catalog
/Pages 2 0 R
/AcroForm [5 0 R 6 0 R]
>>
endobj
2 0 obj <<
/Type /Pages
/Count 1
/Kids [3 0 R]
>>
endobj
3 0 obj <<
/Type /Page
/Parent 2 0 R
/Annots [5 0 R 6 0 R 7 0 R 8 0 R]
/Contents 4 0 R
/Tabs /R
>>
endobj
4 0 obj <<
/Length 42
>>
stream
BT
70 340 Td
14 Tf
(External Link ) Tj
ET
endstream
endobj
5 0 obj <<
/Type /Annot
/Subtype /Widget
/FT /Tx
/Parent 3 0 R
/T (TextField)
/Rect [69 670 220 690]
>>
endobj
6 0 obj <<
/Type /Annot
/Subtype /Widget
/FT /Btn
/Rect [69 360 220 380]
/A <<
/URI (https://www.google.com)
/S /URI
>>
/F 4
/T (button)
/Ff 65536
>>
endobj
7 0 obj <<
/Type /Annot
/Subtype /Link
/Rect [69 338 180 358]
/A <<
/Type /Action
/S /URI
/URI (https://www.google.com/)
>>
/F 4
>>
endobj
8 0 obj <<
/Type /Annot
/Subtype /Highlight
/F 4
/QuadPoints [120 358 150 358 120 338 150 338]
/C [1 0.90196 0]
/Rect [120 338 150 358]
>>
endobj
xref
0 9
0000000000 65535 f
0000000015 00000 n
0000000094 00000 n
0000000157 00000 n
0000000273 00000 n
0000000366 00000 n
0000000489 00000 n
0000000672 00000 n
0000000835 00000 n
trailer <<
/Root 1 0 R
/Size 9
>>
startxref
993
%%EOF