Use more RetainPtrs in CXFA_FFTabOrderPageWidgetIterator.
- Make CreateSpaceOrderLayoutItems() return a vector of
RetainPtr<CXFA_ContentLayoutItem> instead of CXFA_FFWidget pointers.
- Change CreateTabOrderWidgetArray() to use the RetainPtrs.
- Add a test for this case.
Bug: chromium:980116
Change-Id: I5ef172930e775a07fb37e2dffe2318ead76961cb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70213
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/testing/resources/javascript/xfa_specific/bug_980116.evt b/testing/resources/javascript/xfa_specific/bug_980116.evt
new file mode 100644
index 0000000..a5025fa
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_980116.evt
@@ -0,0 +1,4 @@
+mousemove,50,50
+mousedown,left,50,50
+mouseup,left,50,50
+keycode,9
diff --git a/testing/resources/javascript/xfa_specific/bug_980116.in b/testing/resources/javascript/xfa_specific/bug_980116.in
new file mode 100644
index 0000000..11bcbf2
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_980116.in
@@ -0,0 +1,58 @@
+{{header}}
+{{include ../../xfa_catalog_1_0.fragment}}
+{{include ../../xfa_object_2_0.fragment}}
+{{include ../../xfa_preamble_3_0.fragment}}
+{{include ../../xfa_config_4_0.fragment}}
+{{object 5 0}} <<
+ {{streamlen}}
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/2.6/">
+ <subform layout="tb" locale="en_US" name="form1" restoreState="auto">
+ <pageSet>
+ <pageArea id="Page1" name="Page1">
+ <contentArea h="10.5in" w="8in" x="0.25in" y="0.25in"/>
+ <medium long="11in" short="8.5in" stock="letter"/>
+ </pageArea>
+ </pageSet>
+ <subform h="10.5in" w="8in">
+ <field h="3mm" name="DropDownList1" w="3mm" x="0mm" y="1mm">
+ <ui>
+ <choiceList/>
+ </ui>
+ <items save="1">
+ <text>Single</text>
+ <text>Married</text>
+ <text>Other</text>
+ </items>
+ </field>
+ <field h="500.0001mm" name="DropDownList2" w="500.625mm" x="0mm" y="0mm">
+ <ui>
+ <textEdit></textEdit>
+ </ui>
+ <value>
+ <text>Employee</text>
+ </value>
+ </field>
+ </subform>
+ <traversal>
+ <traverse operation="first" ref="$xfa.(eval('xfa.host.setFocus(field_DropDownList1); xfa.template.remerge(); xfa.host.openList(field_DropDownList1);') == 0)"/>
+ </traversal>
+ <event activity="docReady">
+ <script contentType="application/x-javascript">
+ field_DropDownList1 = xfa.resolveNode("xfa.form..DropDownList1");
+ field_DropDownList2 = xfa.resolveNode("xfa.form..DropDownList2");
+ xfa.host.setFocus(field_DropDownList2);
+ </script>
+ </event>
+ </subform>
+</template>
+endstream
+endobj
+{{include ../../xfa_locale_6_0.fragment}}
+{{include ../../xfa_postamble_7_0.fragment}}
+{{include ../../xfa_pages_8_0.fragment}}
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp
index 6ff6ee8..996d8e5 100644
--- a/xfa/fxfa/cxfa_ffpageview.cpp
+++ b/xfa/fxfa/cxfa_ffpageview.cpp
@@ -342,36 +342,37 @@
void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() {
m_TabOrderWidgetArray.clear();
- const std::vector<CXFA_FFWidget*> widgets = CreateSpaceOrderWidgetArray();
- if (widgets.empty())
+ const std::vector<RetainPtr<CXFA_ContentLayoutItem>> items =
+ CreateSpaceOrderLayoutItems();
+ if (items.empty())
return;
- CXFA_FFWidget* widget = widgets[0];
- while (m_TabOrderWidgetArray.size() < widgets.size()) {
- if (!pdfium::Contains(m_TabOrderWidgetArray, widget->GetLayoutItem())) {
- m_TabOrderWidgetArray.emplace_back(widget->GetLayoutItem());
- CXFA_Node* node = widget->GetNode();
+ RetainPtr<CXFA_ContentLayoutItem> item = items[0];
+ while (m_TabOrderWidgetArray.size() < items.size()) {
+ if (!pdfium::Contains(m_TabOrderWidgetArray, item)) {
+ m_TabOrderWidgetArray.emplace_back(item);
+ CXFA_Node* node = item->GetFFWidget()->GetNode();
if (node->GetFFWidgetType() == XFA_FFWidgetType::kExclGroup) {
- auto it = std::find(widgets.begin(), widgets.end(), widget);
- size_t index = it != widgets.end() ? it - widgets.begin() + 1 : 0;
+ auto it = std::find(items.begin(), items.end(), item);
+ size_t index = it != items.end() ? it - items.begin() + 1 : 0;
while (true) {
- CXFA_FFWidget* radio = widgets[index % widgets.size()];
+ CXFA_FFWidget* radio = items[index % items.size()]->GetFFWidget();
if (radio->GetNode()->GetExclGroupIfExists() != node)
break;
- if (!pdfium::Contains(m_TabOrderWidgetArray, widget->GetLayoutItem()))
+ if (!pdfium::Contains(m_TabOrderWidgetArray, item))
m_TabOrderWidgetArray.emplace_back(radio->GetLayoutItem());
++index;
}
}
- CXFA_FFWidget* next_widget = GetTraverseWidget(widget);
+ CXFA_FFWidget* next_widget = GetTraverseWidget(item->GetFFWidget());
if (next_widget) {
- widget = next_widget;
+ item = next_widget->GetLayoutItem();
continue;
}
}
- auto it = std::find(widgets.begin(), widgets.end(), widget);
- size_t index = it != widgets.end() ? it - widgets.begin() + 1 : 0;
- widget = widgets[index % widgets.size()];
+ auto it = std::find(items.begin(), items.end(), item);
+ size_t index = it != items.end() ? it - items.begin() + 1 : 0;
+ item = items[index % items.size()];
}
}
@@ -429,17 +430,18 @@
pContainer->AppendTabParam(pParam.get());
}
-std::vector<CXFA_FFWidget*>
-CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray() {
- std::vector<CXFA_FFWidget*> widgets;
+std::vector<RetainPtr<CXFA_ContentLayoutItem>>
+CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderLayoutItems() {
+ std::vector<RetainPtr<CXFA_ContentLayoutItem>> items;
CXFA_LayoutItemIterator sIterator(m_pPageViewLayout.Get());
auto pParam = std::make_unique<CXFA_TabParam>(nullptr);
bool bCurrentItem = false;
bool bContentArea = false;
OrderContainer(&sIterator, nullptr, pParam.get(), &bCurrentItem,
&bContentArea, false);
- widgets.insert(widgets.end(), pParam->GetChildren().begin(),
- pParam->GetChildren().end());
+ items.reserve(pParam->GetChildren().size());
+ for (CXFA_FFWidget* widget : pParam->GetChildren())
+ items.emplace_back(widget->GetLayoutItem());
sIterator.Reset();
bCurrentItem = false;
@@ -447,9 +449,9 @@
pParam->ClearChildren();
OrderContainer(&sIterator, nullptr, pParam.get(), &bCurrentItem,
&bContentArea, true);
- widgets.insert(widgets.end(), pParam->GetChildren().begin(),
- pParam->GetChildren().end());
- return widgets;
+ for (CXFA_FFWidget* widget : pParam->GetChildren())
+ items.emplace_back(widget->GetLayoutItem());
+ return items;
}
CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget(
diff --git a/xfa/fxfa/cxfa_ffpageview.h b/xfa/fxfa/cxfa_ffpageview.h
index 5599af0..ad0ff26 100644
--- a/xfa/fxfa/cxfa_ffpageview.h
+++ b/xfa/fxfa/cxfa_ffpageview.h
@@ -98,7 +98,7 @@
CXFA_FFWidget* FindWidgetByName(const WideString& wsWidgetName,
CXFA_FFWidget* pRefWidget);
void CreateTabOrderWidgetArray();
- std::vector<CXFA_FFWidget*> CreateSpaceOrderWidgetArray();
+ std::vector<RetainPtr<CXFA_ContentLayoutItem>> CreateSpaceOrderLayoutItems();
CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem);
void OrderContainer(CXFA_LayoutItemIterator* sIterator,
CXFA_LayoutItem* pViewItem,