Skip to content

Commit

Permalink
Add choice field structs for PDF accessibility
Browse files Browse the repository at this point in the history
This change adds struct PP_PrivateAccessibilityChoiceFieldInfo to
PP_PrivateAccessibilityFormFieldInfo to transfer accessibility related
PDF choice field data from the plugin process to the mimehandler
process. Made the same changes to the C++ versions of these structs and
added the appropriate conversion code.

Bug: 1030242
Change-Id: I7aa6fd612de051d9e6b22e84e60c964d24685242
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2214734
Commit-Queue: Mansi Awasthi <maawas@microsoft.com>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Ankit Kumar 🌪️ <ankk@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#774049}
  • Loading branch information
maawas authored and Commit Bot committed Jun 2, 2020
1 parent 84df010 commit f538f3f
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 0 deletions.
27 changes: 27 additions & 0 deletions components/pdf/renderer/pdf_accessibility_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,33 @@ bool PdfAccessibilityTree::IsDataFromPluginValid(
return false;
}

const std::vector<ppapi::PdfAccessibilityTextFieldInfo>& text_fields =
page_objects.form_fields.text_fields;
if (!std::is_sorted(text_fields.begin(), text_fields.end(),
CompareTextRuns<ppapi::PdfAccessibilityTextFieldInfo>)) {
return false;
}
// Text run index of an |text_field| works on the same logic as the text run
// index of a |link| as mentioned above.
for (const ppapi::PdfAccessibilityTextFieldInfo& text_field : text_fields) {
if (text_field.text_run_index > text_runs.size())
return false;
}

const std::vector<ppapi::PdfAccessibilityChoiceFieldInfo>& choice_fields =
page_objects.form_fields.choice_fields;
if (!std::is_sorted(
choice_fields.begin(), choice_fields.end(),
CompareTextRuns<ppapi::PdfAccessibilityChoiceFieldInfo>)) {
return false;
}
// Text run index of an |choice_field| works on the same logic as the text run
// index of a |link| as mentioned above.
for (const auto& choice_field : choice_fields) {
if (choice_field.text_run_index > text_runs.size())
return false;
}

return true;
}

Expand Down
96 changes: 96 additions & 0 deletions components/pdf/renderer/pdf_accessibility_tree_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,100 @@ TEST(PdfAccessibilityTreeUnitTest, OutOfBoundHighlight) {
page_objects));
}

TEST(PdfAccessibilityTreeUnitTest, UnsortedTextFieldVector) {
std::vector<ppapi::PdfAccessibilityTextRunInfo> text_runs;
text_runs.emplace_back(kFirstTextRun);
text_runs.emplace_back(kSecondTextRun);

std::vector<PP_PrivateAccessibilityCharInfo> chars(
std::begin(kDummyCharsData), std::end(kDummyCharsData));

ppapi::PdfAccessibilityPageObjects page_objects;

{
// Add first text field in the vector.
ppapi::PdfAccessibilityTextFieldInfo text_field;
text_field.text_run_index = 2;
page_objects.form_fields.text_fields.push_back(std::move(text_field));
}

{
// Add second text field in the vector.
ppapi::PdfAccessibilityTextFieldInfo text_field;
text_field.text_run_index = 0;
page_objects.form_fields.text_fields.push_back(std::move(text_field));
}

EXPECT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
page_objects));
}

TEST(PdfAccessibilityTreeUnitTest, OutOfBoundTextField) {
std::vector<ppapi::PdfAccessibilityTextRunInfo> text_runs;
text_runs.emplace_back(kFirstTextRun);
text_runs.emplace_back(kSecondTextRun);

std::vector<PP_PrivateAccessibilityCharInfo> chars(
std::begin(kDummyCharsData), std::end(kDummyCharsData));

ppapi::PdfAccessibilityPageObjects page_objects;

{
ppapi::PdfAccessibilityTextFieldInfo text_field;
text_field.text_run_index = 3;
page_objects.form_fields.text_fields.push_back(std::move(text_field));
}

EXPECT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
page_objects));
}

