Add CFWL_Widget::ScopedUpdateLock.

Scoper to help call CFWL_Widget::LockUpdate() and UnlockUpdate(). With
all calls going through ScopedUpdateLock, LockUpdate() and
UnlockUpdate() can become private.

Change-Id: I1477471d82384608691e8ae7727787870da0c2ad
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/62493
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/xfa/fwl/cfwl_combobox.cpp b/xfa/fwl/cfwl_combobox.cpp
index 7c77fc5..9c5edf4 100644
--- a/xfa/fwl/cfwl_combobox.cpp
+++ b/xfa/fwl/cfwl_combobox.cpp
@@ -30,14 +30,12 @@
 #include "xfa/fwl/ifwl_themeprovider.h"
 
 CFWL_ComboBox::CFWL_ComboBox(const CFWL_App* app)
-    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
-      m_iCurSel(-1),
-      m_iBtnState(CFWL_PartState_Normal) {
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr) {
   InitComboList();
   InitComboEdit();
 }
 
-CFWL_ComboBox::~CFWL_ComboBox() {}
+CFWL_ComboBox::~CFWL_ComboBox() = default;
 
 FWL_Type CFWL_ComboBox::GetClassID() const {
   return FWL_Type::ComboBox;
@@ -309,9 +307,8 @@
 
   if (m_iCurSel >= 0) {
     CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-    m_pEdit->LockUpdate();
+    ScopedUpdateLock update_lock(m_pEdit.get());
     m_pEdit->SetText(hItem ? hItem->GetText() : WideString());
-    m_pEdit->UnlockUpdate();
   }
   m_pEdit->Update();
 }
diff --git a/xfa/fwl/cfwl_combobox.h b/xfa/fwl/cfwl_combobox.h
index ce3414b..39c952c 100644
--- a/xfa/fwl/cfwl_combobox.h
+++ b/xfa/fwl/cfwl_combobox.h
@@ -123,8 +123,8 @@
   CFX_RectF m_rtBtn;
   std::unique_ptr<CFWL_ComboEdit> m_pEdit;
   std::unique_ptr<CFWL_ComboList> m_pListBox;
-  int32_t m_iCurSel;
-  int32_t m_iBtnState;
+  int32_t m_iCurSel = -1;
+  int32_t m_iBtnState = CFWL_PartState_Normal;
 };
 
 #endif  // XFA_FWL_CFWL_COMBOBOX_H_
diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp
index 8b70f4d..2fc74c7 100644
--- a/xfa/fwl/cfwl_edit.cpp
+++ b/xfa/fwl/cfwl_edit.cpp
@@ -665,24 +665,26 @@
   if (bShowHorz) {
     CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect();
     if (rtScroll.width < contents_bounds.width) {
-      m_pHorzScrollBar->LockUpdate();
-      float fRange = contents_bounds.width - rtScroll.width;
-      m_pHorzScrollBar->SetRange(0.0f, fRange);
+      {
+        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
+        float fRange = contents_bounds.width - rtScroll.width;
+        m_pHorzScrollBar->SetRange(0.0f, fRange);
 
-      float fPos = pdfium::clamp(m_fScrollOffsetX, 0.0f, fRange);
-      m_pHorzScrollBar->SetPos(fPos);
-      m_pHorzScrollBar->SetTrackPos(fPos);
-      m_pHorzScrollBar->SetPageSize(rtScroll.width);
-      m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
-      m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
-      m_pHorzScrollBar->UnlockUpdate();
+        float fPos = pdfium::clamp(m_fScrollOffsetX, 0.0f, fRange);
+        m_pHorzScrollBar->SetPos(fPos);
+        m_pHorzScrollBar->SetTrackPos(fPos);
+        m_pHorzScrollBar->SetPageSize(rtScroll.width);
+        m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
+        m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
+      }
       m_pHorzScrollBar->Update();
       pRepaint = m_pHorzScrollBar.get();
     } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
-      m_pHorzScrollBar->LockUpdate();
-      m_pHorzScrollBar->SetRange(0, -1);
-      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled);
-      m_pHorzScrollBar->UnlockUpdate();
+      {
+        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
+        m_pHorzScrollBar->SetRange(0, -1);
+        m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled);
+      }
       m_pHorzScrollBar->Update();
       pRepaint = m_pHorzScrollBar.get();
     }
