Add ObservedPtrs to PWL_CREATEPARAM

It's possible for both the provider and attached widget to be destroyed before
the PWL_CREATEPARAM objects which point to them. This causes issues when those
widgets access their attached widget or provider.

This CL wraps the pAttachedWidget and pProvider into ObservedPtrs so we will
know if the underlying pointer has gone away.

BUG=chromium:681351

Change-Id: Ib40445be9487dc3e89a66bb7407abdeed7d2c946
Reviewed-on: https://pdfium-review.googlesource.com/2270
Reviewed-by: Nicolás Peña <npm@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 12c0f60..4a05c56 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -964,6 +964,7 @@
     "fpdfsdk/pdfwindow/PWL_Utils.h",
     "fpdfsdk/pdfwindow/PWL_Wnd.cpp",
     "fpdfsdk/pdfwindow/PWL_Wnd.h",
+    "fpdfsdk/pdfwindow/cpwl_color.h",
   ]
   configs += [ ":pdfium_core_config" ]
   deps = [
diff --git a/fpdfsdk/cpdfsdk_widget.h b/fpdfsdk/cpdfsdk_widget.h
index b630738..69114d1 100644
--- a/fpdfsdk/cpdfsdk_widget.h
+++ b/fpdfsdk/cpdfsdk_widget.h
@@ -16,7 +16,7 @@
 #include "core/fxcrt/fx_string.h"
 #include "fpdfsdk/cpdfsdk_baannot.h"
 #include "fpdfsdk/pdfsdk_fieldaction.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
+#include "fpdfsdk/pdfwindow/cpwl_color.h"
 
 class CFX_RenderDevice;
 class CPDF_Annot;
diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp
index 7c1dec4..281057a 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_formfiller.cpp
@@ -289,7 +289,7 @@
 
   PWL_CREATEPARAM cp;
   cp.pParentWnd = nullptr;
-  cp.pProvider = this;
+  cp.pProvider.Reset(this);
   cp.rcRectWnd = GetPDFWindowRect();
 
   uint32_t dwCreateFlags = PWS_BORDER | PWS_BACKGROUND | PWS_VISIBLE;
@@ -359,7 +359,7 @@
     }
   } else {
     PWL_CREATEPARAM cp = GetCreateParam();
-    cp.pAttachedWidget = m_pWidget;
+    cp.pAttachedWidget.Reset(m_pWidget);
 
     CFFL_PrivateData* pPrivateData = new CFFL_PrivateData;
     pPrivateData->pWidget = m_pWidget;
diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.cpp b/fpdfsdk/pdfwindow/PWL_Wnd.cpp
index d3b3b9b..8fd7b16 100644
--- a/fpdfsdk/pdfwindow/PWL_Wnd.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Wnd.cpp
@@ -247,8 +247,8 @@
 }
 
 void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
-  if (m_sPrivateParam.pProvider == provider)
-    m_sPrivateParam.pProvider = nullptr;
+  if (m_sPrivateParam.pProvider.Get() == provider)
+    m_sPrivateParam.pProvider.Reset();
 }
 
 void CPWL_Wnd::Destroy() {
@@ -268,7 +268,7 @@
     m_bCreated = false;
   }
   DestroyMsgControl();
-  FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
+  m_sPrivateParam.Reset();
   m_Children.clear();
   m_pVScrollBar = nullptr;
 }
@@ -399,8 +399,10 @@
     rcWin.bottom += PWL_INVALIDATE_INFLATE;
 
     if (CFX_SystemHandler* pSH = GetSystemHandler()) {
-      if (CPDFSDK_Widget* widget = m_sPrivateParam.pAttachedWidget)
+      if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>(
+              m_sPrivateParam.pAttachedWidget.Get())) {
         pSH->InvalidateRect(widget, rcWin);
+      }
     }
   }
 }
@@ -800,7 +802,7 @@
 }
 
 IPWL_Provider* CPWL_Wnd::GetProvider() const {
-  return m_sPrivateParam.pProvider;
+  return m_sPrivateParam.pProvider.Get();
 }
 
 IPVT_FontMap* CPWL_Wnd::GetFontMap() const {
@@ -845,7 +847,6 @@
   CFX_Matrix mt = GetChildToRoot();
   if (IPWL_Provider* pProvider = GetProvider())
     mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
-
   return mt;
 }
 
diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.h b/fpdfsdk/pdfwindow/PWL_Wnd.h
index ce3d58c..dd4f321 100644
--- a/fpdfsdk/pdfwindow/PWL_Wnd.h
+++ b/fpdfsdk/pdfwindow/PWL_Wnd.h
@@ -11,10 +11,12 @@
 #include <vector>
 
 #include "core/fpdfdoc/cpdf_formcontrol.h"
+#include "core/fxcrt/cfx_observable.h"
 #include "core/fxcrt/fx_basic.h"
 #include "fpdfsdk/cfx_systemhandler.h"
+#include "fpdfsdk/cpdfsdk_widget.h"
+#include "fpdfsdk/pdfwindow/cpwl_color.h"
 
-class CPDFSDK_Widget;
 class CPWL_MsgControl;
 class CPWL_ScrollBar;
 class CPWL_Timer;
@@ -91,42 +93,17 @@
   CPWL_Dash(int32_t dash, int32_t gap, int32_t phase)
       : nDash(dash), nGap(gap), nPhase(phase) {}
 
+  void Reset() {
+    nDash = 0;
+    nGap = 0;
+    nPhase = 0;
+  }
+
   int32_t nDash;
   int32_t nGap;
   int32_t nPhase;
 };
 
