Observe FWL widgets in events/messages that destroy them.

Bug: chromium:995712
Change-Id: I3b1f8d9c31545aff4f2013cf6952791089cf65bc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59832
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/testing/resources/javascript/xfa_specific/bug_995712.evt b/testing/resources/javascript/xfa_specific/bug_995712.evt
new file mode 100644
index 0000000..3a0748a
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_995712.evt
@@ -0,0 +1,3 @@
+mousedown,left,100,100
+mouseup,left,100,100
+keycode,13
diff --git a/testing/resources/javascript/xfa_specific/bug_995712.in b/testing/resources/javascript/xfa_specific/bug_995712.in
new file mode 100644
index 0000000..c100b37
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_995712.in
@@ -0,0 +1,67 @@
+{{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 name="form1">
+    <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" name="subform2">
+      <field h="500mm" name="pushButton0" w="500mm" x="1mm" y="1mm">
+        <ui>
+          <button/>
+        </ui>
+        <caption>
+          <value>
+            <text>ClickMe</text>
+          </value>
+        </caption>
+        <border>
+          <edge stroke="raised"/>
+        </border>
+        <event activity="mouseUp">
+          <script contentType="application/x-javascript">
+            count_mouseUp += 1;
+            if (count_mouseUp == 2) {
+              f1 = xfa.resolveNode("xfa.form..field1");
+              xfa.host.setFocus(f1);
+              xfa.template.remerge();
+              xfa.host.openList(f1);
+            }
+          </script>
+        </event>
+      </field>
+      <field h="9.0001mm" name="field1" w="47.625mm" x="6.35mm" y="92.075mm">
+        <ui>
+          <choiceList/>
+        </ui>
+        <items>
+          <text>Foo</text>
+        </items>
+      </field>
+    </subform>
+    <event activity="docReady">
+      <script contentType="application/x-javascript">
+        count_mouseUp = 0;
+      </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/testing/resources/javascript/xfa_specific/bug_995712_expected.txt b/testing/resources/javascript/xfa_specific/bug_995712_expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_995712_expected.txt
diff --git a/xfa/fwl/cfwl_checkbox.cpp b/xfa/fwl/cfwl_checkbox.cpp
index ba8d4ae..f3ff43f 100644
--- a/xfa/fwl/cfwl_checkbox.cpp
+++ b/xfa/fwl/cfwl_checkbox.cpp
@@ -237,8 +237,9 @@
     default:
       break;
   }
-
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_CheckBox::OnDrawWidget(CXFA_Graphics* pGraphics,
diff --git a/xfa/fwl/cfwl_combobox.cpp b/xfa/fwl/cfwl_combobox.cpp
index 9521e2d..808c8c2 100644
--- a/xfa/fwl/cfwl_combobox.cpp
+++ b/xfa/fwl/cfwl_combobox.cpp
@@ -221,6 +221,8 @@
   if (bActivate) {
     CFWL_Event preEvent(CFWL_Event::Type::PreDropDown, this);
     DispatchEvent(&preEvent);
+    if (!preEvent.GetSrcTarget())
+      return;
 
     CFWL_ComboList* pComboList = m_pListBox.get();
     int32_t iItems = pComboList->CountItems(nullptr);
@@ -479,7 +481,8 @@
     default:
       break;
   }
-  if (backDefault)
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (backDefault && pMessage->GetDstTarget())
     CFWL_Widget::OnProcessMessage(pMessage);
 }
 
diff --git a/xfa/fwl/cfwl_datetimepicker.cpp b/xfa/fwl/cfwl_datetimepicker.cpp
index a3fbc9c..b711eba 100644
--- a/xfa/fwl/cfwl_datetimepicker.cpp
+++ b/xfa/fwl/cfwl_datetimepicker.cpp
@@ -378,8 +378,9 @@
     default:
       break;
   }
