// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "pdf/pdfium/pdfium_form_filler.h"

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

#include "base/auto_reset.h"
#include "base/check_op.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "pdf/pdf_features.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/pdfium/public/fpdf_annot.h"
#include "ui/base/window_open_disposition_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "v8/include/v8-isolate.h"

namespace chrome_pdf {

namespace {

int g_last_timer_id = 0;

#if defined(PDF_ENABLE_V8)
std::string WideStringToString(FPDF_WIDESTRING wide_string) {
  return base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(wide_string));
}
#endif

}  // namespace

// static
PDFiumFormFiller::ScriptOption PDFiumFormFiller::DefaultScriptOption() {
#if defined(PDF_ENABLE_XFA)
  if (base::FeatureList::IsEnabled(features::kPdfXfaSupport))
    return PDFiumFormFiller::ScriptOption::kJavaScriptAndXFA;
#endif  // defined(PDF_ENABLE_XFA)
  return PDFiumFormFiller::ScriptOption::kJavaScript;
}

PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine,
                                   ScriptOption script_option)
    : engine_in_isolate_scope_factory_(engine, script_option),
      script_option_(script_option) {
  // Initialize FPDF_FORMFILLINFO member variables.  Deriving from this struct
  // allows the static callbacks to be able to cast the FPDF_FORMFILLINFO in
  // callbacks to ourself instead of maintaining a map of them to
  // PDFiumEngine.
  FPDF_FORMFILLINFO::version = 2;
  FPDF_FORMFILLINFO::Release = nullptr;
  FPDF_FORMFILLINFO::FFI_Invalidate = Form_Invalidate;
  FPDF_FORMFILLINFO::FFI_OutputSelectedRect = Form_OutputSelectedRect;
  FPDF_FORMFILLINFO::FFI_SetCursor = Form_SetCursor;
  FPDF_FORMFILLINFO::FFI_SetTimer = Form_SetTimer;
  FPDF_FORMFILLINFO::FFI_KillTimer = Form_KillTimer;
  FPDF_FORMFILLINFO::FFI_GetLocalTime = Form_GetLocalTime;
  FPDF_FORMFILLINFO::FFI_OnChange = Form_OnChange;
  FPDF_FORMFILLINFO::FFI_GetPage = Form_GetPage;
  FPDF_FORMFILLINFO::FFI_GetCurrentPage = Form_GetCurrentPage;
  FPDF_FORMFILLINFO::FFI_GetRotation = Form_GetRotation;
  FPDF_FORMFILLINFO::FFI_ExecuteNamedAction = Form_ExecuteNamedAction;
  FPDF_FORMFILLINFO::FFI_SetTextFieldFocus = Form_SetTextFieldFocus;
  FPDF_FORMFILLINFO::FFI_DoURIAction = Form_DoURIAction;
  FPDF_FORMFILLINFO::FFI_DoGoToAction = Form_DoGoToAction;
  FPDF_FORMFILLINFO::FFI_OnFocusChange = Form_OnFocusChange;
  FPDF_FORMFILLINFO::FFI_DoURIActionWithKeyboardModifier =
      Form_DoURIActionWithKeyboardModifier;
  FPDF_FORMFILLINFO::xfa_disabled = true;
  FPDF_FORMFILLINFO::FFI_EmailTo = nullptr;
  FPDF_FORMFILLINFO::FFI_DisplayCaret = nullptr;
  FPDF_FORMFILLINFO::FFI_SetCurrentPage = nullptr;
  FPDF_FORMFILLINFO::FFI_GetCurrentPageIndex = nullptr;
  FPDF_FORMFILLINFO::FFI_GetPageViewRect = nullptr;
  FPDF_FORMFILLINFO::FFI_GetPlatform = nullptr;
  FPDF_FORMFILLINFO::FFI_PageEvent = nullptr;
  FPDF_FORMFILLINFO::FFI_PopupMenu = nullptr;
  FPDF_FORMFILLINFO::FFI_PostRequestURL = nullptr;
  FPDF_FORMFILLINFO::FFI_PutRequestURL = nullptr;
  FPDF_FORMFILLINFO::FFI_UploadTo = nullptr;
  FPDF_FORMFILLINFO::FFI_DownloadFromURL = nullptr;
  FPDF_FORMFILLINFO::FFI_OpenFile = nullptr;
  FPDF_FORMFILLINFO::FFI_GotoURL = nullptr;
  FPDF_FORMFILLINFO::FFI_GetLanguage = nullptr;
  FPDF_FORMFILLINFO::m_pJsPlatform = nullptr;

#if defined(PDF_ENABLE_V8)
  if (script_option != ScriptOption::kNoJavaScript) {
    FPDF_FORMFILLINFO::m_pJsPlatform = this;
    IPDF_JSPLATFORM::version = 3;
    IPDF_JSPLATFORM::app_alert = Form_Alert;
    IPDF_JSPLATFORM::app_beep = Form_Beep;
    IPDF_JSPLATFORM::app_response = Form_Response;
    IPDF_JSPLATFORM::Doc_getFilePath = Form_GetFilePath;
    IPDF_JSPLATFORM::Doc_mail = Form_Mail;
    IPDF_JSPLATFORM::Doc_print = Form_Print;
    IPDF_JSPLATFORM::Doc_submitForm = Form_SubmitForm;
    IPDF_JSPLATFORM::Doc_gotoPage = Form_GotoPage;
    IPDF_JSPLATFORM::Field_browse = nullptr;
  }
#if defined(PDF_ENABLE_XFA)
  if (script_option == ScriptOption::kJavaScriptAndXFA) {
    FPDF_FORMFILLINFO::xfa_disabled = false;
    FPDF_FORMFILLINFO::FFI_EmailTo = Form_EmailTo;
    FPDF_FORMFILLINFO::FFI_DisplayCaret = Form_DisplayCaret;
    FPDF_FORMFILLINFO::FFI_SetCurrentPage = Form_SetCurrentPage;
    FPDF_FORMFILLINFO::FFI_GetCurrentPageIndex = Form_GetCurrentPageIndex;
    FPDF_FORMFILLINFO::FFI_GetPageViewRect = Form_GetPageViewRect;
    FPDF_FORMFILLINFO::FFI_GetPlatform = Form_GetPlatform;
    FPDF_FORMFILLINFO::FFI_PageEvent = Form_PageEvent;
    FPDF_FORMFILLINFO::FFI_PopupMenu = Form_PopupMenu;
    FPDF_FORMFILLINFO::FFI_PostRequestURL = Form_PostRequestURL;
    FPDF_FORMFILLINFO::FFI_PutRequestURL = Form_PutRequestURL;
    FPDF_FORMFILLINFO::FFI_UploadTo = Form_UploadTo;
    FPDF_FORMFILLINFO::FFI_DownloadFromURL = Form_DownloadFromURL;
    FPDF_FORMFILLINFO::FFI_OpenFile = Form_OpenFile;
    FPDF_FORMFILLINFO::FFI_GotoURL = Form_GotoURL;
    FPDF_FORMFILLINFO::FFI_GetLanguage = Form_GetLanguage;
  }
#endif  // defined(PDF_ENABLE_XFA)
#endif  // defined(PDF_ENABLE_V8)
}

