// Copyright 2016 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

#include "fpdfsdk/cpdfsdk_formfillenvironment.h"

#include <memory>
#include <utility>
#include <vector>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfdoc/cpdf_docjsactions.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "fpdfsdk/cpdfsdk_actionhandler.h"
#include "fpdfsdk/cpdfsdk_annothandlermgr.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "fpdfsdk/cpdfsdk_interactiveform.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_formfiller.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fxjs/ijs_runtime.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"

FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) {
  // Force a private version of the string, since we're about to hand it off
  // to the embedder. Should the embedder modify it by accident, it won't
  // corrupt other shares of the string beyond |bsUTF16LE|.
  return reinterpret_cast<FPDF_WIDESTRING>(
      bsUTF16LE->GetBuffer(bsUTF16LE->GetLength()).data());
}

CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment(
    CPDF_Document* pDoc,
    FPDF_FORMFILLINFO* pFFinfo,
    std::unique_ptr<CPDFSDK_AnnotHandlerMgr> pHandlerMgr)
    : m_pInfo(pFFinfo),
      m_pCPDFDoc(pDoc),
      m_pAnnotHandlerMgr(std::move(pHandlerMgr)) {
  ASSERT(m_pCPDFDoc);
  m_pAnnotHandlerMgr->SetFormFillEnv(this);
}

CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() {
  m_bBeingDestroyed = true;
  ClearAllFocusedAnnots();

  // |m_PageMap| will try to access |m_pInteractiveForm| when it cleans itself
  // up. Make sure it is deleted before |m_pInteractiveForm|.
  m_PageMap.clear();

  // |m_pAnnotHandlerMgr| will try to access |m_pFormFiller| when it cleans
  // itself up. Make sure it is deleted before |m_pFormFiller|.
  m_pAnnotHandlerMgr.reset();

  // Must destroy the |m_pFormFiller| before the environment (|this|)
  // because any created form widgets hold a pointer to the environment.
  // Those widgets may call things like KillTimer() as they are shutdown.
  m_pFormFiller.reset();

  if (m_pInfo && m_pInfo->Release)
    m_pInfo->Release(m_pInfo);
}

void CPDFSDK_FormFillEnvironment::InvalidateRect(PerWindowData* pWidgetData,
                                                 const CFX_FloatRect& rect) {
  auto* pPrivateData = static_cast<CFFL_PrivateData*>(pWidgetData);
  CPDFSDK_Widget* widget = pPrivateData->pWidget.Get();
  if (!widget)
    return;

  CPDFSDK_PageView* pPageView = widget->GetPageView();
  IPDF_Page* pPage = widget->GetPage();
  if (!pPage || !pPageView)
    return;

  CFX_Matrix device2page = pPageView->GetCurrentMatrix().GetInverse();
  CFX_PointF left_top = device2page.Transform(CFX_PointF(rect.left, rect.top));
  CFX_PointF right_bottom =
      device2page.Transform(CFX_PointF(rect.right, rect.bottom));

  CFX_FloatRect rcPDF(left_top.x, right_bottom.y, right_bottom.x, left_top.y);
  rcPDF.Normalize();
  Invalidate(pPage, rcPDF.GetOuterRect());
}

void CPDFSDK_FormFillEnvironment::OutputSelectedRect(
    CFFL_FormFiller* pFormFiller,
    const CFX_FloatRect& rect) {
  if (!pFormFiller || !m_pInfo || !m_pInfo->FFI_OutputSelectedRect)
    return;

  auto* pPage = FPDFPageFromIPDFPage(pFormFiller->GetSDKAnnot()->GetPage());
  ASSERT(pPage);

  CFX_PointF ptA = pFormFiller->PWLtoFFL(CFX_PointF(rect.left, rect.bottom));
  CFX_PointF ptB = pFormFiller->PWLtoFFL(CFX_PointF(rect.right, rect.top));
  m_pInfo->FFI_OutputSelectedRect(m_pInfo, pPage, ptA.x, ptB.y, ptB.x, ptA.y);
}

bool CPDFSDK_FormFillEnvironment::IsSelectionImplemented() const {
  FPDF_FORMFILLINFO* pInfo = GetFormFillInfo();
  return pInfo && pInfo->FFI_OutputSelectedRect;
}

#ifdef PDF_ENABLE_V8
CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
  IPDF_Page* pPage = IPDFPageFromFPDFPage(GetCurrentPage());
  return pPage ? GetPageView(pPage, true) : nullptr;
}

FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
  if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
    return m_pInfo->FFI_GetCurrentPage(
        m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()));
  }
  return nullptr;
}

WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
#ifdef PDF_ENABLE_XFA
  if (!m_pInfo || !m_pInfo->FFI_GetLanguage)
    return WideString();

  int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  std::vector<uint8_t, FxAllocAllocator<uint8_t>> pBuff(nRequiredLen);
  int nActualLen =
      m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
                                 nActualLen / sizeof(uint16_t));
#else   // PDF_ENABLE_XFA
  return WideString();
#endif  // PDF_ENABLE_XFA
}

WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
#ifdef PDF_ENABLE_XFA
  if (!m_pInfo || !m_pInfo->FFI_GetPlatform)
    return WideString();

  int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  std::vector<uint8_t, FxAllocAllocator<uint8_t>> pBuff(nRequiredLen);
  int nActualLen =
      m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
                                 nActualLen / sizeof(uint16_t));
#else   // PDF_ENABLE_XFA
  return WideString();
#endif  // PDF_ENABLE_XFA
}

int CPDFSDK_FormFillEnvironment::JS_appAlert(const WideString& Msg,
                                             const WideString& Title,
                                             int Type,
                                             int Icon) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->app_alert) {
    return -1;
  }

  ByteString bsMsg = Msg.ToUTF16LE();
  ByteString bsTitle = Title.ToUTF16LE();
  return m_pInfo->m_pJsPlatform->app_alert(
      m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsMsg),
      AsFPDFWideString(&bsTitle), Type, Icon);
}

int CPDFSDK_FormFillEnvironment::JS_appResponse(const WideString& Question,
                                                const WideString& Title,
                                                const WideString& Default,
                                                const WideString& Label,
                                                FPDF_BOOL bPassword,
                                                void* response,
                                                int length) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->app_response) {
    return -1;
  }
  ByteString bsQuestion = Question.ToUTF16LE();
  ByteString bsTitle = Title.ToUTF16LE();
  ByteString bsDefault = Default.ToUTF16LE();
  ByteString bsLabel = Label.ToUTF16LE();
  return m_pInfo->m_pJsPlatform->app_response(
      m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsQuestion),
      AsFPDFWideString(&bsTitle), AsFPDFWideString(&bsDefault),
      AsFPDFWideString(&bsLabel), bPassword, response, length);
}

void CPDFSDK_FormFillEnvironment::JS_appBeep(int nType) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->app_beep) {
    return;
  }
  m_pInfo->m_pJsPlatform->app_beep(m_pInfo->m_pJsPlatform, nType);
}

WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Field_browse) {
    return WideString();
  }
  const int nRequiredLen =
      m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  std::vector<uint8_t, FxAllocAllocator<uint8_t>> pBuff(nRequiredLen);
  const int nActualLen = m_pInfo->m_pJsPlatform->Field_browse(
      m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  pBuff.resize(nActualLen);
  return WideString::FromDefANSI(ByteStringView(pBuff));
}

void CPDFSDK_FormFillEnvironment::JS_docmailForm(void* mailData,
                                                 int length,
                                                 FPDF_BOOL bUI,
                                                 const WideString& To,
                                                 const WideString& Subject,
                                                 const WideString& CC,
                                                 const WideString& BCC,
                                                 const WideString& Msg) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Doc_mail) {
    return;
  }
  ByteString bsTo = To.ToUTF16LE();
  ByteString bsSubject = Subject.ToUTF16LE();
  ByteString bsCC = CC.ToUTF16LE();
  ByteString bsBcc = BCC.ToUTF16LE();
  ByteString bsMsg = Msg.ToUTF16LE();
  m_pInfo->m_pJsPlatform->Doc_mail(
      m_pInfo->m_pJsPlatform, mailData, length, bUI, AsFPDFWideString(&bsTo),
      AsFPDFWideString(&bsSubject), AsFPDFWideString(&bsCC),
      AsFPDFWideString(&bsBcc), AsFPDFWideString(&bsMsg));
}

void CPDFSDK_FormFillEnvironment::JS_docprint(FPDF_BOOL bUI,
                                              int nStart,
                                              int nEnd,
                                              FPDF_BOOL bSilent,
                                              FPDF_BOOL bShrinkToFit,
                                              FPDF_BOOL bPrintAsImage,
                                              FPDF_BOOL bReverse,
                                              FPDF_BOOL bAnnotations) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Doc_print) {
    return;
  }
  m_pInfo->m_pJsPlatform->Doc_print(m_pInfo->m_pJsPlatform, bUI, nStart, nEnd,
                                    bSilent, bShrinkToFit, bPrintAsImage,
                                    bReverse, bAnnotations);
}