-
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_DateTimePicker::OnDrawWidget(CXFA_Graphics* pGraphics,
diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp
index 5b70b98..8b70f4d 100644
--- a/xfa/fwl/cfwl_edit.cpp
+++ b/xfa/fwl/cfwl_edit.cpp
@@ -1039,7 +1039,9 @@
     default:
       break;
   }
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) {
diff --git a/xfa/fwl/cfwl_event.h b/xfa/fwl/cfwl_event.h
index 0c4d23e..832c01f 100644
--- a/xfa/fwl/cfwl_event.h
+++ b/xfa/fwl/cfwl_event.h
@@ -7,14 +7,8 @@
 #ifndef XFA_FWL_CFWL_EVENT_H_
 #define XFA_FWL_CFWL_EVENT_H_
 
-#include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/fx_system.h"
-#include "xfa/fwl/cfwl_messagekey.h"
-#include "xfa/fwl/cfwl_messagemouse.h"
-
-class CXFA_Graphics;
-class CFWL_Widget;
+#include "core/fxcrt/observed_ptr.h"
+#include "xfa/fwl/cfwl_widget.h"
 
 class CFWL_Event {
  public:
@@ -44,8 +38,8 @@
 
  private:
   const Type m_type;
-  UnownedPtr<CFWL_Widget> const m_pSrcTarget;
-  UnownedPtr<CFWL_Widget> const m_pDstTarget;
+  ObservedPtr<CFWL_Widget> const m_pSrcTarget;
+  ObservedPtr<CFWL_Widget> const m_pDstTarget;
 };
 
 #endif  // XFA_FWL_CFWL_EVENT_H_
diff --git a/xfa/fwl/cfwl_eventmouse.h b/xfa/fwl/cfwl_eventmouse.h
index 170f39a..273856f 100644
--- a/xfa/fwl/cfwl_eventmouse.h
+++ b/xfa/fwl/cfwl_eventmouse.h
@@ -8,6 +8,7 @@
 #define XFA_FWL_CFWL_EVENTMOUSE_H_
 
 #include "xfa/fwl/cfwl_event.h"
+#include "xfa/fwl/cfwl_messagemouse.h"
 
 class CFWL_EventMouse final : public CFWL_Event {
  public:
diff --git a/xfa/fwl/cfwl_listbox.cpp b/xfa/fwl/cfwl_listbox.cpp
index 8f51f5b..4de06db 100644
--- a/xfa/fwl/cfwl_listbox.cpp
+++ b/xfa/fwl/cfwl_listbox.cpp
@@ -687,7 +687,9 @@
     default:
       break;
   }
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_ListBox::OnProcessEvent(CFWL_Event* pEvent) {
diff --git a/xfa/fwl/cfwl_message.h b/xfa/fwl/cfwl_message.h
index 2242831..69f7bf5 100644
--- a/xfa/fwl/cfwl_message.h
+++ b/xfa/fwl/cfwl_message.h
@@ -11,9 +11,8 @@
 
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
-#include "core/fxcrt/unowned_ptr.h"
-
-class CFWL_Widget;
+#include "core/fxcrt/observed_ptr.h"
+#include "xfa/fwl/cfwl_widget.h"
 
 class CFWL_Message {
  public:
@@ -24,8 +23,8 @@
   Type GetType() const { return m_type; }
   CFWL_Widget* GetSrcTarget() const { return m_pSrcTarget.Get(); }
   CFWL_Widget* GetDstTarget() const { return m_pDstTarget.Get(); }
-  void SetSrcTarget(CFWL_Widget* pWidget) { m_pSrcTarget = pWidget; }
-  void SetDstTarget(CFWL_Widget* pWidget) { m_pDstTarget = pWidget; }
+  void SetSrcTarget(CFWL_Widget* pWidget) { m_pSrcTarget.Reset(pWidget); }
+  void SetDstTarget(CFWL_Widget* pWidget) { m_pDstTarget.Reset(pWidget); }
 
  protected:
   CFWL_Message(Type type, CFWL_Widget* pSrcTarget, CFWL_Widget* pDstTarget);
@@ -34,8 +33,8 @@
 
  private:
   const Type m_type;
-  UnownedPtr<CFWL_Widget> m_pSrcTarget;
-  UnownedPtr<CFWL_Widget> m_pDstTarget;
+  ObservedPtr<CFWL_Widget> m_pSrcTarget;
+  ObservedPtr<CFWL_Widget> m_pDstTarget;
 };
 
 #endif  // XFA_FWL_CFWL_MESSAGE_H_
diff --git a/xfa/fwl/cfwl_monthcalendar.cpp b/xfa/fwl/cfwl_monthcalendar.cpp
index a856af2..76d9156 100644
--- a/xfa/fwl/cfwl_monthcalendar.cpp
+++ b/xfa/fwl/cfwl_monthcalendar.cpp
@@ -710,7 +710,9 @@
     default:
       break;
   }
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_MonthCalendar::OnDrawWidget(CXFA_Graphics* pGraphics,
diff --git a/xfa/fwl/cfwl_pushbutton.cpp b/xfa/fwl/cfwl_pushbutton.cpp
index 947b24d..980a89d 100644
--- a/xfa/fwl/cfwl_pushbutton.cpp
+++ b/xfa/fwl/cfwl_pushbutton.cpp
@@ -134,7 +134,9 @@
     default:
       break;
   }
-  CFWL_Widget::OnProcessMessage(pMessage);
+  // Dst target could be |this|, continue only if not destroyed by above.
+  if (pMessage->GetDstTarget())
+    CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_PushButton::OnDrawWidget(CXFA_Graphics* pGraphics,
@@ -222,6 +224,8 @@
   CFWL_EventMouse wmMouse(this);
   wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
   DispatchEvent(&wmMouse);
+  if (!wmMouse.GetSrcTarget())
+    return;
 
   CFWL_Event wmClick(CFWL_Event::Type::Click, this);
   DispatchEvent(&wmClick);
diff --git a/xfa/fwl/cfwl_widget.h b/xfa/fwl/cfwl_widget.h
index 28a3aa3..c36cd8f 100644
--- a/xfa/fwl/cfwl_widget.h
+++ b/xfa/fwl/cfwl_widget.h
@@ -11,15 +11,23 @@
 
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/observed_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "xfa/fde/cfde_data.h"
-#include "xfa/fwl/cfwl_event.h"
 #include "xfa/fwl/cfwl_themepart.h"
 #include "xfa/fwl/cfwl_widgetmgr.h"
 #include "xfa/fwl/cfwl_widgetproperties.h"
 #include "xfa/fwl/fwl_widgethit.h"
 #include "xfa/fwl/ifwl_widgetdelegate.h"
 
+class CFWL_App;
+class CFWL_AppImp;
+class CFWL_Event;
+class CFWL_MessageKey;
+class CFWL_Widget;
+class CFWL_WidgetMgr;
+class IFWL_ThemeProvider;
+
 enum class FWL_Type {
   Unknown = 0,
 
@@ -40,15 +48,8 @@
   ToolTip
 };
 
-class CFWL_App;
-class CFWL_AppImp;
-class CFWL_MessageKey;
-class CFWL_Widget;
-class CFWL_WidgetMgr;
-class IFWL_ThemeProvider;
-
 // NOTE: CFWL_Widget serves as its own delegate until replaced at runtime.
-class CFWL_Widget : public IFWL_WidgetDelegate {
+class CFWL_Widget : public Observable, public IFWL_WidgetDelegate {
  public:
   class AdapterIface {
    public:
diff --git a/xfa/fwl/cfwl_widgetmgr.cpp b/xfa/fwl/cfwl_widgetmgr.cpp
index 1eefe37..cb41430 100644
--- a/xfa/fwl/cfwl_widgetmgr.cpp
+++ b/xfa/fwl/cfwl_widgetmgr.cpp
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "third_party/base/ptr_util.h"
 #include "xfa/fwl/cfwl_app.h"
+#include "xfa/fwl/cfwl_message.h"
 #include "xfa/fwl/cfwl_notedriver.h"
 
 CFWL_WidgetMgr::CFWL_WidgetMgr(AdapterIface* pAdapterNative)