PDFiumFormFiller::~PDFiumFormFiller() = default;

// static
void PDFiumFormFiller::Form_Invalidate(FPDF_FORMFILLINFO* param,
                                       FPDF_PAGE page,
                                       double left,
                                       double top,
                                       double right,
                                       double bottom) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  int page_index = engine->GetVisiblePageIndex(page);
  if (page_index == -1) {
    // This can sometime happen when the page is closed because it went off
    // screen, and PDFium invalidates the control as it's being deleted.
    return;
  }

  gfx::Rect rect = engine->pages_[page_index]->PageToScreen(
      engine->GetVisibleRect().origin(), engine->current_zoom_, left, top,
      right, bottom, engine->layout_.options().default_page_orientation());
  engine->client_->Invalidate(rect);
}

// static
void PDFiumFormFiller::Form_OutputSelectedRect(FPDF_FORMFILLINFO* param,
                                               FPDF_PAGE page,
                                               double left,
                                               double top,
                                               double right,
                                               double bottom) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  int page_index = engine->GetVisiblePageIndex(page);
  if (page_index == -1)
    return;

  gfx::Rect rect = engine->pages_[page_index]->PageToScreen(
      engine->GetVisibleRect().origin(), engine->current_zoom_, left, top,
      right, bottom, engine->layout_.options().default_page_orientation());
  if (rect.IsEmpty())
    return;

  engine->form_highlights_.push_back(rect);
}