@@ -691,26 +693,28 @@
   if (bShowVert) {
     CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect();
     if (rtScroll.height < contents_bounds.height) {
-      m_pVertScrollBar->LockUpdate();
-      float fStep = m_EdtEngine.GetLineSpace();
-      float fRange =
-          std::max(contents_bounds.height - m_rtEngine.height, fStep);
+      {
+        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
+        float fStep = m_EdtEngine.GetLineSpace();
+        float fRange =
+            std::max(contents_bounds.height - m_rtEngine.height, fStep);
 
-      m_pVertScrollBar->SetRange(0.0f, fRange);
-      float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange);
-      m_pVertScrollBar->SetPos(fPos);
-      m_pVertScrollBar->SetTrackPos(fPos);
-      m_pVertScrollBar->SetPageSize(rtScroll.height);
-      m_pVertScrollBar->SetStepSize(fStep);
-      m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
-      m_pVertScrollBar->UnlockUpdate();
+        m_pVertScrollBar->SetRange(0.0f, fRange);
+        float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange);
+        m_pVertScrollBar->SetPos(fPos);
+        m_pVertScrollBar->SetTrackPos(fPos);
+        m_pVertScrollBar->SetPageSize(rtScroll.height);
+        m_pVertScrollBar->SetStepSize(fStep);
+        m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
+      }
       m_pVertScrollBar->Update();
       pRepaint = m_pVertScrollBar.get();
     } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
-      m_pVertScrollBar->LockUpdate();
-      m_pVertScrollBar->SetRange(0, -1);
-      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled);
-      m_pVertScrollBar->UnlockUpdate();
+      {
+        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
+        m_pVertScrollBar->SetRange(0, -1);
+        m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled);
+      }
       m_pVertScrollBar->Update();
       pRepaint = m_pVertScrollBar.get();
     }
diff --git a/xfa/fwl/cfwl_widget.cpp b/xfa/fwl/cfwl_widget.cpp
index 0c3dee3..a252cd2 100644
--- a/xfa/fwl/cfwl_widget.cpp
+++ b/xfa/fwl/cfwl_widget.cpp
@@ -390,3 +390,12 @@
 
 void CFWL_Widget::OnDrawWidget(CXFA_Graphics* pGraphics,
                                const CFX_Matrix& matrix) {}
+
+CFWL_Widget::ScopedUpdateLock::ScopedUpdateLock(CFWL_Widget* widget)
+    : widget_(widget) {
+  widget_->LockUpdate();
+}
+
+CFWL_Widget::ScopedUpdateLock::~ScopedUpdateLock() {
+  widget_->UnlockUpdate();
+}
diff --git a/xfa/fwl/cfwl_widget.h b/xfa/fwl/cfwl_widget.h
index c36cd8f..cc6ee3b 100644
--- a/xfa/fwl/cfwl_widget.h
+++ b/xfa/fwl/cfwl_widget.h
@@ -59,6 +59,15 @@
     virtual void GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) = 0;
   };
 
+  class ScopedUpdateLock {
+   public:
+    explicit ScopedUpdateLock(CFWL_Widget* widget);
+    ~ScopedUpdateLock();
+
+   private:
+    UnownedPtr<CFWL_Widget> const widget_;
+  };
+
   ~CFWL_Widget() override;
 
   virtual FWL_Type GetClassID() const = 0;
@@ -100,12 +109,6 @@
   uint32_t GetStylesEx() const;
   uint32_t GetStates() const;
 
-  void LockUpdate() { m_iLock++; }
-  void UnlockUpdate() {
-    if (IsLocked())
-      m_iLock--;
-  }
-
   CFX_PointF TransformTo(CFWL_Widget* pWidget, const CFX_PointF& point);
   CFX_Matrix GetMatrix() const;
   IFWL_ThemeProvider* GetThemeProvider() const {
@@ -166,6 +169,12 @@
   int32_t m_iLock = 0;
 
  private:
+  void LockUpdate() { m_iLock++; }
+  void UnlockUpdate() {
+    if (IsLocked())
+      m_iLock--;
+  }
+
   CFWL_Widget* GetParent() const { return m_pWidgetMgr->GetParentWidget(this); }
   CFX_SizeF GetOffsetFromParent(CFWL_Widget* pParent);
   void DrawBackground(CXFA_Graphics* pGraphics,
diff --git a/xfa/fxfa/cxfa_ffbarcode.cpp b/xfa/fxfa/cxfa_ffbarcode.cpp
index 7663ee0..69646c2 100644
--- a/xfa/fxfa/cxfa_ffbarcode.cpp
+++ b/xfa/fxfa/cxfa_ffbarcode.cpp
@@ -149,11 +149,13 @@
   pNoteDriver->RegisterEventTarget(pFWLBarcode, pFWLBarcode);
   m_pOldDelegate = pFWLBarcode->GetDelegate();
   pFWLBarcode->SetDelegate(this);
-  pFWLBarcode->LockUpdate();
 
-  pFWLBarcode->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
-  UpdateWidgetProperty();
-  pFWLBarcode->UnlockUpdate();
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pFWLBarcode);
+    pFWLBarcode->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
+    UpdateWidgetProperty();
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffcheckbutton.cpp b/xfa/fxfa/cxfa_ffcheckbutton.cpp
index 9d1467d..2245177 100644
--- a/xfa/fxfa/cxfa_ffcheckbutton.cpp
+++ b/xfa/fxfa/cxfa_ffcheckbutton.cpp
@@ -44,10 +44,12 @@
   if (m_pNode->IsRadioButton())
     pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF);
 
-  pCheckBox->LockUpdate();
-  UpdateWidgetProperty();
-  SetFWLCheckState(m_pNode->GetCheckState());
-  pCheckBox->UnlockUpdate();
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pCheckBox);
+    UpdateWidgetProperty();
+    SetFWLCheckState(m_pNode->GetCheckState());
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp
index 38203b1..0336d28 100644
--- a/xfa/fxfa/cxfa_ffcombobox.cpp
+++ b/xfa/fxfa/cxfa_ffcombobox.cpp
@@ -55,19 +55,21 @@
   pNoteDriver->RegisterEventTarget(pComboBox, pComboBox);
   m_pOldDelegate = pComboBox->GetDelegate();
   pComboBox->SetDelegate(this);
-  pComboBox->LockUpdate();
 
-  for (const auto& label : m_pNode->GetChoiceListItems(false))
-    pComboBox->AddString(label);
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pComboBox);
+    for (const auto& label : m_pNode->GetChoiceListItems(false))
+      pComboBox->AddString(label);
 
-  std::vector<int32_t> iSelArray = m_pNode->GetSelectedItems();
-  if (iSelArray.empty())
-    pComboBox->SetEditText(m_pNode->GetValue(XFA_VALUEPICTURE_Raw));
-  else
-    pComboBox->SetCurSel(iSelArray.front());
+    std::vector<int32_t> iSelArray = m_pNode->GetSelectedItems();
+    if (iSelArray.empty())
+      pComboBox->SetEditText(m_pNode->GetValue(XFA_VALUEPICTURE_Raw));
+    else
+      pComboBox->SetCurSel(iSelArray.front());
 
-  UpdateWidgetProperty();
-  pComboBox->UnlockUpdate();
+    UpdateWidgetProperty();
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
index 45f9b9f..ba05835 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.cpp
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
@@ -51,28 +51,31 @@
   pNoteDriver->RegisterEventTarget(pWidget, pWidget);
   m_pOldDelegate = pWidget->GetDelegate();
   pWidget->SetDelegate(this);
-  pWidget->LockUpdate();
 
-  WideString wsText = m_pNode->GetValue(XFA_VALUEPICTURE_Display);
-  pWidget->SetEditText(wsText);
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pWidget);
+    WideString wsText = m_pNode->GetValue(XFA_VALUEPICTURE_Display);
+    pWidget->SetEditText(wsText);
 
-  CXFA_Value* value = m_pNode->GetFormValueIfExists();
-  if (value) {
-    switch (value->GetChildValueClassID()) {
-      case XFA_Element::Date: {
-        if (!wsText.IsEmpty()) {
-          CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get());
-          CFX_DateTime date = lcValue.GetDate();
-          if (date.IsSet())
-            pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay());
-        }
-      } break;
-      default:
-        break;
+    CXFA_Value* value = m_pNode->GetFormValueIfExists();
+    if (value) {
+      switch (value->GetChildValueClassID()) {
+        case XFA_Element::Date: {
+          if (!wsText.IsEmpty()) {
+            CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get());
+            CFX_DateTime date = lcValue.GetDate();
+            if (date.IsSet())
+              pWidget->SetCurSel(date.GetYear(), date.GetMonth(),
+                                 date.GetDay());
+          }
+        } break;
+        default:
+          break;
+      }
     }
+    UpdateWidgetProperty();
   }
-  UpdateWidgetProperty();
-  pWidget->UnlockUpdate();
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp
index a3e288e..38e6b1a 100644
--- a/xfa/fxfa/cxfa_fflistbox.cpp
+++ b/xfa/fxfa/cxfa_fflistbox.cpp
@@ -51,21 +51,22 @@
   pNoteDriver->RegisterEventTarget(pListBox, pListBox);
   m_pOldDelegate = pListBox->GetDelegate();
   pListBox->SetDelegate(this);
-  pListBox->LockUpdate();
 
-  for (const auto& label : m_pNode->GetChoiceListItems(false))
-    pListBox->AddString(label);
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pListBox);
+    for (const auto& label : m_pNode->GetChoiceListItems(false))
+      pListBox->AddString(label);
 
-  uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
-  if (m_pNode->IsChoiceListMultiSelect())
-    dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
+    uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
+    if (m_pNode->IsChoiceListMultiSelect())
+      dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
 
-  dwExtendedStyle |= GetAlignment();
-  pListBox->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
-  for (int32_t selected : m_pNode->GetSelectedItems())
-    pListBox->SetSelItem(pListBox->GetItem(nullptr, selected), true);
+    dwExtendedStyle |= GetAlignment();
+    pListBox->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+    for (int32_t selected : m_pNode->GetSelectedItems())
+      pListBox->SetSelItem(pListBox->GetItem(nullptr, selected), true);
+  }
 
-  pListBox->UnlockUpdate();
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffnumericedit.cpp b/xfa/fxfa/cxfa_ffnumericedit.cpp
index 7765e3f..86431fd 100644
--- a/xfa/fxfa/cxfa_ffnumericedit.cpp
+++ b/xfa/fxfa/cxfa_ffnumericedit.cpp
@@ -34,11 +34,13 @@
   pNoteDriver->RegisterEventTarget(pWidget, pWidget);
   m_pOldDelegate = pWidget->GetDelegate();
   pWidget->SetDelegate(this);
-  pWidget->LockUpdate();
 
-  pWidget->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
-  UpdateWidgetProperty();
-  pWidget->UnlockUpdate();
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pWidget);
+    pWidget->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
+    UpdateWidgetProperty();
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffpasswordedit.cpp b/xfa/fxfa/cxfa_ffpasswordedit.cpp
index 1724e7a..b70d1d3 100644
--- a/xfa/fxfa/cxfa_ffpasswordedit.cpp
+++ b/xfa/fxfa/cxfa_ffpasswordedit.cpp
@@ -33,11 +33,13 @@
   pNoteDriver->RegisterEventTarget(pWidget, pWidget);
   m_pOldDelegate = pWidget->GetDelegate();
   pWidget->SetDelegate(this);
-  pWidget->LockUpdate();
 
-  pWidget->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
-  UpdateWidgetProperty();
-  pWidget->UnlockUpdate();
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pWidget);
+    pWidget->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
+    UpdateWidgetProperty();
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_ffpushbutton.cpp b/xfa/fxfa/cxfa_ffpushbutton.cpp
index 6d8ed7e..daf1aaa 100644
--- a/xfa/fxfa/cxfa_ffpushbutton.cpp
+++ b/xfa/fxfa/cxfa_ffpushbutton.cpp
@@ -60,10 +60,13 @@
 
   CFWL_NoteDriver* pNoteDriver = pPushButton->GetOwnerApp()->GetNoteDriver();
   pNoteDriver->RegisterEventTarget(pPushButton, pPushButton);
-  pPushButton->LockUpdate();
-  UpdateWidgetProperty();
-  LoadHighlightCaption();
-  pPushButton->UnlockUpdate();
+
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pPushButton);
+    UpdateWidgetProperty();
+    LoadHighlightCaption();
+  }
+
   return CXFA_FFField::LoadWidget();
 }
 
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index d34e943..f5282ba 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -53,11 +53,13 @@
   pNoteDriver->RegisterEventTarget(pFWLEdit, pFWLEdit);
   m_pOldDelegate = pFWLEdit->GetDelegate();
   pFWLEdit->SetDelegate(this);
-  pFWLEdit->LockUpdate();
-  UpdateWidgetProperty();
 
-  pFWLEdit->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
-  pFWLEdit->UnlockUpdate();
+  {
+    CFWL_Widget::ScopedUpdateLock update_lock(pFWLEdit);
+    UpdateWidgetProperty();
+    pFWLEdit->SetText(m_pNode->GetValue(XFA_VALUEPICTURE_Display));
+  }
+
   return CXFA_FFField::LoadWidget();
 }