Annotation deleted while retrieving it in JS

Widgets as returned from GetWidgets() can pop out of existence
unexpectedly, so always return observed pointers.  This extends
the same pattern used elsewhere in the file to all occurrences.

BUG=679642

Review-Url: https://codereview.chromium.org/2624933002
diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp
index a2f07b4..7b77180 100644
--- a/fpdfsdk/cpdfsdk_interform.cpp
+++ b/fpdfsdk/cpdfsdk_interform.cpp
@@ -117,7 +117,7 @@
 
 void CPDFSDK_InterForm::GetWidgets(
     const CFX_WideString& sFieldName,
-    std::vector<CPDFSDK_Widget*>* widgets) const {
+    std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
   for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) {
     CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
     ASSERT(pFormField);
@@ -127,13 +127,13 @@
 
 void CPDFSDK_InterForm::GetWidgets(
     CPDF_FormField* pField,
-    std::vector<CPDFSDK_Widget*>* widgets) const {
+    std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
   for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
     CPDF_FormControl* pFormCtrl = pField->GetControl(i);
     ASSERT(pFormCtrl);
     CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
     if (pWidget)
-      widgets->push_back(pWidget);
+      widgets->emplace_back(pWidget);
   }
 }
 
diff --git a/fpdfsdk/cpdfsdk_interform.h b/fpdfsdk/cpdfsdk_interform.h
index 9f35d56..032399c 100644
--- a/fpdfsdk/cpdfsdk_interform.h
+++ b/fpdfsdk/cpdfsdk_interform.h
@@ -15,6 +15,7 @@
 #include "core/fpdfdoc/ipdf_formnotify.h"
 #include "core/fxcrt/fx_basic.h"
 #include "core/fxge/fx_dib.h"
+#include "fpdfsdk/cpdfsdk_widget.h"
 
 class CPDF_Dictionary;
 class CPDF_FormControl;
@@ -22,7 +23,6 @@
 class CPDF_InterForm;
 class CPDF_Object;
 class CPDFSDK_FormFillEnvironment;
-class CPDFSDK_Widget;
 
 #ifdef PDF_ENABLE_XFA
 class CPDFSDK_XFAWidget;
@@ -42,9 +42,9 @@
   CPDFSDK_Widget* GetSibling(CPDFSDK_Widget* pWidget, bool bNext) const;
   CPDFSDK_Widget* GetWidget(CPDF_FormControl* pControl) const;
   void GetWidgets(const CFX_WideString& sFieldName,
-                  std::vector<CPDFSDK_Widget*>* widgets) const;
+                  std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const;
   void GetWidgets(CPDF_FormField* pField,
-                  std::vector<CPDFSDK_Widget*>* widgets) const;
+                  std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const;
 
   void AddMap(CPDF_FormControl* pControl, CPDFSDK_Widget* pWidget);
   void RemoveMap(CPDF_FormControl* pControl);
diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp
index 29f9764..7e4dc26 100644
--- a/fpdfsdk/javascript/Document.cpp
+++ b/fpdfsdk/javascript/Document.cpp
@@ -506,12 +506,16 @@
   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
   CFX_WideString sFieldName = params[0].ToCFXWideString(pRuntime);
   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
-  std::vector<CPDFSDK_Widget*> widgets;
+  std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
   pInterForm->GetWidgets(sFieldName, &widgets);
   if (widgets.empty())
     return true;
 