// static
void PDFiumFormFiller::Form_SetCursor(FPDF_FORMFILLINFO* param,
                                      int cursor_type) {
  // We don't need this since it's not enough to change the cursor in all
  // scenarios.  Instead, we check which form field we're under in OnMouseMove.
}

// static
int PDFiumFormFiller::Form_SetTimer(FPDF_FORMFILLINFO* param,
                                    int elapse,
                                    TimerCallback timer_func) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(param);
  return form_filler->SetTimer(base::Milliseconds(elapse), timer_func);
}

// static
void PDFiumFormFiller::Form_KillTimer(FPDF_FORMFILLINFO* param, int timer_id) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(param);
  form_filler->KillTimer(timer_id);
}

// static
FPDF_SYSTEMTIME PDFiumFormFiller::Form_GetLocalTime(FPDF_FORMFILLINFO* param) {
  base::Time time = base::Time::Now();
  base::Time::Exploded exploded;
  time.LocalExplode(&exploded);
  return FPDF_SYSTEMTIME{
      .wYear = static_cast<unsigned short>(exploded.year),
      .wMonth = static_cast<unsigned short>(exploded.month),
      .wDayOfWeek = static_cast<unsigned short>(exploded.day_of_week),
      .wDay = static_cast<unsigned short>(exploded.day_of_month),
      .wHour = static_cast<unsigned short>(exploded.hour),
      .wMinute = static_cast<unsigned short>(exploded.minute),
      .wSecond = static_cast<unsigned short>(exploded.second),
      .wMilliseconds = static_cast<unsigned short>(exploded.millisecond)};
}

// static
void PDFiumFormFiller::Form_OnChange(FPDF_FORMFILLINFO* param) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->EnteredEditMode();
}

// static
FPDF_PAGE PDFiumFormFiller::Form_GetPage(FPDF_FORMFILLINFO* param,
                                         FPDF_DOCUMENT document,
                                         int page_index) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  if (!engine->PageIndexInBounds(page_index))
    return nullptr;
  return engine->pages_[page_index]->GetPage();
}

// static
FPDF_PAGE PDFiumFormFiller::Form_GetCurrentPage(FPDF_FORMFILLINFO* param,
                                                FPDF_DOCUMENT document) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  int index = engine->last_focused_page_;
  if (index == -1) {
    index = engine->GetMostVisiblePage();
    if (index == -1)
      return nullptr;
  }

  DCHECK_NE(index, -1);
  return engine->pages_[index]->GetPage();
}

// static
int PDFiumFormFiller::Form_GetRotation(FPDF_FORMFILLINFO* param,
                                       FPDF_PAGE page) {
  return 0;
}

// static
void PDFiumFormFiller::Form_ExecuteNamedAction(FPDF_FORMFILLINFO* param,
                                               FPDF_BYTESTRING named_action) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  std::string action(named_action);
  if (action == "Print") {
    engine->client_->Print();
    return;
  }

  int index = engine->last_focused_page_;
  /* Don't try to calculate the most visible page if we don't have a left click
     before this event (this code originally copied Form_GetCurrentPage which of
     course needs to do that and which doesn't have recursion). This can end up
     causing infinite recursion. See http://crbug.com/240413 for more
     information. Either way, it's not necessary for the spec'd list of named
     actions.
  if (index == -1)
    index = engine->GetMostVisiblePage();
  */
  if (index == -1)
    return;

  // This is the only list of named actions per the spec (see 12.6.4.11). Adobe
  // Reader supports more, like FitWidth, but since they're not part of the spec
  // and we haven't got bugs about them, no need to now.
  if (action == "NextPage") {
    engine->ScrollToPage(index + 1);
  } else if (action == "PrevPage") {
    engine->ScrollToPage(index - 1);
  } else if (action == "FirstPage") {
    engine->ScrollToPage(0);
  } else if (action == "LastPage") {
    engine->ScrollToPage(engine->pages_.size() - 1);
  }
}

// static
void PDFiumFormFiller::Form_SetTextFieldFocus(FPDF_FORMFILLINFO* param,
                                              FPDF_WIDESTRING value,
                                              FPDF_DWORD valueLen,
                                              FPDF_BOOL is_focus) {
  // Do nothing for now.
  // TODO(gene): use this signal to trigger OSK.
}

