// Copyright 2016 The PDFium Authors
// 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 <stdint.h>

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

#include "core/fpdfapi/page/cpdf_annotcontext.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfdoc/cpdf_nametree.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/containers/contains.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/notreached.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/stl_util.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_formfield.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fxjs/ijs_event_context.h"
#include "fxjs/ijs_runtime.h"

#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
#endif

static_assert(FXCT_ARROW ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kArrow),
              "kArrow value mismatch");
static_assert(FXCT_NESW ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kNESW),
              "kNEWS value mismatch");
static_assert(FXCT_NWSE ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kNWSE),
              "kNWSE value mismatch");
static_assert(FXCT_VBEAM ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kVBeam),
              "kVBeam value mismatch");
static_assert(FXCT_HBEAM ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kHBeam),
              "HBeam value mismatch");
static_assert(FXCT_HAND ==
                  static_cast<int>(IPWL_FillerNotify::CursorStyle::kHand),
              "kHand value mismatch");

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)
    : m_pInfo(pFFinfo),
      m_pCPDFDoc(pDoc),
      m_pInteractiveFormFiller(
          std::make_unique<CFFL_InteractiveFormFiller>(this)) {
  DCHECK(m_pCPDFDoc);
}

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();

  // Must destroy the |m_pInteractiveFormFiller| 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_pInteractiveFormFiller.reset();

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

void CPDFSDK_FormFillEnvironment::InvalidateRect(CPDFSDK_Widget* widget,
                                                 const CFX_FloatRect& rect) {
  IPDF_Page* pPage = widget->GetPage();
  if (!pPage)
    return;

  CFX_Matrix device2page =
      widget->GetPageView()->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_FormField* pFormField,
    const CFX_FloatRect& rect) {
  if (!m_pInfo || !m_pInfo->FFI_OutputSelectedRect)
    return;

  auto* pPage = FPDFPageFromIPDFPage(pFormField->GetSDKWidget()->GetPage());
  DCHECK(pPage);

  CFX_PointF ptA = pFormField->PWLtoFFL(CFX_PointF(rect.left, rect.bottom));
  CFX_PointF ptB = pFormField->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 = GetCurrentPage();
  return pPage ? GetOrCreatePageView(pPage) : nullptr;
}

IPDF_Page* CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
  if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
    return IPDFPageFromFPDFPage(m_pInfo->FFI_GetCurrentPage(
        m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc)));
  }
  return nullptr;
}

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

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

  DataVector<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(
      pdfium::make_span(pBuff).first(static_cast<size_t>(nActualLen)));
#else   // PDF_ENABLE_XFA
  return WideString();
#endif  // PDF_ENABLE_XFA
}

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

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

  DataVector<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(
      pdfium::make_span(pBuff).first(static_cast<size_t>(nActualLen)));
#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) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->app_alert)
    return -1;

  ByteString bsMsg = Msg.ToUTF16LE();
  ByteString bsTitle = Title.ToUTF16LE();
  return js_platform->app_alert(js_platform, 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,
    pdfium::span<uint8_t> response) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->app_response)
    return -1;

  ByteString bsQuestion = Question.ToUTF16LE();
  ByteString bsTitle = Title.ToUTF16LE();
  ByteString bsDefault = Default.ToUTF16LE();
  ByteString bsLabel = Label.ToUTF16LE();
  return js_platform->app_response(
      js_platform, AsFPDFWideString(&bsQuestion), AsFPDFWideString(&bsTitle),
      AsFPDFWideString(&bsDefault), AsFPDFWideString(&bsLabel), bPassword,
      response.data(), pdfium::checked_cast<int>(response.size()));
}

void CPDFSDK_FormFillEnvironment::JS_appBeep(int nType) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->app_beep)
    return;

  js_platform->app_beep(js_platform, nType);
}

WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Field_browse)
    return WideString();

  const int nRequiredLen = js_platform->Field_browse(js_platform, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  DataVector<uint8_t> pBuff(nRequiredLen);
  const int nActualLen =
      js_platform->Field_browse(js_platform, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  // Don't include trailing NUL.
  pBuff.resize(nActualLen - 1);

  // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
  return WideString::FromDefANSI(ByteStringView(pBuff));
}

void CPDFSDK_FormFillEnvironment::JS_docmailForm(
    pdfium::span<const uint8_t> mailData,
    FPDF_BOOL bUI,
    const WideString& To,
    const WideString& Subject,
    const WideString& CC,
    const WideString& BCC,
    const WideString& Msg) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Doc_mail)
    return;

  ByteString bsTo = To.ToUTF16LE();
  ByteString bsSubject = Subject.ToUTF16LE();
  ByteString bsCC = CC.ToUTF16LE();
  ByteString bsBcc = BCC.ToUTF16LE();
  ByteString bsMsg = Msg.ToUTF16LE();
  js_platform->Doc_mail(js_platform, const_cast<uint8_t*>(mailData.data()),
                        pdfium::checked_cast<int>(mailData.size()), 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) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Doc_print)
    return;

  js_platform->Doc_print(js_platform, bUI, nStart, nEnd, bSilent, bShrinkToFit,
                         bPrintAsImage, bReverse, bAnnotations);
}

void CPDFSDK_FormFillEnvironment::JS_docgotoPage(int nPageNum) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Doc_gotoPage)
    return;

  js_platform->Doc_gotoPage(js_platform, nPageNum);
}

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

WideString CPDFSDK_FormFillEnvironment::GetFilePath() const {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Doc_getFilePath)
    return WideString();

  const int nRequiredLen =
      js_platform->Doc_getFilePath(js_platform, nullptr, 0);
  if (nRequiredLen <= 0)
    return WideString();

  DataVector<uint8_t> pBuff(nRequiredLen);
  const int nActualLen =
      js_platform->Doc_getFilePath(js_platform, pBuff.data(), nRequiredLen);
  if (nActualLen <= 0 || nActualLen > nRequiredLen)
    return WideString();

  // Don't include trailing NUL.
  pBuff.resize(nActualLen - 1);

  // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
  return WideString::FromDefANSI(ByteStringView(pBuff));
}

void CPDFSDK_FormFillEnvironment::SubmitForm(
    pdfium::span<const uint8_t> form_data,
    const WideString& URL) {
  IPDF_JSPLATFORM* js_platform = GetJSPlatform();
  if (!js_platform || !js_platform->Doc_submitForm)
    return;

  ByteString bsUrl = URL.ToUTF16LE();
  js_platform->Doc_submitForm(
      js_platform, const_cast<uint8_t*>(form_data.data()),
      fxcrt::CollectionSize<int>(form_data), AsFPDFWideString(&bsUrl));
}