-  for (CPDFSDK_Widget* pWidget : widgets) {
+  for (const auto& pAnnot : widgets) {
+    CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot.Get());
+    if (!pWidget)
+      continue;
+
     CFX_FloatRect rcAnnot = pWidget->GetRect();
     --rcAnnot.left;
     --rcAnnot.bottom;
diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp
index f8ac479..e04cbd6 100644
--- a/fpdfsdk/javascript/Field.cpp
+++ b/fpdfsdk/javascript/Field.cpp
@@ -265,24 +265,28 @@
   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
 
   if (bResetAP) {
-    std::vector<CPDFSDK_Widget*> widgets;
+    std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
     pInterForm->GetWidgets(pFormField, &widgets);
 
     int nFieldType = pFormField->GetFieldType();
     if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_TEXTFIELD) {
-      for (CPDFSDK_Annot* pAnnot : widgets) {
-        bool bFormatted = false;
-        CPDFSDK_Annot::ObservedPtr pObserved(pAnnot);
-        CFX_WideString sValue =
-            static_cast<CPDFSDK_Widget*>(pObserved.Get())->OnFormat(bFormatted);
+      for (auto& pObserved : widgets) {
         if (pObserved) {
-          static_cast<CPDFSDK_Widget*>(pObserved.Get())
-              ->ResetAppearance(bFormatted ? &sValue : nullptr, false);
+          bool bFormatted = false;
+          CFX_WideString sValue = static_cast<CPDFSDK_Widget*>(pObserved.Get())
+                                      ->OnFormat(bFormatted);
+          if (pObserved) {  // Not redundant, may be clobbered by OnFormat.
+            static_cast<CPDFSDK_Widget*>(pObserved.Get())
+                ->ResetAppearance(bFormatted ? &sValue : nullptr, false);
+          }
         }
       }
     } else {
-      for (CPDFSDK_Widget* pWidget : widgets) {
-        pWidget->ResetAppearance(nullptr, false);
+      for (auto& pObserved : widgets) {
+        if (pObserved) {
+          static_cast<CPDFSDK_Widget*>(pObserved.Get())
+              ->ResetAppearance(nullptr, false);
+        }
       }
     }
   }
@@ -291,16 +295,18 @@
     // Refresh the widget list. The calls in |bResetAP| may have caused widgets
     // to be removed from the list. We need to call |GetWidgets| again to be
     // sure none of the widgets have been deleted.
-    std::vector<CPDFSDK_Widget*> widgets;
+    std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
     pInterForm->GetWidgets(pFormField, &widgets);
 
     // TODO(dsinclair): Determine if all widgets share the same
     // CPDFSDK_InterForm. If that's the case, we can move the code to
     // |GetFormFillEnv| out of the loop.
-    for (CPDFSDK_Widget* pWidget : widgets) {
-      pWidget->GetInterForm()
-          ->GetFormFillEnv()
-          ->UpdateAllViews(nullptr, pWidget);
+    for (auto& pObserved : widgets) {
+      if (pObserved) {
+        CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
+        pWidget->GetInterForm()->GetFormFillEnv()->UpdateAllViews(nullptr,
+                                                                  pWidget);
+      }
     }
   }
 
@@ -1803,8 +1809,10 @@
 }
 
 bool Field::page(IJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError) {
-  if (!vp.IsGetting())
+  if (!vp.IsGetting()) {
+    sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
     return false;
+  }
 
   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   if (FieldArray.empty())
@@ -1814,9 +1822,8 @@
   if (!pFormField)
     return false;
 
-  std::vector<CPDFSDK_Widget*> widgets;
+  std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
   m_pFormFillEnv->GetInterForm()->GetWidgets(pFormField, &widgets);
-
   if (widgets.empty()) {
     vp << (int32_t)-1;
     return true;
@@ -1824,13 +1831,21 @@
 
   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
   CJS_Array PageArray;
-  for (size_t i = 0; i < widgets.size(); ++i) {
-    CPDFSDK_PageView* pPageView = widgets[i]->GetPageView();
+  int i = 0;
+  for (const auto& pObserved : widgets) {
+    if (!pObserved) {
+      sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
+      return false;
+    }
+
+    auto pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
+    CPDFSDK_PageView* pPageView = pWidget->GetPageView();
     if (!pPageView)
       return false;
 
     PageArray.SetElement(
         pRuntime, i, CJS_Value(pRuntime, (int32_t)pPageView->GetPageIndex()));
+    ++i;
   }
 
   vp << PageArray;