// static
void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
                                          FPDF_ANNOTATION annot,
                                          int page_index) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  if (!engine->PageIndexInBounds(page_index))
    return;

  base::AutoReset<bool> defer_page_unload_guard(&engine->defer_page_unload_,
                                                true);

  // Maintain viewport if we are updating focus. This is to ensure that we don't
  // scroll the focused annotation into view when focus is regained.
  if (!engine->updating_focus_)
    engine->ScrollAnnotationIntoView(annot, page_index);

  engine->OnFocusedAnnotationUpdated(annot, page_index);
}

// static
void PDFiumFormFiller::Form_DoURIAction(FPDF_FORMFILLINFO* param,
                                        FPDF_BYTESTRING uri) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->NavigateTo(std::string(uri),
                              WindowOpenDisposition::CURRENT_TAB);
}

// static
void PDFiumFormFiller::Form_DoGoToAction(FPDF_FORMFILLINFO* param,
                                         int page_index,
                                         int zoom_mode,
                                         float* position_array,
                                         int size_of_array) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->ScrollToPage(page_index);
}

// static
void PDFiumFormFiller::Form_DoURIActionWithKeyboardModifier(
    FPDF_FORMFILLINFO* param,
    FPDF_BYTESTRING uri,
    int modifiers) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  bool middle_button =
      !!(modifiers & blink::WebInputEvent::Modifiers::kMiddleButtonDown);
  bool alt_key = !!(modifiers & blink::WebInputEvent::Modifiers::kAltKey);
  bool ctrl_key = !!(modifiers & blink::WebInputEvent::Modifiers::kControlKey);
  bool meta_key = !!(modifiers & blink::WebInputEvent::Modifiers::kMetaKey);
  bool shift_key = !!(modifiers & blink::WebInputEvent::Modifiers::kShiftKey);

  WindowOpenDisposition disposition = ui::DispositionFromClick(
      middle_button, alt_key, ctrl_key, meta_key, shift_key);

  engine->client_->NavigateTo(std::string(uri), disposition);
}

#if defined(PDF_ENABLE_V8)
#if defined(PDF_ENABLE_XFA)

// static
void PDFiumFormFiller::Form_EmailTo(FPDF_FORMFILLINFO* param,
                                    FPDF_FILEHANDLER* file_handler,
                                    FPDF_WIDESTRING to,
                                    FPDF_WIDESTRING subject,
                                    FPDF_WIDESTRING cc,
                                    FPDF_WIDESTRING bcc,
                                    FPDF_WIDESTRING message) {
  std::string to_str = WideStringToString(to);
  std::string subject_str = WideStringToString(subject);
  std::string cc_str = WideStringToString(cc);
  std::string bcc_str = WideStringToString(bcc);
  std::string message_str = WideStringToString(message);

  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->Email(to_str, cc_str, bcc_str, subject_str, message_str);
}

// static
void PDFiumFormFiller::Form_DisplayCaret(FPDF_FORMFILLINFO* param,
                                         FPDF_PAGE page,
                                         FPDF_BOOL visible,
                                         double left,
                                         double top,
                                         double right,
                                         double bottom) {}

// static
void PDFiumFormFiller::Form_SetCurrentPage(FPDF_FORMFILLINFO* param,
                                           FPDF_DOCUMENT document,
                                           int page) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->ScrollToPage(page);
}

// static
int PDFiumFormFiller::Form_GetCurrentPageIndex(FPDF_FORMFILLINFO* param,
                                               FPDF_DOCUMENT document) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  return engine->GetMostVisiblePage();
}