TEST(PdfAccessibilityTreeUnitTest, UnsortedChoiceFieldVector) {
std::vector<ppapi::PdfAccessibilityTextRunInfo> text_runs;
text_runs.emplace_back(kFirstTextRun);
text_runs.emplace_back(kSecondTextRun);

std::vector<PP_PrivateAccessibilityCharInfo> chars(
std::begin(kDummyCharsData), std::end(kDummyCharsData));

ppapi::PdfAccessibilityPageObjects page_objects;

{
// Add first choice field in the vector.
ppapi::PdfAccessibilityChoiceFieldInfo choice_field;
choice_field.text_run_index = 2;
page_objects.form_fields.choice_fields.push_back(std::move(choice_field));
}

{
// Add second choice field in the vector.
ppapi::PdfAccessibilityChoiceFieldInfo choice_field;
choice_field.text_run_index = 0;
page_objects.form_fields.choice_fields.push_back(std::move(choice_field));
}

EXPECT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
page_objects));
}

TEST(PdfAccessibilityTreeUnitTest, OutOfBoundChoiceField) {
std::vector<ppapi::PdfAccessibilityTextRunInfo> text_runs;
text_runs.emplace_back(kFirstTextRun);
text_runs.emplace_back(kSecondTextRun);

std::vector<PP_PrivateAccessibilityCharInfo> chars(
std::begin(kDummyCharsData), std::end(kDummyCharsData));

ppapi::PdfAccessibilityPageObjects page_objects;

{
ppapi::PdfAccessibilityChoiceFieldInfo choice_field;
choice_field.text_run_index = 3;
page_objects.form_fields.choice_fields.push_back(std::move(choice_field));
}

EXPECT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
page_objects));
}

} // namespace pdf
60 changes: 60 additions & 0 deletions ppapi/c/private/ppb_pdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ struct PP_PrivateAccessibilityCharInfo {
// This holds the link information provided by the PDF and will be used in
// accessibility to provide the link information. Needs to stay in sync with
// C++ versions (PdfAccessibilityLinkInfo and PrivateAccessibilityLinkInfo).
// This struct contains index state that should be validated using
// PdfAccessibilityTree::IsDataFromPluginValid() before usage.
struct PP_PrivateAccessibilityLinkInfo {
// URL of the link.
const char* url;
Expand All @@ -138,6 +140,8 @@ struct PP_PrivateAccessibilityLinkInfo {
// This holds the image information provided by the PDF and will be used in
// accessibility to provide the image information. Needs to stay in sync with
// C++ versions (PdfAccessibilityImageInfo and PrivateAccessibilityImageInfo).
// This struct contains index state that should be validated using
// PdfAccessibilityTree::IsDataFromPluginValid() before usage.
struct PP_PrivateAccessibilityImageInfo {
// Alternate text for the image provided by PDF.
const char* alt_text;
Expand All @@ -155,6 +159,8 @@ struct PP_PrivateAccessibilityImageInfo {
// popup note, the data of which is also captured here.
// Needs to stay in sync with C++ versions (PdfAccessibilityHighlightInfo and
// PrivateAccessibilityHighlightInfo).
// This struct contains index state that should be validated using
// PdfAccessibilityTree::IsDataFromPluginValid() before usage.
struct PP_PrivateAccessibilityHighlightInfo {
// Represents the text of the associated popup note, if present.
const char* note_text;
Expand All @@ -178,6 +184,8 @@ struct PP_PrivateAccessibilityHighlightInfo {
// This holds text form field information provided by the PDF and will be used
// in accessibility to expose it. Needs to stay in sync with C++ versions
// (PdfAccessibilityTextFieldInfo and PrivateAccessibilityTextFieldInfo).
// This struct contains index state that should be validated using
// PdfAccessibilityTree::IsDataFromPluginValid() before usage.
struct PP_PrivateAccessibilityTextFieldInfo {
// Represents the name property of text field, if present.
const char* name;
Expand All @@ -202,12 +210,64 @@ struct PP_PrivateAccessibilityTextFieldInfo {
struct PP_FloatRect bounds;
};

// This holds choice form field option information provided by the PDF and
// will be used in accessibility to expose it. Needs to stay in sync with C++
// versions (PdfAccessibilityChoiceFieldOptionInfo and
// PrivateAccessibilityChoiceFieldOptionInfo).
struct PP_PrivateAccessibilityChoiceFieldOptionInfo {
// Represents the name property of choice field option.
const char* name;
uint32_t name_length;
// Represents if a choice field option is selected or not.
bool is_selected;
// Bounding box of the choice field option.
struct PP_FloatRect bounds;
};

typedef enum {
PP_PRIVATECHOICEFIELD_LISTBOX = 0,
PP_PRIVATECHOICEFIELD_COMBOBOX = 1,
PP_PRIVATECHOICEFIELD_LAST = PP_PRIVATECHOICEFIELD_COMBOBOX
} PP_PrivateChoiceFieldType;

// This holds choice form field information provided by the PDF and will be used
// in accessibility to expose it. Needs to stay in sync with C++ versions
// (PdfAccessibilityChoiceFieldInfo and PrivateAccessibilityChoiceFieldInfo).
// This struct contains index state that should be validated using
// PdfAccessibilityTree::IsDataFromPluginValid() before usage.
struct PP_PrivateAccessibilityChoiceFieldInfo {
// Represents the name property of choice field, if present.
const char* name;
uint32_t name_length;
// Represents list of options in choice field, if present.
struct PP_PrivateAccessibilityChoiceFieldOptionInfo* options;
uint32_t options_length;
// Represents type of choice field.
PP_PrivateChoiceFieldType type;
// Represents if the choice field is non-editable.
bool is_read_only;
// Represents if the choice field is multi-selectable.
bool is_multi_select;
// Represents if the choice field includes an editable text box.
bool has_editable_text_box;
// Index of the choice field in the collection of choice fields in the page.
// Used to identify the annotation on which action needs to be performed.
uint32_t index_in_page;
// We anchor the choice field to a text run index, this denotes the text run
// before which the choice field should be inserted in the accessibility tree.
uint32_t text_run_index;
// Bounding box of the choice field.
struct PP_FloatRect bounds;
};

// This holds form fields within a PDF page. Needs to stay in sync with C++
// versions (PdfAccessibilityFormFieldInfo and
// PrivateAccessibilityFormFieldInfo).
struct PP_PrivateAccessibilityFormFieldInfo {
struct PP_PrivateAccessibilityTextFieldInfo* text_fields;
uint32_t text_field_count;
struct PP_PrivateAccessibilityChoiceFieldInfo* choice_fields;
uint32_t choice_field_count;
};

// This holds different PDF page objects - links, images, highlights and
Expand Down
39 changes: 39 additions & 0 deletions ppapi/cpp/private/pdf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,31 @@ void ConvertPrivateAccessibilityTextFieldInfo(
info->bounds = text_field.bounds;
}

void ConvertPrivateAccessibilityChoiceFieldInfo(
const PDF::PrivateAccessibilityChoiceFieldInfo& choice_field,
PP_PrivateAccessibilityChoiceFieldInfo* info,
std::vector<PP_PrivateAccessibilityChoiceFieldOptionInfo>* option_info) {
info->name = choice_field.name.c_str();
info->name_length = choice_field.name.size();

option_info->resize(choice_field.options.size());
info->options = option_info->data();
for (size_t i = 0; i < choice_field.options.size(); i++) {
info->options[i].name = choice_field.options[i].name.c_str();
info->options[i].name_length = choice_field.options[i].name.size();
info->options[i].is_selected = choice_field.options[i].is_selected;
info->options[i].bounds = choice_field.options[i].bounds;
}
info->options_length = choice_field.options.size();
info->type = choice_field.type;
info->is_read_only = choice_field.is_read_only;
info->is_multi_select = choice_field.is_multi_select;
info->has_editable_text_box = choice_field.has_editable_text_box;
info->index_in_page = choice_field.index_in_page;
info->text_run_index = choice_field.text_run_index;
info->bounds = choice_field.bounds;
}

} // namespace

// static
Expand Down Expand Up @@ -307,6 +332,18 @@ void PDF::SetAccessibilityPageInfo(
&text_field_info[i]);
}

const std::vector<PrivateAccessibilityChoiceFieldInfo>& choice_fields =
page_objects.form_fields.choice_fields;
std::vector<PP_PrivateAccessibilityChoiceFieldInfo> choice_field_info(
choice_fields.size());
std::vector<std::vector<PP_PrivateAccessibilityChoiceFieldOptionInfo> >
choice_field_option_info(choice_fields.size());
for (size_t i = 0; i < choice_fields.size(); ++i) {
ConvertPrivateAccessibilityChoiceFieldInfo(choice_fields[i],
&choice_field_info[i],
&choice_field_option_info[i]);
}

PP_PrivateAccessibilityPageObjects pp_page_objects;
pp_page_objects.links = link_info.data();
pp_page_objects.link_count = link_info.size();
Expand All @@ -316,6 +353,8 @@ void PDF::SetAccessibilityPageInfo(
pp_page_objects.highlight_count = highlight_info.size();
pp_page_objects.form_fields.text_fields = text_field_info.data();
pp_page_objects.form_fields.text_field_count = text_field_info.size();
pp_page_objects.form_fields.choice_fields = choice_field_info.data();
pp_page_objects.form_fields.choice_field_count = choice_field_info.size();

get_interface<PPB_PDF>()->SetAccessibilityPageInfo(
instance.pp_instance(), page_info, text_run_info.data(), chars.data(),
Expand Down
31 changes: 31 additions & 0 deletions ppapi/cpp/private/pdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,41 @@ class PDF {
FloatRect bounds;
};

// C++ version of PP_PrivateAccessibilityChoiceFieldOptionInfo.
// Needs to stay in sync with the C version.
struct PrivateAccessibilityChoiceFieldOptionInfo {
std::string name;
bool is_selected;
FloatRect bounds;
};

// C++ version of PP_PrivateAccessibilityChoiceFieldInfo.
// Needs to stay in sync with the C version.
struct PrivateAccessibilityChoiceFieldInfo {
std::string name;
std::vector<PrivateAccessibilityChoiceFieldOptionInfo> options;
PP_PrivateChoiceFieldType type;
// Represents if the choice field is non-editable.
bool is_read_only;
// Represents if the choice field is multi-selectable.
bool is_multi_select;
// Represents if the choice field includes an editable text box.
bool has_editable_text_box;
// Index of this choice field in the collection of choice fields in the
// page.
uint32_t index_in_page;
// We anchor the choice field to a text run index, this denotes the text run
// before which the choice field should be inserted in the accessibility
// tree.
uint32_t text_run_index;
FloatRect bounds;
};

// C++ version of PP_PrivateAccessibilityFormFieldInfo.
// Needs to stay in sync with the C version.
struct PrivateAccessibilityFormFieldInfo {
std::vector<PrivateAccessibilityTextFieldInfo> text_fields;
std::vector<PrivateAccessibilityChoiceFieldInfo> choice_fields;
};

// C++ version of PP_PrivateAccessibilityPageObjects.
Expand Down
20 changes: 20 additions & 0 deletions ppapi/proxy/ppapi_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(PP_PdfAccessibilityScrollAlignment,
PP_PDF_ACCESSIBILITYSCROLLALIGNMENT_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(PP_PdfAccessibilityAnnotationType,
PP_PDF_ACCESSIBILITY_ANNOTATIONTYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(PP_PrivateChoiceFieldType, PP_PRIVATECHOICEFIELD_LAST)

IPC_STRUCT_TRAITS_BEGIN(PP_Point)
IPC_STRUCT_TRAITS_MEMBER(x)
Expand Down Expand Up @@ -346,8 +347,27 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::PdfAccessibilityTextFieldInfo)
IPC_STRUCT_TRAITS_MEMBER(bounds)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(ppapi::PdfAccessibilityChoiceFieldOptionInfo)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(is_selected)
IPC_STRUCT_TRAITS_MEMBER(bounds)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(ppapi::PdfAccessibilityChoiceFieldInfo)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(options)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(is_read_only)
IPC_STRUCT_TRAITS_MEMBER(is_multi_select)
IPC_STRUCT_TRAITS_MEMBER(has_editable_text_box)
IPC_STRUCT_TRAITS_MEMBER(index_in_page)
IPC_STRUCT_TRAITS_MEMBER(text_run_index)
IPC_STRUCT_TRAITS_MEMBER(bounds)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(ppapi::PdfAccessibilityFormFieldInfo)
IPC_STRUCT_TRAITS_MEMBER(text_fields)
IPC_STRUCT_TRAITS_MEMBER(choice_fields)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(ppapi::PdfAccessibilityPageObjects)
Expand Down
Loading

0 comments on commit f538f3f

Please sign in to comment.