// Copyright 2018 The Chromium Authors. All rights reserved.
// 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 <string>
#include <utility>

#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "pdf/pdfium/pdfium_engine.h"

namespace chrome_pdf {

namespace {

std::string WideStringToString(FPDF_WIDESTRING wide_string) {
  return base::UTF16ToUTF8(reinterpret_cast<const base::char16*>(wide_string));
}

}  // namespace

PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript)
    : engine_(engine) {
  // 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 = 1;
  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;
#if defined(PDF_ENABLE_XFA)
  FPDF_FORMFILLINFO::version = 2;
  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)

  if (enable_javascript) {
    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;
  } else {
    FPDF_FORMFILLINFO::m_pJsPlatform = nullptr;
  }
}

PDFiumFormFiller::~PDFiumFormFiller() = default;

// static
void PDFiumFormFiller::Form_Invalidate(FPDF_FORMFILLINFO* param,
                                       FPDF_PAGE page,
                                       double left,
                                       double top,
                                       double right,
                                       double bottom) {
  PDFiumEngine* engine = GetEngine(param);
  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;
  }

  pp::Rect rect = engine->pages_[page_index]->PageToScreen(
      engine->GetVisibleRect().point(), engine->current_zoom_, left, top, right,
      bottom, engine->current_rotation_);
  engine->client_->Invalidate(rect);
}

// static
void PDFiumFormFiller::Form_OutputSelectedRect(FPDF_FORMFILLINFO* param,
                                               FPDF_PAGE page,
                                               double left,
                                               double top,
                                               double right,
                                               double bottom) {
  PDFiumEngine* engine = GetEngine(param);
  int page_index = engine->GetVisiblePageIndex(page);
  if (page_index == -1) {
    NOTREACHED();
    return;
  }
  pp::Rect rect = engine->pages_[page_index]->PageToScreen(
      engine->GetVisibleRect().point(), engine->current_zoom_, left, top, right,
      bottom, engine->current_rotation_);
  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::TimeDelta::FromMilliseconds(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);

  FPDF_SYSTEMTIME rv;
  rv.wYear = exploded.year;
  rv.wMonth = exploded.month;
  rv.wDayOfWeek = exploded.day_of_week;
  rv.wDay = exploded.day_of_month;
  rv.wHour = exploded.hour;
  rv.wMinute = exploded.minute;
  rv.wSecond = exploded.second;
  rv.wMilliseconds = exploded.millisecond;
  return rv;
}

// static
void PDFiumFormFiller::Form_OnChange(FPDF_FORMFILLINFO* param) {
  PDFiumEngine* engine = GetEngine(param);
  engine->SetEditMode(true);
}

// static
FPDF_PAGE PDFiumFormFiller::Form_GetPage(FPDF_FORMFILLINFO* param,
                                         FPDF_DOCUMENT document,
                                         int page_index) {
  PDFiumEngine* engine = GetEngine(param);
  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) {
  PDFiumEngine* engine = GetEngine(param);
  int index = engine->last_page_mouse_down_;
  if (index == -1) {
    index = engine->GetMostVisiblePage();
    if (index == -1) {
      NOTREACHED();
      return nullptr;
    }
  }

  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) {
  PDFiumEngine* engine = GetEngine(param);
  std::string action(named_action);
  if (action == "Print") {
    engine->client_->Print();
    return;
  }

  int index = engine->last_page_mouse_down_;
  /* 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_DoURIAction(FPDF_FORMFILLINFO* param,
                                        FPDF_BYTESTRING uri) {
  PDFiumEngine* engine = GetEngine(param);
  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) {
  PDFiumEngine* engine = GetEngine(param);
  engine->ScrollToPage(page_index);
}

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

  PDFiumEngine* engine = GetEngine(param);
  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) {
  PDFiumEngine* engine = GetEngine(param);
  engine->ScrollToPage(page);
}

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

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

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

  float toolbar_height_in_screen_coords =
      engine->GetToolbarHeightInScreenCoords();

  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 y position that can be relied to be visible on the screen is
  // the bottom of the toolbar, which is y = toolbar_height_in_screen_coords.
  float screen_top_in_page_coords =
      page_height * (toolbar_height_in_screen_coords - 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);

  PDFiumEngine* engine = GetEngine(param);
  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) {
  std::string url_str = WideStringToString(url);
  std::string data_str = WideStringToString(data);
  std::string content_type_str = WideStringToString(content_type);
  std::string encode_str = WideStringToString(encode);
  std::string header_str = WideStringToString(header);

  std::string javascript = "alert(\"Post:" + url_str + "," + data_str + "," +
                           content_type_str + "," + encode_str + "," +
                           header_str + "\")";
  return true;
}

// static
FPDF_BOOL PDFiumFormFiller::Form_PutRequestURL(FPDF_FORMFILLINFO* param,
                                               FPDF_WIDESTRING url,
                                               FPDF_WIDESTRING data,
                                               FPDF_WIDESTRING encode) {
  std::string url_str = WideStringToString(url);
  std::string data_str = WideStringToString(data);
  std::string encode_str = WideStringToString(encode);

  std::string javascript =
      "alert(\"Put:" + url_str + "," + data_str + "," + encode_str + "\")";

  return true;
}

// static
void PDFiumFormFiller::Form_UploadTo(FPDF_FORMFILLINFO* param,
                                     FPDF_FILEHANDLER* file_handle,
                                     int file_flag,
                                     FPDF_WIDESTRING to) {
  std::string to_str = WideStringToString(to);
  // TODO: needs the full implementation of form uploading
}

// static
FPDF_LPFILEHANDLER 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.
  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) {
  std::string url_str = WideStringToString(url);
  // TODO: needs to implement GOTO URL action
}

// 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
  };

  PDFiumEngine* engine = GetEngine(param);
  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) {
  PDFiumEngine* engine = GetEngine(param);
  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);

  PDFiumEngine* engine = GetEngine(param);
  std::string rv = engine->client_->Prompt(question_str, default_str);
  base::string16 rv_16 = base::UTF8ToUTF16(rv);
  int rv_bytes = rv_16.size() * sizeof(base::char16);
  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) {
  PDFiumEngine* engine = GetEngine(param);
  std::string rv = engine->client_->GetURL();
  if (file_path && rv.size() <= static_cast<size_t>(length))
    memcpy(file_path, rv.c_str(), rv.size());
  return rv.size();
}

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

  PDFiumEngine* engine = GetEngine(param);
  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.
  PDFiumEngine* engine = GetEngine(param);
  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);
  PDFiumEngine* engine = GetEngine(param);
  engine->client_->SubmitForm(url_str, form_data, length);
}

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

// static
PDFiumEngine* PDFiumFormFiller::GetEngine(FPDF_FORMFILLINFO* info) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(info);
  return form_filler->engine_;
}

// static
PDFiumEngine* PDFiumFormFiller::GetEngine(IPDF_JSPLATFORM* platform) {
  auto* form_filler = static_cast<PDFiumFormFiller*>(platform);
  return form_filler->engine_;
}

int PDFiumFormFiller::SetTimer(const base::TimeDelta& delay,
                               TimerCallback timer_func) {
  const int timer_id = ++last_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) {
  timers_.erase(timer_id);
}

}  // namespace chrome_pdf