// static
void PDFiumFormFiller::Form_GetPageViewRect(FPDF_FORMFILLINFO* param,
                                            FPDF_PAGE page,
                                            double* left,
                                            double* top,
                                            double* right,
                                            double* bottom) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  int page_index = engine->GetVisiblePageIndex(page);
  if (!engine->PageIndexInBounds(page_index)) {
    *left = 0;
    *right = 0;
    *top = 0;
    *bottom = 0;
    return;
  }

  gfx::Rect page_view_rect = engine->GetPageContentsRect(page_index);

  float page_width = FPDF_GetPageWidth(page);
  float page_height = FPDF_GetPageHeight(page);

  // To convert from a screen scale to a page scale, we multiply by
  // (page_height / page_view_rect.height()) and
  // (page_width / page_view_rect.width()),
  // The base point of the page in screen coords is (page_view_rect.x(),
  // page_view_rect.y()).
  // Therefore, to convert an x position from screen to page
  // coords, we use (page_width * (x - base_x) / page_view_rect.width()).
  // For y positions, (page_height * (y - base_y) / page_view_rect.height()).

  // The top-most x position that is visible on the screen is the top of the
  // plugin area, which is y = 0.
  float screen_top_in_page_coords =
      page_height * (0 - page_view_rect.y()) / page_view_rect.height();
  // The bottom-most y position that is visible on the screen is the bottom of
  // the plugin area, which is y = engine->plugin_size().height().
  float screen_bottom_in_page_coords =
      page_height * (engine->plugin_size().height() - page_view_rect.y()) /
      page_view_rect.height();
  // The left-most x position that is visible on the screen is the left of the
  // plugin area, which is x = 0.
  float screen_left_in_page_coords =
      page_width * (0 - page_view_rect.x()) / page_view_rect.width();
  // The right-most x position that is visible on the screen is the right of the
  // plugin area, which is x = engine->plugin_size().width().
  float screen_right_in_page_coords =
      page_width * (engine->plugin_size().width() - page_view_rect.x()) /
      page_view_rect.width();

  // Return the edge of the screen or of the page, since we're restricted to
  // both.
  *left = std::max(screen_left_in_page_coords, 0.0f);
  *right = std::min(screen_right_in_page_coords, page_width);
  *top = std::max(screen_top_in_page_coords, 0.0f);
  *bottom = std::min(screen_bottom_in_page_coords, page_height);
}

// static
int PDFiumFormFiller::Form_GetPlatform(FPDF_FORMFILLINFO* param,
                                       void* platform,
                                       int length) {
  int platform_flag = -1;

#if defined(WIN32)
  platform_flag = 0;
#elif defined(__linux__)
  platform_flag = 1;
#else
  platform_flag = 2;
#endif

  std::string javascript =
      "alert(\"Platform:" + base::NumberToString(platform_flag) + "\")";

  return platform_flag;
}

// static
void PDFiumFormFiller::Form_PageEvent(FPDF_FORMFILLINFO* param,
                                      int page_count,
                                      unsigned long event_type) {
  DCHECK(page_count != 0);
  DCHECK(event_type == FXFA_PAGEVIEWEVENT_POSTADDED ||
         event_type == FXFA_PAGEVIEWEVENT_POSTREMOVED);

  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->UpdatePageCount();
}

// static
FPDF_BOOL PDFiumFormFiller::Form_PopupMenu(FPDF_FORMFILLINFO* param,
                                           FPDF_PAGE page,
                                           FPDF_WIDGET widget,
                                           int menu_flag,
                                           float x,
                                           float y) {
  return false;
}

// static
FPDF_BOOL PDFiumFormFiller::Form_PostRequestURL(FPDF_FORMFILLINFO* param,
                                                FPDF_WIDESTRING url,
                                                FPDF_WIDESTRING data,
                                                FPDF_WIDESTRING content_type,
                                                FPDF_WIDESTRING encode,
                                                FPDF_WIDESTRING header,
                                                FPDF_BSTR* response) {
  // NOTE: Think hard about the privacy implications before allowing
  // a PDF file to perform this action, as it might be used for beaconing.
  return true;
}

// static
FPDF_BOOL PDFiumFormFiller::Form_PutRequestURL(FPDF_FORMFILLINFO* param,
                                               FPDF_WIDESTRING url,
                                               FPDF_WIDESTRING data,
                                               FPDF_WIDESTRING encode) {
  // NOTE: Think hard about the privacy implications before allowing
  // a PDF file to perform this action, as it might be used for beaconing.
  return true;
}

// static
void PDFiumFormFiller::Form_UploadTo(FPDF_FORMFILLINFO* param,
                                     FPDF_FILEHANDLER* file_handle,
                                     int file_flag,
                                     FPDF_WIDESTRING to) {
  // NOTE: Think hard about the privacy implications before allowing
  // a PDF file to perform this action, as it might be used for beaconing.
}

