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,