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