// static
FPDF_FILEHANDLER* PDFiumFormFiller::Form_DownloadFromURL(
    FPDF_FORMFILLINFO* param,
    FPDF_WIDESTRING url) {
  // NOTE: Think hard about the security implications before allowing
  // a PDF file to perform this action. Also think hard about the privacy
  // implications, as it might be used for beaconing.
  return nullptr;
}

// static
FPDF_FILEHANDLER* PDFiumFormFiller::Form_OpenFile(FPDF_FORMFILLINFO* param,
                                                  int file_flag,
                                                  FPDF_WIDESTRING url,
                                                  const char* mode) {
  // NOTE: Think hard about the security implications before allowing
  // a PDF file to perform this action.
  return nullptr;
}

// static
void PDFiumFormFiller::Form_GotoURL(FPDF_FORMFILLINFO* param,
                                    FPDF_DOCUMENT document,
                                    FPDF_WIDESTRING url) {
  // NOTE: Think hard about the security implications before allowing
  // a PDF file to perform this action. Also think hard about the privacy
  // implications, as it might be used for beaconing.
}

// static
int PDFiumFormFiller::Form_GetLanguage(FPDF_FORMFILLINFO* param,
                                       void* language,
                                       int length) {
  return 0;
}

#endif  // defined(PDF_ENABLE_XFA)

// static
int PDFiumFormFiller::Form_Alert(IPDF_JSPLATFORM* param,
                                 FPDF_WIDESTRING message,
                                 FPDF_WIDESTRING title,
                                 int type,
                                 int icon) {
  // See fpdfformfill.h for these values.
  enum AlertType {
    ALERT_TYPE_OK = 0,
    ALERT_TYPE_OK_CANCEL,
    ALERT_TYPE_YES_ON,
    ALERT_TYPE_YES_NO_CANCEL
  };

  enum AlertResult {
    ALERT_RESULT_OK = 1,
    ALERT_RESULT_CANCEL,
    ALERT_RESULT_NO,
    ALERT_RESULT_YES
  };

  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  std::string message_str = WideStringToString(message);
  if (type == ALERT_TYPE_OK) {
    engine->client_->Alert(message_str);
    return ALERT_RESULT_OK;
  }

  bool rv = engine->client_->Confirm(message_str);
  if (type == ALERT_TYPE_OK_CANCEL)
    return rv ? ALERT_RESULT_OK : ALERT_RESULT_CANCEL;
  return rv ? ALERT_RESULT_YES : ALERT_RESULT_NO;
}

// static
void PDFiumFormFiller::Form_Beep(IPDF_JSPLATFORM* param, int type) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->Beep();
}

// static
int PDFiumFormFiller::Form_Response(IPDF_JSPLATFORM* param,
                                    FPDF_WIDESTRING question,
                                    FPDF_WIDESTRING title,
                                    FPDF_WIDESTRING default_response,
                                    FPDF_WIDESTRING label,
                                    FPDF_BOOL password,
                                    void* response,
                                    int length) {
  std::string question_str = WideStringToString(question);
  std::string default_str = WideStringToString(default_response);

  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  std::string rv = engine->client_->Prompt(question_str, default_str);
  std::u16string rv_16 = base::UTF8ToUTF16(rv);
  int rv_bytes = rv_16.size() * sizeof(char16_t);
  if (response) {
    int bytes_to_copy = rv_bytes < length ? rv_bytes : length;
    memcpy(response, rv_16.c_str(), bytes_to_copy);
  }
  return rv_bytes;
}

// static
int PDFiumFormFiller::Form_GetFilePath(IPDF_JSPLATFORM* param,
                                       void* file_path,
                                       int length) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  std::string rv = engine->client_->GetURL();

  // Account for the trailing null.
  int necessary_length = rv.size() + 1;
  if (file_path && necessary_length <= length)
    memcpy(file_path, rv.c_str(), necessary_length);
  return necessary_length;
}

// static
void PDFiumFormFiller::Form_Mail(IPDF_JSPLATFORM* param,
                                 void* mail_data,
                                 int length,
                                 FPDF_BOOL ui,
                                 FPDF_WIDESTRING to,
                                 FPDF_WIDESTRING subject,
                                 FPDF_WIDESTRING cc,
                                 FPDF_WIDESTRING bcc,
                                 FPDF_WIDESTRING message) {
  // Note: `mail_data` and `length` are ignored. We don't handle attachments;
  // there is no way with mailto.
  std::string to_str = WideStringToString(to);
  std::string cc_str = WideStringToString(cc);
  std::string bcc_str = WideStringToString(bcc);
  std::string subject_str = WideStringToString(subject);
  std::string message_str = WideStringToString(message);

  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->Email(to_str, cc_str, bcc_str, subject_str, message_str);
}