void CPDFSDK_FormFillEnvironment::JS_docgotoPage(int nPageNum) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Doc_gotoPage) {
    return;
  }
  m_pInfo->m_pJsPlatform->Doc_gotoPage(m_pInfo->m_pJsPlatform, nPageNum);
}

WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() {
  return GetFilePath();
}
#endif  // PDF_ENABLE_V8

WideString CPDFSDK_FormFillEnvironment::GetFilePath() const {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Doc_getFilePath) {
    return WideString();
  }
  const int nRequiredLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(
      m_pInfo->m_pJsPlatform, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  std::vector<uint8_t, FxAllocAllocator<uint8_t>> pBuff(nRequiredLen);
  const int nActualLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(
      m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  pBuff.resize(nActualLen);
  return WideString::FromDefANSI(ByteStringView(pBuff));
}

void CPDFSDK_FormFillEnvironment::SubmitForm(pdfium::span<uint8_t> form_data,
                                             const WideString& URL) {
  if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
      !m_pInfo->m_pJsPlatform->Doc_submitForm) {
    return;
  }
  ByteString bsUrl = URL.ToUTF16LE();
  m_pInfo->m_pJsPlatform->Doc_submitForm(m_pInfo->m_pJsPlatform,
                                         form_data.data(), form_data.size(),
                                         AsFPDFWideString(&bsUrl));
}

IJS_Runtime* CPDFSDK_FormFillEnvironment::GetIJSRuntime() {
  if (!m_pIJSRuntime)
    m_pIJSRuntime = IJS_Runtime::Create(this);
  return m_pIJSRuntime.get();
}

CPDFSDK_AnnotHandlerMgr* CPDFSDK_FormFillEnvironment::GetAnnotHandlerMgr() {
  return m_pAnnotHandlerMgr.get();
}

CPDFSDK_ActionHandler* CPDFSDK_FormFillEnvironment::GetActionHandler() {
  if (!m_pActionHandler)
    m_pActionHandler = pdfium::MakeUnique<CPDFSDK_ActionHandler>();
  return m_pActionHandler.get();
}

CFFL_InteractiveFormFiller*
CPDFSDK_FormFillEnvironment::GetInteractiveFormFiller() {
  if (!m_pFormFiller)
    m_pFormFiller = pdfium::MakeUnique<CFFL_InteractiveFormFiller>(this);
  return m_pFormFiller.get();
}

void CPDFSDK_FormFillEnvironment::Invalidate(IPDF_Page* page,
                                             const FX_RECT& rect) {
  if (m_pInfo && m_pInfo->FFI_Invalidate) {
    m_pInfo->FFI_Invalidate(m_pInfo, FPDFPageFromIPDFPage(page), rect.left,
                            rect.top, rect.right, rect.bottom);
  }
}

void CPDFSDK_FormFillEnvironment::SetCursor(int nCursorType) {
  if (m_pInfo && m_pInfo->FFI_SetCursor)
    m_pInfo->FFI_SetCursor(m_pInfo, nCursorType);
}

int CPDFSDK_FormFillEnvironment::SetTimer(int uElapse,
                                          TimerCallback lpTimerFunc) {
  if (m_pInfo && m_pInfo->FFI_SetTimer)
    return m_pInfo->FFI_SetTimer(m_pInfo, uElapse, lpTimerFunc);
  return TimerHandlerIface::kInvalidTimerID;
}

void CPDFSDK_FormFillEnvironment::KillTimer(int nTimerID) {
  if (m_pInfo && m_pInfo->FFI_KillTimer)
    m_pInfo->FFI_KillTimer(m_pInfo, nTimerID);
}

void CPDFSDK_FormFillEnvironment::OnChange() {
  if (m_pInfo && m_pInfo->FFI_OnChange)
    m_pInfo->FFI_OnChange(m_pInfo);
}

void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(const char* namedAction) {
  if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
    m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction);
}

void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocus(
    FPDF_WIDESTRING focusText,
    FPDF_DWORD nTextLen,
    bool bFocus) {
  if (m_pInfo && m_pInfo->FFI_SetTextFieldFocus)
    m_pInfo->FFI_SetTextFieldFocus(m_pInfo, focusText, nTextLen, bFocus);
}