IJS_Runtime* CPDFSDK_FormFillEnvironment::GetIJSRuntime() {
  if (!m_pIJSRuntime)
    m_pIJSRuntime = IJS_Runtime::Create(this);
  return m_pIJSRuntime.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(
    IPWL_FillerNotify::CursorStyle nCursorType) {
  if (m_pInfo && m_pInfo->FFI_SetCursor)
    m_pInfo->FFI_SetCursor(m_pInfo, static_cast<int>(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 CFX_Timer::HandlerIface::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 ByteString& namedAction) {
  if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
    m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction.c_str());
}

void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocus(const WideString& text) {
  OnSetFieldInputFocusInternal(text, true);
}

void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocusInternal(
    const WideString& text,
    bool bFocus) {
  if (m_pInfo && m_pInfo->FFI_SetTextFieldFocus) {
    size_t nCharacters = text.GetLength();
    ByteString bsUTFText = text.ToUTF16LE();
    auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
    m_pInfo->FFI_SetTextFieldFocus(
        m_pInfo, pBuffer, pdfium::checked_cast<FPDF_DWORD>(nCharacters),
        bFocus);
  }
}

void CPDFSDK_FormFillEnvironment::OnCalculate(
    ObservedPtr<CPDFSDK_Annot>& pAnnot) {
  ObservedPtr<CPDFSDK_Widget> pWidget(ToCPDFSDKWidget(pAnnot.Get()));
  if (pWidget) {
    m_pInteractiveForm->OnCalculate(pWidget->GetFormField());
  }
}

void CPDFSDK_FormFillEnvironment::OnFormat(ObservedPtr<CPDFSDK_Annot>& pAnnot) {
  ObservedPtr<CPDFSDK_Widget> pWidget(ToCPDFSDKWidget(pAnnot.Get()));
  std::optional<WideString> sValue =
      m_pInteractiveForm->OnFormat(pWidget->GetFormField());
  if (!pWidget) {
    return;
  }
  if (sValue.has_value()) {
    m_pInteractiveForm->ResetFieldAppearance(pWidget->GetFormField(), sValue);
    m_pInteractiveForm->UpdateField(pWidget->GetFormField());
  }
}

void CPDFSDK_FormFillEnvironment::DoURIAction(const ByteString& bsURI,
                                              Mask<FWL_EVENTFLAG> modifiers) {
  if (!m_pInfo)
    return;

  if (m_pInfo->version >= 2 && m_pInfo->FFI_DoURIActionWithKeyboardModifier) {
    m_pInfo->FFI_DoURIActionWithKeyboardModifier(m_pInfo, bsURI.c_str(),
                                                 modifiers.UncheckedValue());
    return;
  }

  if (m_pInfo->FFI_DoURIAction)
    m_pInfo->FFI_DoURIAction(m_pInfo, bsURI.c_str());
}

void CPDFSDK_FormFillEnvironment::DoGoToAction(int nPageIndex,
                                               int zoomMode,
                                               pdfium::span<float> fPosArray) {
  if (m_pInfo && m_pInfo->FFI_DoGoToAction) {
    m_pInfo->FFI_DoGoToAction(m_pInfo, nPageIndex, zoomMode, fPosArray.data(),
                              fxcrt::CollectionSize<int>(fPosArray));
  }
}

#ifdef PDF_ENABLE_XFA
int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
  return fxcrt::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->version >= 2 && 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->version < 2 || !m_pInfo->FFI_GetCurrentPageIndex)
    return -1;
  return m_pInfo->FFI_GetCurrentPageIndex(
      m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc));
}

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

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

  ByteString bsTo = wsURL.ToUTF16LE();
  m_pInfo->FFI_GotoURL(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc),
                       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->version < 2 || !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,
                                            int menuFlag,
                                            const CFX_PointF& pt) {
  return m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PopupMenu &&
         m_pInfo->FFI_PopupMenu(m_pInfo, FPDFPageFromIPDFPage(page), nullptr,
                                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->version >= 2 && 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->version >= 2 && 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->version >= 2 && 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->version < 2 || !m_pInfo->FFI_DownloadFromURL)
    return nullptr;

  ByteString bstrURL = url.ToUTF16LE();
  FPDF_FILEHANDLER* 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->version < 2 || !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);

  // SAFETY: required from FFI callback.
  WideString wsRet = WideString::FromUTF16LE(UNSAFE_BUFFERS(
      pdfium::make_span(reinterpret_cast<const uint8_t*>(response.str),
                        static_cast<size_t>(response.len))));

  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->version < 2 || !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->version >= 2 && 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())) {
      ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
      KillFocusAnnot({});
      if (!pObserved)
        break;
    }
  }
}

CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetOrCreatePageView(
    IPDF_Page* pUnderlyingPage) {
  CPDFSDK_PageView* pExisting = GetPageView(pUnderlyingPage);
  if (pExisting)
    return pExisting;

  auto pNew = std::make_unique<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(
    IPDF_Page* pUnderlyingPage) {
  auto it = m_PageMap.find(pUnderlyingPage);
  return it != m_PageMap.end() ? it->second.get() : nullptr;
}

CFX_Timer::HandlerIface* CPDFSDK_FormFillEnvironment::GetTimerHandler() {
  return this;
}

CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageViewAtIndex(int nIndex) {
  IPDF_Page* pTempPage = GetPage(nIndex);
  return pTempPage ? GetPageView(pTempPage) : nullptr;
}

void CPDFSDK_FormFillEnvironment::ProcJavascriptAction() {
  auto name_tree = CPDF_NameTree::Create(m_pCPDFDoc, "JavaScript");
  if (!name_tree)
    return;

  size_t count = name_tree->GetCount();
  for (size_t i = 0; i < count; ++i) {
    WideString name;
    CPDF_Action action(ToDictionary(name_tree->LookupValueAndName(i, &name)));
    DoActionJavaScript(action, name);
  }
}

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

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

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

  RetainPtr<const CPDF_Dictionary> pDict = ToDictionary(pOpenAction);
  if (!pDict)
    return false;

  DoActionDocOpen(CPDF_Action(std::move(pDict)));
  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({});

  // 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) const {
  if (!m_pInfo || !m_pInfo->FFI_GetPage)
    return nullptr;
  return IPDFPageFromFPDFPage(m_pInfo->FFI_GetPage(
      m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), nIndex));
}

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

void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_Annot* pAnnot) {
  for (const auto& it : m_PageMap) {
    ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
    if (pObserved) {
      pObserved->UpdateView(pAnnot);
      if (!pObserved)
        break;
    }
  }
}

CPDFSDK_Annot* CPDFSDK_FormFillEnvironment::GetFocusAnnot() const {
  return m_pFocusAnnot.Get();
}

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

  if (m_pFocusAnnot)
    return false;

#ifdef PDF_ENABLE_XFA
  CPDFXFA_Widget* pXFAWidget = pAnnot->AsXFAWidget();
  if (pXFAWidget && pXFAWidget->OnChangedFocus())
    return false;

  // `pAnnot` may be destroyed in `OnChangedFocus()`.
  if (!pAnnot)
    return false;
#endif  // PDF_ENABLE_XFA

  if (!CPDFSDK_Annot::OnSetFocus(pAnnot, {})) {
    return false;
  }
  if (m_pFocusAnnot) {
    return false;
  }
  m_pFocusAnnot = pAnnot;

  // If we are not able to inform the client about the focus change, it
  // shouldn't be considered as failure.
  SendOnFocusChange(pAnnot);
  return true;
}

bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(Mask<FWL_EVENTFLAG> nFlags) {
  if (!m_pFocusAnnot)
    return false;

  ObservedPtr<CPDFSDK_Annot> pFocusAnnot(m_pFocusAnnot.Get());
  m_pFocusAnnot.Reset();

  if (!CPDFSDK_Annot::OnKillFocus(pFocusAnnot, nFlags)) {
    m_pFocusAnnot = pFocusAnnot;
    return false;
  }

  // Might have been destroyed by OnKillFocus().
  if (!pFocusAnnot)
    return false;

  if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
    const FormFieldType field_type =
        ToCPDFSDKWidget(pFocusAnnot.Get())->GetFieldType();
    if (field_type == FormFieldType::kTextField ||
        field_type == FormFieldType::kComboBox) {
      OnSetFieldInputFocusInternal(WideString(), 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::HasPermissions(uint32_t flags) const {
  return !!(m_pCPDFDoc->GetUserPermissions(/*get_owner_perms=*/true) & flags);
}

void CPDFSDK_FormFillEnvironment::SendOnFocusChange(
    ObservedPtr<CPDFSDK_Annot>& pAnnot) {
  if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_OnFocusChange)
    return;

  // TODO(crbug.com/pdfium/1482): Handle XFA case.
  if (pAnnot->AsXFAWidget())
    return;

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

  IPDF_Page* page = pAnnot->GetPage();
  if (!page)
    return;

  RetainPtr<CPDF_Dictionary> annot_dict =
      pAnnot->GetPDFAnnot()->GetMutableAnnotDict();
  auto focused_annot = std::make_unique<CPDF_AnnotContext>(annot_dict, page);
  FPDF_ANNOTATION fpdf_annot =
      FPDFAnnotationFromCPDFAnnotContext(focused_annot.get());

  m_pInfo->FFI_OnFocusChange(m_pInfo, fpdf_annot, pPageView->GetPageIndex());
}

bool CPDFSDK_FormFillEnvironment::DoActionDocOpen(const CPDF_Action& action) {
  std::set<const CPDF_Dictionary*> visited;
  return ExecuteDocumentOpenAction(action, &visited);
}

bool CPDFSDK_FormFillEnvironment::DoActionJavaScript(
    const CPDF_Action& JsAction,
    WideString csJSName) {
  if (JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
    WideString swJS = JsAction.GetJavaScript();
    if (!swJS.IsEmpty()) {
      RunDocumentOpenJavaScript(csJSName, swJS);
      return true;
    }
  }

  return false;
}

bool CPDFSDK_FormFillEnvironment::DoActionFieldJavaScript(
    const CPDF_Action& JsAction,
    CPDF_AAction::AActionType type,
    CPDF_FormField* pFormField,
    CFFL_FieldAction* data) {
  if (IsJSPlatformPresent() &&
      JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
    WideString swJS = JsAction.GetJavaScript();
    if (!swJS.IsEmpty()) {
      RunFieldJavaScript(pFormField, type, data, swJS);
      return true;
    }
  }
  return false;
}

bool CPDFSDK_FormFillEnvironment::DoActionLink(const CPDF_Action& action,
                                               CPDF_AAction::AActionType type,
                                               Mask<FWL_EVENTFLAG> modifiers) {
  if (!CPDF_AAction::IsUserInput(type))
    return false;

  switch (action.GetType()) {
    case CPDF_Action::Type::kGoTo:
      DoActionGoTo(action);
      return true;
    case CPDF_Action::Type::kURI:
      DoActionURI(action, modifiers);
      return true;
    default:
      return false;
  }
}

bool CPDFSDK_FormFillEnvironment::DoActionDestination(const CPDF_Dest& dest) {
  CPDF_Document* document = GetPDFDocument();
  DCHECK(document);

  std::vector<float> positions = dest.GetScrollPositionArray();
  DoGoToAction(dest.GetDestPageIndex(document), dest.GetZoomMode(), positions);
  return true;
}

bool CPDFSDK_FormFillEnvironment::DoActionPage(
    const CPDF_Action& action,
    CPDF_AAction::AActionType eType) {
  std::set<const CPDF_Dictionary*> visited;
  return ExecuteDocumentPageAction(action, eType, &visited);
}

bool CPDFSDK_FormFillEnvironment::DoActionDocument(
    const CPDF_Action& action,
    CPDF_AAction::AActionType eType) {
  std::set<const CPDF_Dictionary*> visited;
  return ExecuteDocumentPageAction(action, eType, &visited);
}

bool CPDFSDK_FormFillEnvironment::DoActionField(const CPDF_Action& action,
                                                CPDF_AAction::AActionType type,
                                                CPDF_FormField* pFormField,
                                                CFFL_FieldAction* data) {
  std::set<const CPDF_Dictionary*> visited;
  return ExecuteFieldAction(action, type, pFormField, data, &visited);
}

bool CPDFSDK_FormFillEnvironment::ExecuteDocumentOpenAction(
    const CPDF_Action& action,
    std::set<const CPDF_Dictionary*>* visited) {
  const CPDF_Dictionary* pDict = action.GetDict();
  if (pdfium::Contains(*visited, pDict))
    return false;

  visited->insert(pDict);

  if (action.GetType() == CPDF_Action::Type::kJavaScript) {
    if (IsJSPlatformPresent()) {
      WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty())
        RunDocumentOpenJavaScript(WideString(), swJS);
    }
  } else {
    DoActionNoJs(action, CPDF_AAction::AActionType::kDocumentOpen);
  }

  for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteDocumentOpenAction(subaction, visited))
      return false;
  }

  return true;
}

bool CPDFSDK_FormFillEnvironment::ExecuteDocumentPageAction(
    const CPDF_Action& action,
    CPDF_AAction::AActionType type,
    std::set<const CPDF_Dictionary*>* visited) {
  const CPDF_Dictionary* pDict = action.GetDict();
  if (pdfium::Contains(*visited, pDict))
    return false;

  visited->insert(pDict);

  if (action.GetType() == CPDF_Action::Type::kJavaScript) {
    if (IsJSPlatformPresent()) {
      WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty())
        RunDocumentPageJavaScript(type, swJS);
    }
  } else {
    DoActionNoJs(action, type);
  }

  for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteDocumentPageAction(subaction, type, visited))
      return false;
  }

  return true;
}