// static
void PDFiumFormFiller::Form_Print(IPDF_JSPLATFORM* param,
                                  FPDF_BOOL ui,
                                  int start,
                                  int end,
                                  FPDF_BOOL silent,
                                  FPDF_BOOL shrink_to_fit,
                                  FPDF_BOOL print_as_image,
                                  FPDF_BOOL reverse,
                                  FPDF_BOOL annotations) {
  // No way to pass the extra information to the print dialog using JavaScript.
  // Just opening it is fine for now.
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->Print();
}

// static
void PDFiumFormFiller::Form_SubmitForm(IPDF_JSPLATFORM* param,
                                       void* form_data,
                                       int length,
                                       FPDF_WIDESTRING url) {
  std::string url_str = WideStringToString(url);
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->client_->SubmitForm(url_str, form_data, length);
}

// static
void PDFiumFormFiller::Form_GotoPage(IPDF_JSPLATFORM* param, int page_number) {
  EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
  PDFiumEngine* engine = engine_scope.engine();
  engine->ScrollToPage(page_number);
}

#endif  // defined(PDF_ENABLE_V8)

PDFiumFormFiller::EngineInIsolateScope::EngineInIsolateScope(
    PDFiumEngine* engine,
    v8::Isolate* isolate)
    : isolate_scope_(isolate ? std::make_unique<v8::Isolate::Scope>(isolate)
                             : nullptr),
      engine_(engine) {
  DCHECK(engine_);
}

PDFiumFormFiller::EngineInIsolateScope::EngineInIsolateScope(
    EngineInIsolateScope&&) = default;

PDFiumFormFiller::EngineInIsolateScope&
PDFiumFormFiller::EngineInIsolateScope::operator=(EngineInIsolateScope&&) =
    default;

PDFiumFormFiller::EngineInIsolateScope::~EngineInIsolateScope() = default;

PDFiumFormFiller::EngineInIsolateScopeFactory::EngineInIsolateScopeFactory(
    PDFiumEngine* engine,
    ScriptOption script_option)
    : engine_(engine),
      callback_isolate_(script_option !=
                                PDFiumFormFiller::ScriptOption::kNoJavaScript
                            ? v8::Isolate::TryGetCurrent()
                            : nullptr) {
  if (callback_isolate_) {
    CHECK_EQ(engine_->client_->GetIsolate(), callback_isolate_);
  }
}

PDFiumFormFiller::EngineInIsolateScopeFactory::~EngineInIsolateScopeFactory() =
    default;

PDFiumFormFiller::EngineInIsolateScope
PDFiumFormFiller::EngineInIsolateScopeFactory::GetEngineInIsolateScope() const {
  return EngineInIsolateScope(engine_, callback_isolate_);
}

// static
PDFiumFormFiller::EngineInIsolateScope
PDFiumFormFiller::GetEngineInIsolateScope(FPDF_FORMFILLINFO* info) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(info);
  return form_filler->engine_in_isolate_scope_factory_
      .GetEngineInIsolateScope();
}

// static
PDFiumFormFiller::EngineInIsolateScope
PDFiumFormFiller::GetEngineInIsolateScope(IPDF_JSPLATFORM* platform) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(platform);
  return form_filler->engine_in_isolate_scope_factory_
      .GetEngineInIsolateScope();
}

int PDFiumFormFiller::SetTimer(const base::TimeDelta& delay,
                               TimerCallback timer_func) {
  const int timer_id = ++g_last_timer_id;
  DCHECK(!base::Contains(timers_, timer_id));

  auto timer = std::make_unique<base::RepeatingTimer>();
  timer->Start(FROM_HERE, delay, base::BindRepeating(timer_func, timer_id));
  timers_[timer_id] = std::move(timer);
  return timer_id;
}

void PDFiumFormFiller::KillTimer(int timer_id) {
  size_t erased = timers_.erase(timer_id);
  DCHECK_EQ(1u, erased);
}

}  // namespace chrome_pdf