-struct CPWL_Color {
-  CPWL_Color(int32_t type = COLORTYPE_TRANSPARENT,
-             FX_FLOAT color1 = 0.0f,
-             FX_FLOAT color2 = 0.0f,
-             FX_FLOAT color3 = 0.0f,
-             FX_FLOAT color4 = 0.0f)
-      : nColorType(type),
-        fColor1(color1),
-        fColor2(color2),
-        fColor3(color3),
-        fColor4(color4) {}
-
-  CPWL_Color(int32_t r, int32_t g, int32_t b)
-      : nColorType(COLORTYPE_RGB),
-        fColor1(r / 255.0f),
-        fColor2(g / 255.0f),
-        fColor3(b / 255.0f),
-        fColor4(0) {}
-
-  void ConvertColorType(int32_t other_nColorType);
-
-  /*
-  COLORTYPE_TRANSPARENT
-  COLORTYPE_RGB
-  COLORTYPE_CMYK
-  COLORTYPE_GRAY
-  */
-  int32_t nColorType;
-  FX_FLOAT fColor1, fColor2, fColor3, fColor4;
-};
-
 inline bool operator==(const CPWL_Color& c1, const CPWL_Color& c2) {
   return c1.nColorType == c2.nColorType && c1.fColor1 - c2.fColor1 < 0.0001 &&
          c1.fColor1 - c2.fColor1 > -0.0001 &&
@@ -161,7 +138,7 @@
 #define PWL_CBBUTTON_TRIANGLE_HALFLEN 3.0f
 #define PWL_INVALIDATE_INFLATE 2
 
-class IPWL_Provider {
+class IPWL_Provider : public CFX_Observable<IPWL_Provider> {
  public:
   virtual ~IPWL_Provider() {}
 
@@ -191,14 +168,38 @@
   PWL_CREATEPARAM();
   PWL_CREATEPARAM(const PWL_CREATEPARAM& other);
 
+  void Reset() {
+    rcRectWnd.Reset();
+    pSystemHandler = nullptr;
+    pFontMap = nullptr;
+    pProvider.Reset();
+    pFocusHandler = nullptr;
+    dwFlags = 0;
+    sBackgroundColor.Reset();
+    pAttachedWidget.Reset();
+    nBorderStyle = BorderStyle::SOLID;
+    dwBorderWidth = 0;
+    sBorderColor.Reset();
+    sTextColor.Reset();
+    sTextStrokeColor.Reset();
+    nTransparency = 0;
+    fFontSize = 0.0f;
+    sDash.Reset();
+    pAttachedData = nullptr;
+    pParentWnd = nullptr;
+    pMsgControl = nullptr;
+    eCursorType = 0;
+    mtChild.SetIdentity();
+  }
+
   CFX_FloatRect rcRectWnd;            // required
   CFX_SystemHandler* pSystemHandler;  // required
-  IPVT_FontMap* pFontMap;             // required for text window
-  IPWL_Provider* pProvider;           // required for self coordinate
+  IPVT_FontMap* pFontMap;             // required
+  IPWL_Provider::ObservedPtr pProvider;  // required
   IPWL_FocusHandler* pFocusHandler;   // optional
   uint32_t dwFlags;                   // optional
   CPWL_Color sBackgroundColor;        // optional
-  CPDFSDK_Widget* pAttachedWidget;    // required for no-reader framework
+  CPDFSDK_Widget::ObservedPtr pAttachedWidget;  // required
   BorderStyle nBorderStyle;           // optional
   int32_t dwBorderWidth;              // optional
   CPWL_Color sBorderColor;            // optional
diff --git a/fpdfsdk/pdfwindow/cpwl_color.h b/fpdfsdk/pdfwindow/cpwl_color.h
new file mode 100644
index 0000000..c1f9e6e
--- /dev/null
+++ b/fpdfsdk/pdfwindow/cpwl_color.h
@@ -0,0 +1,48 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef FPDFSDK_PDFWINDOW_CPWL_COLOR_H_
+#define FPDFSDK_PDFWINDOW_CPWL_COLOR_H_
+
+#include "core/fpdfdoc/cpdf_formcontrol.h"
+
+struct CPWL_Color {
+  CPWL_Color(int32_t type = COLORTYPE_TRANSPARENT,
+             FX_FLOAT color1 = 0.0f,
+             FX_FLOAT color2 = 0.0f,
+             FX_FLOAT color3 = 0.0f,
+             FX_FLOAT color4 = 0.0f)
+      : nColorType(type),
+        fColor1(color1),
+        fColor2(color2),
+        fColor3(color3),
+        fColor4(color4) {}
+
+  CPWL_Color(int32_t r, int32_t g, int32_t b)
+      : nColorType(COLORTYPE_RGB),
+        fColor1(r / 255.0f),
+        fColor2(g / 255.0f),
+        fColor3(b / 255.0f),
+        fColor4(0) {}
+
+  void ConvertColorType(int32_t other_nColorType);
+
+  void Reset() {
+    nColorType = COLORTYPE_TRANSPARENT;
+    fColor1 = 0.0f;
+    fColor2 = 0.0f;
+    fColor3 = 0.0f;
+    fColor4 = 0.0f;
+  }
+
+  int32_t nColorType;
+  FX_FLOAT fColor1;
+  FX_FLOAT fColor2;
+  FX_FLOAT fColor3;
+  FX_FLOAT fColor4;
+};
+
+#endif  // FPDFSDK_PDFWINDOW_CPWL_COLOR_H_