bool CPDFSDK_FormFillEnvironment::IsValidField(
    const CPDF_Dictionary* pFieldDict) {
  DCHECK(pFieldDict);

  CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
  CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
  return !!pPDFForm->GetFieldByDict(pFieldDict);
}

bool CPDFSDK_FormFillEnvironment::ExecuteFieldAction(
    const CPDF_Action& action,
    CPDF_AAction::AActionType type,
    CPDF_FormField* pFormField,
    CFFL_FieldAction* data,
    std::set<const CPDF_Dictionary*>* visited) {
  const CPDF_Dictionary* pDict = action.GetDict();
  if (pdfium::Contains(*visited, pDict))
    return false;

  visited->insert(pDict);

  if (action.GetType() == CPDF_Action::Type::kJavaScript) {
    if (IsJSPlatformPresent()) {
      WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        RunFieldJavaScript(pFormField, type, data, swJS);
        if (!IsValidField(pFormField->GetFieldDict()))
          return false;
      }
    }
  } else {
    DoActionNoJs(action, type);
  }

  for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteFieldAction(subaction, type, pFormField, data, visited))
      return false;
  }

  return true;
}

void CPDFSDK_FormFillEnvironment::DoActionNoJs(const CPDF_Action& action,
                                               CPDF_AAction::AActionType type) {
  switch (action.GetType()) {
    case CPDF_Action::Type::kGoTo:
      DoActionGoTo(action);
      break;
    case CPDF_Action::Type::kURI:
      if (CPDF_AAction::IsUserInput(type))
        DoActionURI(action, Mask<FWL_EVENTFLAG>{});
      break;
    case CPDF_Action::Type::kHide:
      DoActionHide(action);
      break;
    case CPDF_Action::Type::kNamed:
      DoActionNamed(action);
      break;
    case CPDF_Action::Type::kSubmitForm:
      if (CPDF_AAction::IsUserInput(type))
        DoActionSubmitForm(action);
      break;
    case CPDF_Action::Type::kResetForm:
      DoActionResetForm(action);
      break;
    case CPDF_Action::Type::kJavaScript:
      NOTREACHED_NORETURN();
    case CPDF_Action::Type::kSetOCGState:
    case CPDF_Action::Type::kThread:
    case CPDF_Action::Type::kSound:
    case CPDF_Action::Type::kMovie:
    case CPDF_Action::Type::kRendition:
    case CPDF_Action::Type::kTrans:
    case CPDF_Action::Type::kGoTo3DView:
    case CPDF_Action::Type::kGoToR:
    case CPDF_Action::Type::kGoToE:
    case CPDF_Action::Type::kLaunch:
    case CPDF_Action::Type::kImportData:
      // Unimplemented
      break;
    default:
      break;
  }
}

void CPDFSDK_FormFillEnvironment::DoActionGoTo(const CPDF_Action& action) {
  DCHECK(action.GetDict());

  CPDF_Document* pPDFDocument = GetPDFDocument();
  DCHECK(pPDFDocument);

  CPDF_Dest MyDest = action.GetDest(pPDFDocument);
  DoActionDestination(MyDest);
}

void CPDFSDK_FormFillEnvironment::DoActionURI(const CPDF_Action& action,
                                              Mask<FWL_EVENTFLAG> modifiers) {
  DCHECK(action.GetDict());
  DoURIAction(action.GetURI(GetPDFDocument()), modifiers);
}

void CPDFSDK_FormFillEnvironment::DoActionNamed(const CPDF_Action& action) {
  DCHECK(action.GetDict());
  ExecuteNamedAction(action.GetNamedAction());
}

void CPDFSDK_FormFillEnvironment::RunFieldJavaScript(
    CPDF_FormField* pFormField,
    CPDF_AAction::AActionType type,
    CFFL_FieldAction* data,
    const WideString& script) {
  DCHECK(type != CPDF_AAction::kCalculate);
  DCHECK(type != CPDF_AAction::kFormat);

  RunScript(script, [type, data, pFormField](IJS_EventContext* context) {
    switch (type) {
      case CPDF_AAction::kCursorEnter:
        context->OnField_MouseEnter(data->bModifier, data->bShift, pFormField);
        break;
      case CPDF_AAction::kCursorExit:
        context->OnField_MouseExit(data->bModifier, data->bShift, pFormField);
        break;
      case CPDF_AAction::kButtonDown:
        context->OnField_MouseDown(data->bModifier, data->bShift, pFormField);
        break;
      case CPDF_AAction::kButtonUp:
        context->OnField_MouseUp(data->bModifier, data->bShift, pFormField);
        break;
      case CPDF_AAction::kGetFocus:
        context->OnField_Focus(data->bModifier, data->bShift, pFormField,
                               &data->sValue);
        break;
      case CPDF_AAction::kLoseFocus:
        context->OnField_Blur(data->bModifier, data->bShift, pFormField,
                              &data->sValue);
        break;
      case CPDF_AAction::kKeyStroke:
        context->OnField_Keystroke(
            &data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier,
            &data->nSelEnd, &data->nSelStart, data->bShift, pFormField,
            &data->sValue, data->bWillCommit, data->bFieldFull, &data->bRC);
        break;
      case CPDF_AAction::kValidate:
        context->OnField_Validate(&data->sChange, data->sChangeEx,
                                  data->bKeyDown, data->bModifier, data->bShift,
                                  pFormField, &data->sValue, &data->bRC);
        break;
      default:
        NOTREACHED_NORETURN();
    }
  });
}

void CPDFSDK_FormFillEnvironment::RunDocumentOpenJavaScript(
    const WideString& sScriptName,
    const WideString& script) {
  RunScript(script, [sScriptName](IJS_EventContext* context) {
    context->OnDoc_Open(sScriptName);
  });
}

void CPDFSDK_FormFillEnvironment::RunDocumentPageJavaScript(
    CPDF_AAction::AActionType type,
    const WideString& script) {
  RunScript(script, [type](IJS_EventContext* context) {
    switch (type) {
      case CPDF_AAction::kOpenPage:
        context->OnPage_Open();
        break;
      case CPDF_AAction::kClosePage:
        context->OnPage_Close();
        break;
      case CPDF_AAction::kCloseDocument:
        context->OnDoc_WillClose();
        break;
      case CPDF_AAction::kSaveDocument:
        context->OnDoc_WillSave();
        break;
      case CPDF_AAction::kDocumentSaved:
        context->OnDoc_DidSave();
        break;
      case CPDF_AAction::kPrintDocument:
        context->OnDoc_WillPrint();
        break;
      case CPDF_AAction::kDocumentPrinted:
        context->OnDoc_DidPrint();
        break;
      case CPDF_AAction::kPageVisible:
        context->OnPage_InView();
        break;
      case CPDF_AAction::kPageInvisible:
        context->OnPage_OutView();
        break;
      default:
        NOTREACHED_NORETURN();
    }
  });
}

bool CPDFSDK_FormFillEnvironment::DoActionHide(const CPDF_Action& action) {
  CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
  if (pForm->DoAction_Hide(action)) {
    SetChangeMark();
    return true;
  }
  return false;
}

bool CPDFSDK_FormFillEnvironment::DoActionSubmitForm(
    const CPDF_Action& action) {
  CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
  return pForm->DoAction_SubmitForm(action);
}

void CPDFSDK_FormFillEnvironment::DoActionResetForm(const CPDF_Action& action) {
  CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
  pForm->DoAction_ResetForm(action);
}

void CPDFSDK_FormFillEnvironment::RunScript(const WideString& script,
                                            const RunScriptCallback& cb) {
  IJS_Runtime::ScopedEventContext pContext(GetIJSRuntime());
  cb(pContext.Get());
  pContext->RunScript(script);
  // TODO(dsinclair): Return error if RunScript returns a IJS_Runtime::JS_Error.
}
