Observe CXFA_FFWidget across UpdateFWLData() calls.

It may reenter JS and mutate the page.

Bug: chromium:1038000, chromium:995081
Change-Id: I14a4fdb7e4f6a499c9713bfe02f1cda2d3b5e32e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64531
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp
index 0336d28..fd485db 100644
--- a/xfa/fxfa/cxfa_ffcombobox.cpp
+++ b/xfa/fxfa/cxfa_ffcombobox.cpp
@@ -107,10 +107,11 @@
 }
 
 bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
   if (!ProcessCommittedData())
     UpdateFWLData();
 
-  return CXFA_FFField::OnKillFocus(pNewWidget);
+  return pNewWatched && CXFA_FFField::OnKillFocus(pNewWatched.Get());
 }
 
 void CXFA_FFComboBox::OpenDropDownList() {
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index ccf17bf..31141bf 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -196,14 +196,21 @@
 
 void CXFA_FFDocView::UpdateUIDisplay(CXFA_Node* pNode, CXFA_FFWidget* pExcept) {
   CXFA_FFWidget* pWidget = GetWidgetForNode(pNode);
-  for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
+  CXFA_FFWidget* pNext = nullptr;
+  for (; pWidget; pWidget = pNext) {
+    pNext = pWidget->GetNextFFWidget();
     if (pWidget == pExcept || !pWidget->IsLoaded() ||
         (pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton &&
          pWidget->IsFocused())) {
       continue;
     }
-    pWidget->UpdateFWLData();
-    pWidget->InvalidateRect();
+    ObservedPtr<CXFA_FFWidget> pWatched(pWidget);
+    ObservedPtr<CXFA_FFWidget> pWatchedNext(pNext);
+    pWatched->UpdateFWLData();
+    if (pWatched)
+      pWatched->InvalidateRect();
+    if (!pWatchedNext)
+      break;
   }
 }
 
@@ -285,6 +292,7 @@
   if (pNewFocus == m_pFocusWidget)
     return false;
 
+  ObservedPtr<CXFA_FFWidget> pNewWatched(pNewFocus);
   if (m_pFocusWidget) {
     CXFA_ContentLayoutItem* pItem = m_pFocusWidget->GetLayoutItem();
     if (pItem->TestStatusBits(XFA_WidgetStatus_Visible) &&
@@ -296,22 +304,23 @@
     }
   }
   if (m_pFocusWidget) {
-    if (!m_pFocusWidget->OnKillFocus(pNewFocus))
+    if (!m_pFocusWidget->OnKillFocus(pNewWatched.Get()))
       return false;
   }
 
-  if (pNewFocus) {
-    if (pNewFocus->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible)) {
-      if (!pNewFocus->IsLoaded())
-        pNewFocus->LoadWidget();
-      if (!pNewFocus->OnSetFocus(m_pFocusWidget.Get()))
-        pNewFocus = nullptr;
+  if (pNewWatched) {
+    if (pNewWatched->GetLayoutItem()->TestStatusBits(
+            XFA_WidgetStatus_Visible)) {
+      if (!pNewWatched->IsLoaded())
+        pNewWatched->LoadWidget();
+      if (!pNewWatched->OnSetFocus(m_pFocusWidget.Get()))
+        pNewWatched.Reset();
     }
   }
-  if (pNewFocus) {
-    CXFA_Node* node = pNewFocus->GetNode();
+  if (pNewWatched) {
+    CXFA_Node* node = pNewWatched->GetNode();
     m_pFocusNode = node->IsWidgetReady() ? node : nullptr;
-    m_pFocusWidget.Reset(pNewFocus);
+    m_pFocusWidget.Reset(pNewWatched.Get());
   } else {
     m_pFocusNode = nullptr;
     m_pFocusWidget.Reset();
@@ -321,9 +330,7 @@
 }
 
 void CXFA_FFDocView::SetFocusNode(CXFA_Node* node) {
-  CXFA_FFWidget* pNewFocus = nullptr;
-  if (node)
-    pNewFocus = GetWidgetForNode(node);
+  CXFA_FFWidget* pNewFocus = node ? GetWidgetForNode(node) : nullptr;
   if (!SetFocus(pNewFocus))
     return;
 
diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp
index 767ef2a..217fe2c 100644
--- a/xfa/fxfa/cxfa_fffield.cpp
+++ b/xfa/fxfa/cxfa_fffield.cpp
@@ -506,13 +506,14 @@
 }
 
 bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
   if (GetNormalWidget()) {
     SendMessageToFWLWidget(
         pdfium::MakeUnique<CFWL_MessageKillFocus>(nullptr, GetNormalWidget()));
     GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
     InvalidateRect();
   }
-  return CXFA_FFWidget::OnKillFocus(pNewWidget);
+  return pNewWatched && CXFA_FFWidget::OnKillFocus(pNewWatched.Get());
 }
 
 bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp
index 38e6b1a..ede1bc5 100644
--- a/xfa/fxfa/cxfa_fflistbox.cpp
+++ b/xfa/fxfa/cxfa_fflistbox.cpp
@@ -71,10 +71,11 @@
 }
 
 bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
+  ObservedPtr<CXFA_FFWidget> pWatched(pNewFocus);
   if (!ProcessCommittedData())
     UpdateFWLData();
 
-  return CXFA_FFField::OnKillFocus(pNewFocus);
+  return pWatched && CXFA_FFField::OnKillFocus(pWatched.Get());
 }
 
 bool CXFA_FFListBox::CommitData() {
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index cf3eb61..d9af369 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -152,13 +152,14 @@
 }
 
 bool CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) {
+  ObservedPtr<CXFA_FFWidget> pWatched(pOldWidget);
   GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_TextEditValueChanged);
   if (!IsFocused()) {
     GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused);
     UpdateFWLData();
     InvalidateRect();
   }
-  if (!CXFA_FFWidget::OnSetFocus(pOldWidget))
+  if (!CXFA_FFWidget::OnSetFocus(pWatched.Get()))
     return false;
 
   SendMessageToFWLWidget(
@@ -168,6 +169,7 @@
 }
 
 bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  ObservedPtr<CXFA_FFWidget> pWatched(pNewWidget);
   SendMessageToFWLWidget(
       pdfium::MakeUnique<CFWL_MessageKillFocus>(nullptr, GetNormalWidget()));
 
@@ -177,7 +179,7 @@
   UpdateFWLData();
   InvalidateRect();
 
-  if (!CXFA_FFWidget::OnKillFocus(pNewWidget))
+  if (!CXFA_FFWidget::OnKillFocus(pWatched.Get()))
     return false;
 
   GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_TextEditValueChanged);