void CPDFSDK_FormFillEnvironment::DoURIAction(const char* bsURI) {
  if (m_pInfo && m_pInfo->FFI_DoURIAction)
    m_pInfo->FFI_DoURIAction(m_pInfo, bsURI);
}

void CPDFSDK_FormFillEnvironment::DoGoToAction(int nPageIndex,
                                               int zoomMode,
                                               float* fPosArray,
                                               int sizeOfArray) {
  if (m_pInfo && m_pInfo->FFI_DoGoToAction) {
    m_pInfo->FFI_DoGoToAction(m_pInfo, nPageIndex, zoomMode, fPosArray,
                              sizeOfArray);
  }
}

#ifdef PDF_ENABLE_XFA
int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
  return pdfium::CollectionSize<int>(m_PageMap);
}

void CPDFSDK_FormFillEnvironment::DisplayCaret(IPDF_Page* page,
                                               FPDF_BOOL bVisible,
                                               double left,
                                               double top,
                                               double right,
                                               double bottom) {
  if (m_pInfo && m_pInfo->FFI_DisplayCaret) {
    m_pInfo->FFI_DisplayCaret(m_pInfo, FPDFPageFromIPDFPage(page), bVisible,
                              left, top, right, bottom);
  }
}

int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex() const {
  if (!m_pInfo || !m_pInfo->FFI_GetCurrentPageIndex)
    return -1;
  return m_pInfo->FFI_GetCurrentPageIndex(
      m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()));
}

void CPDFSDK_FormFillEnvironment::SetCurrentPage(int iCurPage) {
  if (!m_pInfo || !m_pInfo->FFI_SetCurrentPage)
    return;
  m_pInfo->FFI_SetCurrentPage(
      m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()), iCurPage);
}

void CPDFSDK_FormFillEnvironment::GotoURL(const WideString& wsURL) {
  if (!m_pInfo || !m_pInfo->FFI_GotoURL)
    return;

  ByteString bsTo = wsURL.ToUTF16LE();
  m_pInfo->FFI_GotoURL(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()),
                       AsFPDFWideString(&bsTo));
}

FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(IPDF_Page* page) {
  FS_RECTF rect = {0.0f, 0.0f, 0.0f, 0.0f};
  if (!m_pInfo || !m_pInfo->FFI_GetPageViewRect)
    return rect;

  double left;
  double top;
  double right;
  double bottom;
  m_pInfo->FFI_GetPageViewRect(m_pInfo, FPDFPageFromIPDFPage(page), &left, &top,
                               &right, &bottom);

  rect.left = static_cast<float>(left);
  rect.top = static_cast<float>(top);
  rect.bottom = static_cast<float>(bottom);
  rect.right = static_cast<float>(right);
  return rect;
}

bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page,
                                            FPDF_WIDGET hWidget,
                                            int menuFlag,
                                            const CFX_PointF& pt) {
  return m_pInfo && m_pInfo->FFI_PopupMenu &&
         m_pInfo->FFI_PopupMenu(m_pInfo, FPDFPageFromIPDFPage(page), hWidget,
                                menuFlag, pt.x, pt.y);
}

void CPDFSDK_FormFillEnvironment::EmailTo(FPDF_FILEHANDLER* fileHandler,
                                          FPDF_WIDESTRING pTo,
                                          FPDF_WIDESTRING pSubject,
                                          FPDF_WIDESTRING pCC,
                                          FPDF_WIDESTRING pBcc,
                                          FPDF_WIDESTRING pMsg) {
  if (m_pInfo && m_pInfo->FFI_EmailTo)
    m_pInfo->FFI_EmailTo(m_pInfo, fileHandler, pTo, pSubject, pCC, pBcc, pMsg);
}

void CPDFSDK_FormFillEnvironment::UploadTo(FPDF_FILEHANDLER* fileHandler,
                                           int fileFlag,
                                           FPDF_WIDESTRING uploadTo) {
  if (m_pInfo && m_pInfo->FFI_UploadTo)
    m_pInfo->FFI_UploadTo(m_pInfo, fileHandler, fileFlag, uploadTo);
}

FPDF_FILEHANDLER* CPDFSDK_FormFillEnvironment::OpenFile(int fileType,
                                                        FPDF_WIDESTRING wsURL,
                                                        const char* mode) {
  if (m_pInfo && m_pInfo->FFI_OpenFile)
    return m_pInfo->FFI_OpenFile(m_pInfo, fileType, wsURL, mode);
  return nullptr;
}

RetainPtr<IFX_SeekableReadStream> CPDFSDK_FormFillEnvironment::DownloadFromURL(
    const WideString& url) {
  if (!m_pInfo || !m_pInfo->FFI_DownloadFromURL)
    return nullptr;

  ByteString bstrURL = url.ToUTF16LE();
  FPDF_LPFILEHANDLER fileHandler =
      m_pInfo->FFI_DownloadFromURL(m_pInfo, AsFPDFWideString(&bstrURL));

  return MakeSeekableStream(fileHandler);
}

WideString CPDFSDK_FormFillEnvironment::PostRequestURL(
    const WideString& wsURL,
    const WideString& wsData,
    const WideString& wsContentType,
    const WideString& wsEncode,
    const WideString& wsHeader) {
  if (!m_pInfo || !m_pInfo->FFI_PostRequestURL)
    return WideString();

  ByteString bsURL = wsURL.ToUTF16LE();
  ByteString bsData = wsData.ToUTF16LE();
  ByteString bsContentType = wsContentType.ToUTF16LE();
  ByteString bsEncode = wsEncode.ToUTF16LE();
  ByteString bsHeader = wsHeader.ToUTF16LE();

  FPDF_BSTR response;
  FPDF_BStr_Init(&response);
  m_pInfo->FFI_PostRequestURL(
      m_pInfo, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData),
      AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode),
      AsFPDFWideString(&bsHeader), &response);

  WideString wsRet =
      WideString::FromUTF16LE(reinterpret_cast<FPDF_WIDESTRING>(response.str),
                              response.len / sizeof(FPDF_WIDESTRING));

  FPDF_BStr_Clear(&response);
  return wsRet;
}

FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(
    const WideString& wsURL,
    const WideString& wsData,
    const WideString& wsEncode) {
  if (!m_pInfo || !m_pInfo->FFI_PutRequestURL)
    return false;

  ByteString bsURL = wsURL.ToUTF16LE();
  ByteString bsData = wsData.ToUTF16LE();
  ByteString bsEncode = wsEncode.ToUTF16LE();

  return m_pInfo->FFI_PutRequestURL(m_pInfo, AsFPDFWideString(&bsURL),
                                    AsFPDFWideString(&bsData),
                                    AsFPDFWideString(&bsEncode));
}

void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount,
                                            uint32_t dwEventType) const {
  if (m_pInfo && m_pInfo->FFI_PageEvent)
    m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType);
}
#endif  // PDF_ENABLE_XFA

void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() {
  for (auto& it : m_PageMap) {
    if (it.second->IsValidSDKAnnot(GetFocusAnnot()))
      KillFocusAnnot(0);
  }
}

CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(
    IPDF_Page* pUnderlyingPage,
    bool renew) {
  auto it = m_PageMap.find(pUnderlyingPage);
  if (it != m_PageMap.end())
    return it->second.get();

  if (!renew)
    return nullptr;

  auto pNew = pdfium::MakeUnique<CPDFSDK_PageView>(this, pUnderlyingPage);
  CPDFSDK_PageView* pPageView = pNew.get();
  m_PageMap[pUnderlyingPage] = std::move(pNew);

  // Delay to load all the annotations, to avoid endless loop.
  pPageView->LoadFXAnnots();
  return pPageView;
}

CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) {
  IPDF_Page* pTempPage = GetPage(nIndex);
  if (!pTempPage)
    return nullptr;

  auto it = m_PageMap.find(pTempPage);
  return it != m_PageMap.end() ? it->second.get() : nullptr;
}

void CPDFSDK_FormFillEnvironment::ProcJavascriptFun() {
  CPDF_DocJSActions docJS(m_pCPDFDoc.Get());
  int iCount = docJS.CountJSActions();
  for (int i = 0; i < iCount; i++) {
    WideString csJSName;
    CPDF_Action jsAction = docJS.GetJSActionAndName(i, &csJSName);
    GetActionHandler()->DoAction_JavaScript(jsAction, csJSName, this);
  }
}

bool CPDFSDK_FormFillEnvironment::ProcOpenAction() {
  CPDF_Dictionary* pRoot = m_pCPDFDoc->GetRoot();
  if (!pRoot)
    return false;

  CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction");
  if (!pOpenAction)
    pOpenAction = pRoot->GetArrayFor("OpenAction");
  if (!pOpenAction)
    return false;

  if (pOpenAction->IsArray())
    return true;

  CPDF_Dictionary* pDict = pOpenAction->AsDictionary();
  if (!pDict)
    return false;

  CPDF_Action action(pDict);
  GetActionHandler()->DoAction_DocOpen(action, this);
  return true;
}

