Replace CPDF_Page::GetView() with ClearView()

Rather than handing a caller an unowned reference, do cleanup by
extending the existing CPDF_Page::View interface. Result is that
logic moves from top-level fpdf files into the classes themselves,
avoiding a cast in the process.

Change-Id: I047cb130d9bcd09d2b5e16279d92797cc18167b8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/96314
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp
index 934c8cd..f8cbb1b 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -191,6 +191,11 @@
   m_pRenderContext.reset();
 }
 
+void CPDF_Page::ClearView() {
+  if (m_pView)
+    m_pView->ClearPage(this);
+}
+
 void CPDF_Page::UpdateDimensions() {
   CFX_FloatRect mediabox = GetBox(pdfium::page_object::kMediaBox);
   if (mediabox.IsEmpty())
diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h
index 447ec68..dfc5052 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -26,8 +26,11 @@
 
 class CPDF_Page final : public IPDF_Page, public CPDF_PageObjectHolder {
  public:
-  // Caller implements as desired, empty here due to layering.
-  class View : public Observable {};
+  // Caller implements as desired, exists here due to layering.
+  class View : public Observable {
+   public:
+    virtual void ClearPage(CPDF_Page* pPage) = 0;
+  };
 
   // Data for the render layer to attach to this page.
   class RenderContextIface {
@@ -92,8 +95,8 @@
   void SetRenderContext(std::unique_ptr<RenderContextIface> pContext);
   void ClearRenderContext();
 
-  View* GetView() const { return m_pView.Get(); }
   void SetView(View* pView) { m_pView.Reset(pView); }
+  void ClearView();
   void UpdateDimensions();
 
  private:
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index d16df90..5039735 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -63,6 +63,11 @@
   m_pAnnotList.reset();
 }
 
+void CPDFSDK_PageView::ClearPage(CPDF_Page* pPage) {
+  if (!IsBeingDestroyed())
+    GetFormFillEnv()->RemovePageView(pPage);
+}
+
 void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice,
                                        const CFX_Matrix& mtUser2Device,
                                        CPDF_RenderOptions* pOptions,
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index 1cb25d5..6e5f605 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -33,6 +33,9 @@
   CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv, IPDF_Page* page);
   ~CPDFSDK_PageView();
 
+  // CPDF_Page::View:
+  void ClearPage(CPDF_Page* pPage) override;
+
   void PageView_OnDraw(CFX_RenderDevice* pDevice,
                        const CFX_Matrix& mtUser2Device,
                        CPDF_RenderOptions* pOptions,
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 6def39b..89b04d5 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -716,15 +716,10 @@
   if (pPage->AsXFAPage())
     return;
 
-  CPDFSDK_PageView* pPageView =
-      static_cast<CPDFSDK_PageView*>(pPage->AsPDFPage()->GetView());
-  if (!pPageView || pPageView->IsBeingDestroyed())
-    return;
-
-  // This will delete the |pPageView| object. We must cleanup the PageView
-  // first because it will attempt to reset the View on the |pPage| during
-  // destruction.
-  pPageView->GetFormFillEnv()->RemovePageView(pPage.Get());
+  // This will delete the PageView object corresponding to |pPage|. We must
+  // cleanup the PageView before releasing the reference on |pPage| as it will
+  // attempt to reset the PageView during destruction.
+  pPage->AsPDFPage()->ClearView();
 }
 
 FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {