// 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 <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/data_vector.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"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.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.Get())));
  }
  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(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->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(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) {
  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::base::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::base::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::base::checked_cast<FPDF_DWORD>(nCharacters),
        bFocus);
  }
}

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

void CPDFSDK_FormFillEnvironment::OnFormat(ObservedPtr<CPDFSDK_Annot>& pAnnot) {
  CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot.Get());
  DCHECK(pWidget);

  absl::optional<WideString> sValue =
      m_pInteractiveForm->OnFormat(pWidget->GetFormField());
  if (!pAnnot)
    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.Get()));
}

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.Get()), 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.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->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);

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

  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.Get(), "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;

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

  DoActionDocOpen(CPDF_Action(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.Get()), 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.Reset(pAnnot.Get());

  // 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.Reset(pFocusAnnot.Get());
    return false;
  }

  // Might have been destroyed by OnKillFocus().
  if (!pFocusAnnot)
    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) {
      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() & 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);

  const CPDF_Array* dest_array = dest.GetArray();
  std::vector<float> dest_positions;
  // |dest_array| index 0 contains destination page details and index 1 contains
  // parameter that explains about the rest of |dest_array|.
  if (dest_array) {
    for (size_t i = 2; i < dest_array->size(); i++)
      dest_positions.push_back(dest_array->GetFloatAt(i));
  }

  DoGoToAction(dest.GetDestPageIndex(document), dest.GetZoomMode(),
               dest_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();
      break;
    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();
        break;
    }
  });
}

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

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.
}