void CPDFSDK_FormFillEnvironment::RemovePageView(IPDF_Page* pUnderlyingPage) {
  auto it = m_PageMap.find(pUnderlyingPage);
  if (it == m_PageMap.end())
    return;

  CPDFSDK_PageView* pPageView = it->second.get();
  if (pPageView->IsLocked() || pPageView->IsBeingDestroyed())
    return;

  // Mark the page view so we do not come into |RemovePageView| a second
  // time while we're in the process of removing.
  pPageView->SetBeingDestroyed();

  // This must happen before we remove |pPageView| from the map because
  // |KillFocusAnnot| can call into the |GetPage| method which will
  // look for this page view in the map, if it doesn't find it a new one will
  // be created. We then have two page views pointing to the same page and
  // bad things happen.
  if (pPageView->IsValidSDKAnnot(GetFocusAnnot()))
    KillFocusAnnot(0);

  // Remove the page from the map to make sure we don't accidentally attempt
  // to use the |pPageView| while we're cleaning it up.
  m_PageMap.erase(it);
}

IPDF_Page* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) {
  if (!m_pInfo || !m_pInfo->FFI_GetPage)
    return nullptr;
  return IPDFPageFromFPDFPage(m_pInfo->FFI_GetPage(
      m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc.Get()), nIndex));
}

CPDFSDK_InteractiveForm* CPDFSDK_FormFillEnvironment::GetInteractiveForm() {
  if (!m_pInteractiveForm)
    m_pInteractiveForm = pdfium::MakeUnique<CPDFSDK_InteractiveForm>(this);
  return m_pInteractiveForm.get();
}

void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_PageView* pSender,
                                                 CPDFSDK_Annot* pAnnot) {
  for (const auto& it : m_PageMap) {
    CPDFSDK_PageView* pPageView = it.second.get();
    if (pPageView != pSender)
      pPageView->UpdateView(pAnnot);
  }
}

bool CPDFSDK_FormFillEnvironment::SetFocusAnnot(
    ObservedPtr<CPDFSDK_Annot>* pAnnot) {
  if (m_bBeingDestroyed)
    return false;
  if (m_pFocusAnnot == *pAnnot)
    return true;
  if (m_pFocusAnnot && !KillFocusAnnot(0))
    return false;
  if (!pAnnot->HasObservable())
    return false;

  CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView();
  if (!pPageView || !pPageView->IsValid())
    return false;

  CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
  if (m_pFocusAnnot)
    return false;

#ifdef PDF_ENABLE_XFA
  ObservedPtr<CPDFSDK_Annot> pLastFocusAnnot(m_pFocusAnnot.Get());
  if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot))
    return false;

  // |pAnnot| may be destroyed in |Annot_OnChangeFocus|.
  if (!pAnnot->HasObservable())
    return false;
#endif  // PDF_ENABLE_XFA
  if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0))
    return false;
  if (m_pFocusAnnot)
    return false;

  m_pFocusAnnot.Reset(pAnnot->Get());
  return true;
}

bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) {
  if (!m_pFocusAnnot)
    return false;

  CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
  ObservedPtr<CPDFSDK_Annot> pFocusAnnot(m_pFocusAnnot.Get());
  m_pFocusAnnot.Reset();

#ifdef PDF_ENABLE_XFA
  ObservedPtr<CPDFSDK_Annot> pNull;
  if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot))
    return false;
#endif  // PDF_ENABLE_XFA

  if (!pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) {
    m_pFocusAnnot.Reset(pFocusAnnot.Get());
    return false;
  }

  if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
    CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pFocusAnnot.Get());
    FormFieldType fieldType = pWidget->GetFieldType();
    if (fieldType == FormFieldType::kTextField ||
        fieldType == FormFieldType::kComboBox) {
      OnSetFieldInputFocus(nullptr, 0, false);
    }
  }
  return !m_pFocusAnnot;
}

int CPDFSDK_FormFillEnvironment::GetPageCount() const {
  CPDF_Document::Extension* pExtension = m_pCPDFDoc->GetExtension();
  return pExtension ? pExtension->GetPageCount() : m_pCPDFDoc->GetPageCount();
}

bool CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) const {
  return !!(m_pCPDFDoc->GetUserPermissions() & nFlag);
}
