| // Copyright 2016 The PDFium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "fpdfsdk/cpdfsdk_formfillenvironment.h" |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "core/fpdfapi/page/cpdf_annotcontext.h" |
| #include "core/fpdfapi/parser/cpdf_array.h" |
| #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| #include "core/fpdfdoc/cpdf_nametree.h" |
| #include "core/fxcrt/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))); |
| } |
| 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( |
| {pBuff.data(), static_cast<size_t>(nActualLen)}); |
| #else // PDF_ENABLE_XFA |
| return WideString(); |
| #endif // PDF_ENABLE_XFA |
| } |
| |
| WideString CPDFSDK_FormFillEnvironment::GetPlatform() { |
| #ifdef PDF_ENABLE_XFA |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPlatform) |
| return WideString(); |
| |
| int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0); |
| if (nRequiredLen <= 0) |
| return WideString(); |
| |
| DataVector<uint8_t> pBuff(nRequiredLen); |
| int nActualLen = |
| m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen); |
| if (nActualLen <= 0 || nActualLen > nRequiredLen) |
| return WideString(); |
| |
| return WideString::FromUTF16LE( |
| {pBuff.data(), static_cast<size_t>(nActualLen)}); |
| #else // PDF_ENABLE_XFA |
| return WideString(); |
| #endif // PDF_ENABLE_XFA |
| } |
| |
| int CPDFSDK_FormFillEnvironment::JS_appAlert(const WideString& Msg, |
| const WideString& Title, |
| int Type, |
| int Icon) { |
| IPDF_JSPLATFORM* js_platform = GetJSPlatform(); |
| if (!js_platform || !js_platform->app_alert) |
| return -1; |
| |
| ByteString bsMsg = Msg.ToUTF16LE(); |
| ByteString bsTitle = Title.ToUTF16LE(); |
| return js_platform->app_alert(js_platform, AsFPDFWideString(&bsMsg), |
| AsFPDFWideString(&bsTitle), Type, Icon); |
| } |
| |
| int CPDFSDK_FormFillEnvironment::JS_appResponse( |
| const WideString& Question, |
| const WideString& Title, |
| const WideString& Default, |
| const WideString& Label, |
| FPDF_BOOL bPassword, |
| pdfium::span<uint8_t> response) { |
| IPDF_JSPLATFORM* js_platform = GetJSPlatform(); |
| if (!js_platform || !js_platform->app_response) |
| return -1; |
| |
| ByteString bsQuestion = Question.ToUTF16LE(); |
| ByteString bsTitle = Title.ToUTF16LE(); |
| ByteString bsDefault = Default.ToUTF16LE(); |
| ByteString bsLabel = Label.ToUTF16LE(); |
| return js_platform->app_response( |
| js_platform, AsFPDFWideString(&bsQuestion), AsFPDFWideString(&bsTitle), |
| AsFPDFWideString(&bsDefault), AsFPDFWideString(&bsLabel), bPassword, |
| response.data(), pdfium::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)); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::SetCurrentPage(int iCurPage) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_SetCurrentPage) |
| return; |
| m_pInfo->FFI_SetCurrentPage(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), |
| iCurPage); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::GotoURL(const WideString& wsURL) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GotoURL) |
| return; |
| |
| ByteString bsTo = wsURL.ToUTF16LE(); |
| m_pInfo->FFI_GotoURL(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), |
| AsFPDFWideString(&bsTo)); |
| } |
| |
| FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(IPDF_Page* page) { |
| FS_RECTF rect = {0.0f, 0.0f, 0.0f, 0.0f}; |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPageViewRect) |
| return rect; |
| |
| double left; |
| double top; |
| double right; |
| double bottom; |
| m_pInfo->FFI_GetPageViewRect(m_pInfo, FPDFPageFromIPDFPage(page), &left, &top, |
| &right, &bottom); |
| |
| rect.left = static_cast<float>(left); |
| rect.top = static_cast<float>(top); |
| rect.bottom = static_cast<float>(bottom); |
| rect.right = static_cast<float>(right); |
| return rect; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page, |
| int menuFlag, |
| const CFX_PointF& pt) { |
| return m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PopupMenu && |
| m_pInfo->FFI_PopupMenu(m_pInfo, FPDFPageFromIPDFPage(page), nullptr, |
| menuFlag, pt.x, pt.y); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::EmailTo(FPDF_FILEHANDLER* fileHandler, |
| FPDF_WIDESTRING pTo, |
| FPDF_WIDESTRING pSubject, |
| FPDF_WIDESTRING pCC, |
| FPDF_WIDESTRING pBcc, |
| FPDF_WIDESTRING pMsg) { |
| if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_EmailTo) |
| m_pInfo->FFI_EmailTo(m_pInfo, fileHandler, pTo, pSubject, pCC, pBcc, pMsg); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::UploadTo(FPDF_FILEHANDLER* fileHandler, |
| int fileFlag, |
| FPDF_WIDESTRING uploadTo) { |
| if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_UploadTo) |
| m_pInfo->FFI_UploadTo(m_pInfo, fileHandler, fileFlag, uploadTo); |
| } |
| |
| FPDF_FILEHANDLER* CPDFSDK_FormFillEnvironment::OpenFile(int fileType, |
| FPDF_WIDESTRING wsURL, |
| const char* mode) { |
| if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_OpenFile) |
| return m_pInfo->FFI_OpenFile(m_pInfo, fileType, wsURL, mode); |
| return nullptr; |
| } |
| |
| RetainPtr<IFX_SeekableReadStream> CPDFSDK_FormFillEnvironment::DownloadFromURL( |
| const WideString& url) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_DownloadFromURL) |
| return nullptr; |
| |
| ByteString bstrURL = url.ToUTF16LE(); |
| FPDF_FILEHANDLER* fileHandler = |
| m_pInfo->FFI_DownloadFromURL(m_pInfo, AsFPDFWideString(&bstrURL)); |
| |
| return MakeSeekableStream(fileHandler); |
| } |
| |
| WideString CPDFSDK_FormFillEnvironment::PostRequestURL( |
| const WideString& wsURL, |
| const WideString& wsData, |
| const WideString& wsContentType, |
| const WideString& wsEncode, |
| const WideString& wsHeader) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PostRequestURL) |
| return WideString(); |
| |
| ByteString bsURL = wsURL.ToUTF16LE(); |
| ByteString bsData = wsData.ToUTF16LE(); |
| ByteString bsContentType = wsContentType.ToUTF16LE(); |
| ByteString bsEncode = wsEncode.ToUTF16LE(); |
| ByteString bsHeader = wsHeader.ToUTF16LE(); |
| |
| FPDF_BSTR response; |
| FPDF_BStr_Init(&response); |
| m_pInfo->FFI_PostRequestURL( |
| m_pInfo, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData), |
| AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode), |
| AsFPDFWideString(&bsHeader), &response); |
| |
| WideString wsRet = |
| WideString::FromUTF16LE({reinterpret_cast<const uint8_t*>(response.str), |
| static_cast<size_t>(response.len)}); |
| |
| FPDF_BStr_Clear(&response); |
| return wsRet; |
| } |
| |
| FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL( |
| const WideString& wsURL, |
| const WideString& wsData, |
| const WideString& wsEncode) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PutRequestURL) |
| return false; |
| |
| ByteString bsURL = wsURL.ToUTF16LE(); |
| ByteString bsData = wsData.ToUTF16LE(); |
| ByteString bsEncode = wsEncode.ToUTF16LE(); |
| |
| return m_pInfo->FFI_PutRequestURL(m_pInfo, AsFPDFWideString(&bsURL), |
| AsFPDFWideString(&bsData), |
| AsFPDFWideString(&bsEncode)); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, |
| uint32_t dwEventType) const { |
| if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PageEvent) |
| m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType); |
| } |
| #endif // PDF_ENABLE_XFA |
| |
| void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() { |
| for (auto& it : m_PageMap) { |
| if (it.second->IsValidSDKAnnot(GetFocusAnnot())) { |
| ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get()); |
| KillFocusAnnot({}); |
| if (!pObserved) |
| break; |
| } |
| } |
| } |
| |
| CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetOrCreatePageView( |
| IPDF_Page* pUnderlyingPage) { |
| CPDFSDK_PageView* pExisting = GetPageView(pUnderlyingPage); |
| if (pExisting) |
| return pExisting; |
| |
| auto pNew = std::make_unique<CPDFSDK_PageView>(this, pUnderlyingPage); |
| CPDFSDK_PageView* pPageView = pNew.get(); |
| m_PageMap[pUnderlyingPage] = std::move(pNew); |
| |
| // Delay to load all the annotations, to avoid endless loop. |
| pPageView->LoadFXAnnots(); |
| return pPageView; |
| } |
| |
| CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( |
| IPDF_Page* pUnderlyingPage) { |
| auto it = m_PageMap.find(pUnderlyingPage); |
| return it != m_PageMap.end() ? it->second.get() : nullptr; |
| } |
| |
| CFX_Timer::HandlerIface* CPDFSDK_FormFillEnvironment::GetTimerHandler() { |
| return this; |
| } |
| |
| CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageViewAtIndex(int nIndex) { |
| IPDF_Page* pTempPage = GetPage(nIndex); |
| return pTempPage ? GetPageView(pTempPage) : nullptr; |
| } |
| |
| void CPDFSDK_FormFillEnvironment::ProcJavascriptAction() { |
| auto name_tree = CPDF_NameTree::Create(m_pCPDFDoc, "JavaScript"); |
| if (!name_tree) |
| return; |
| |
| size_t count = name_tree->GetCount(); |
| for (size_t i = 0; i < count; ++i) { |
| WideString name; |
| CPDF_Action action(ToDictionary(name_tree->LookupValueAndName(i, &name))); |
| DoActionJavaScript(action, name); |
| } |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::ProcOpenAction() { |
| const CPDF_Dictionary* pRoot = m_pCPDFDoc->GetRoot(); |
| if (!pRoot) |
| return false; |
| |
| RetainPtr<const CPDF_Object> pOpenAction(pRoot->GetDictFor("OpenAction")); |
| if (!pOpenAction) |
| pOpenAction = pRoot->GetArrayFor("OpenAction"); |
| if (!pOpenAction) |
| return false; |
| |
| if (pOpenAction->IsArray()) |
| return true; |
| |
| RetainPtr<const CPDF_Dictionary> pDict = ToDictionary(pOpenAction); |
| if (!pDict) |
| return false; |
| |
| DoActionDocOpen(CPDF_Action(std::move(pDict))); |
| return true; |
| } |
| |
| void CPDFSDK_FormFillEnvironment::RemovePageView(IPDF_Page* pUnderlyingPage) { |
| auto it = m_PageMap.find(pUnderlyingPage); |
| if (it == m_PageMap.end()) |
| return; |
| |
| CPDFSDK_PageView* pPageView = it->second.get(); |
| if (pPageView->IsLocked() || pPageView->IsBeingDestroyed()) |
| return; |
| |
| // Mark the page view so we do not come into |RemovePageView| a second |
| // time while we're in the process of removing. |
| pPageView->SetBeingDestroyed(); |
| |
| // This must happen before we remove |pPageView| from the map because |
| // |KillFocusAnnot| can call into the |GetPage| method which will |
| // look for this page view in the map, if it doesn't find it a new one will |
| // be created. We then have two page views pointing to the same page and |
| // bad things happen. |
| if (pPageView->IsValidSDKAnnot(GetFocusAnnot())) |
| KillFocusAnnot({}); |
| |
| // Remove the page from the map to make sure we don't accidentally attempt |
| // to use the |pPageView| while we're cleaning it up. |
| m_PageMap.erase(it); |
| } |
| |
| IPDF_Page* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) const { |
| if (!m_pInfo || !m_pInfo->FFI_GetPage) |
| return nullptr; |
| return IPDFPageFromFPDFPage(m_pInfo->FFI_GetPage( |
| m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), nIndex)); |
| } |
| |
| CPDFSDK_InteractiveForm* CPDFSDK_FormFillEnvironment::GetInteractiveForm() { |
| if (!m_pInteractiveForm) |
| m_pInteractiveForm = std::make_unique<CPDFSDK_InteractiveForm>(this); |
| return m_pInteractiveForm.get(); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_Annot* pAnnot) { |
| for (const auto& it : m_PageMap) { |
| ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get()); |
| if (pObserved) { |
| pObserved->UpdateView(pAnnot); |
| if (!pObserved) |
| break; |
| } |
| } |
| } |
| |
| CPDFSDK_Annot* CPDFSDK_FormFillEnvironment::GetFocusAnnot() const { |
| return m_pFocusAnnot.Get(); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::SetFocusAnnot( |
| ObservedPtr<CPDFSDK_Annot>& pAnnot) { |
| if (m_bBeingDestroyed) |
| return false; |
| if (m_pFocusAnnot == pAnnot) |
| return true; |
| if (m_pFocusAnnot && !KillFocusAnnot({})) |
| return false; |
| if (!pAnnot) |
| return false; |
| if (!pAnnot->GetPageView()->IsValid()) |
| return false; |
| |
| if (m_pFocusAnnot) |
| return false; |
| |
| #ifdef PDF_ENABLE_XFA |
| CPDFXFA_Widget* pXFAWidget = pAnnot->AsXFAWidget(); |
| if (pXFAWidget && pXFAWidget->OnChangedFocus()) |
| return false; |
| |
| // `pAnnot` may be destroyed in `OnChangedFocus()`. |
| if (!pAnnot) |
| return false; |
| #endif // PDF_ENABLE_XFA |
| |
| if (!CPDFSDK_Annot::OnSetFocus(pAnnot, {})) |
| return false; |
| if (m_pFocusAnnot) |
| return false; |
| |
| m_pFocusAnnot.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(/*get_owner_perms=*/true) & flags); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::SendOnFocusChange( |
| ObservedPtr<CPDFSDK_Annot>& pAnnot) { |
| if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_OnFocusChange) |
| return; |
| |
| // TODO(crbug.com/pdfium/1482): Handle XFA case. |
| if (pAnnot->AsXFAWidget()) |
| return; |
| |
| CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); |
| if (!pPageView->IsValid()) |
| return; |
| |
| IPDF_Page* page = pAnnot->GetPage(); |
| if (!page) |
| return; |
| |
| RetainPtr<CPDF_Dictionary> annot_dict = |
| pAnnot->GetPDFAnnot()->GetMutableAnnotDict(); |
| auto focused_annot = std::make_unique<CPDF_AnnotContext>(annot_dict, page); |
| FPDF_ANNOTATION fpdf_annot = |
| FPDFAnnotationFromCPDFAnnotContext(focused_annot.get()); |
| |
| m_pInfo->FFI_OnFocusChange(m_pInfo, fpdf_annot, pPageView->GetPageIndex()); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionDocOpen(const CPDF_Action& action) { |
| std::set<const CPDF_Dictionary*> visited; |
| return ExecuteDocumentOpenAction(action, &visited); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionJavaScript( |
| const CPDF_Action& JsAction, |
| WideString csJSName) { |
| if (JsAction.GetType() == CPDF_Action::Type::kJavaScript) { |
| WideString swJS = JsAction.GetJavaScript(); |
| if (!swJS.IsEmpty()) { |
| RunDocumentOpenJavaScript(csJSName, swJS); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionFieldJavaScript( |
| const CPDF_Action& JsAction, |
| CPDF_AAction::AActionType type, |
| CPDF_FormField* pFormField, |
| CFFL_FieldAction* data) { |
| if (IsJSPlatformPresent() && |
| JsAction.GetType() == CPDF_Action::Type::kJavaScript) { |
| WideString swJS = JsAction.GetJavaScript(); |
| if (!swJS.IsEmpty()) { |
| RunFieldJavaScript(pFormField, type, data, swJS); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionLink(const CPDF_Action& action, |
| CPDF_AAction::AActionType type, |
| Mask<FWL_EVENTFLAG> modifiers) { |
| if (!CPDF_AAction::IsUserInput(type)) |
| return false; |
| |
| switch (action.GetType()) { |
| case CPDF_Action::Type::kGoTo: |
| DoActionGoTo(action); |
| return true; |
| case CPDF_Action::Type::kURI: |
| DoActionURI(action, modifiers); |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionDestination(const CPDF_Dest& dest) { |
| CPDF_Document* document = GetPDFDocument(); |
| DCHECK(document); |
| |
| std::vector<float> positions = dest.GetScrollPositionArray(); |
| DoGoToAction(dest.GetDestPageIndex(document), dest.GetZoomMode(), positions); |
| return true; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionPage( |
| const CPDF_Action& action, |
| CPDF_AAction::AActionType eType) { |
| std::set<const CPDF_Dictionary*> visited; |
| return ExecuteDocumentPageAction(action, eType, &visited); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionDocument( |
| const CPDF_Action& action, |
| CPDF_AAction::AActionType eType) { |
| std::set<const CPDF_Dictionary*> visited; |
| return ExecuteDocumentPageAction(action, eType, &visited); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionField(const CPDF_Action& action, |
| CPDF_AAction::AActionType type, |
| CPDF_FormField* pFormField, |
| CFFL_FieldAction* data) { |
| std::set<const CPDF_Dictionary*> visited; |
| return ExecuteFieldAction(action, type, pFormField, data, &visited); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::ExecuteDocumentOpenAction( |
| const CPDF_Action& action, |
| std::set<const CPDF_Dictionary*>* visited) { |
| const CPDF_Dictionary* pDict = action.GetDict(); |
| if (pdfium::Contains(*visited, pDict)) |
| return false; |
| |
| visited->insert(pDict); |
| |
| if (action.GetType() == CPDF_Action::Type::kJavaScript) { |
| if (IsJSPlatformPresent()) { |
| WideString swJS = action.GetJavaScript(); |
| if (!swJS.IsEmpty()) |
| RunDocumentOpenJavaScript(WideString(), swJS); |
| } |
| } else { |
| DoActionNoJs(action, CPDF_AAction::AActionType::kDocumentOpen); |
| } |
| |
| for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { |
| CPDF_Action subaction = action.GetSubAction(i); |
| if (!ExecuteDocumentOpenAction(subaction, visited)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::ExecuteDocumentPageAction( |
| const CPDF_Action& action, |
| CPDF_AAction::AActionType type, |
| std::set<const CPDF_Dictionary*>* visited) { |
| const CPDF_Dictionary* pDict = action.GetDict(); |
| if (pdfium::Contains(*visited, pDict)) |
| return false; |
| |
| visited->insert(pDict); |
| |
| if (action.GetType() == CPDF_Action::Type::kJavaScript) { |
| if (IsJSPlatformPresent()) { |
| WideString swJS = action.GetJavaScript(); |
| if (!swJS.IsEmpty()) |
| RunDocumentPageJavaScript(type, swJS); |
| } |
| } else { |
| DoActionNoJs(action, type); |
| } |
| |
| for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { |
| CPDF_Action subaction = action.GetSubAction(i); |
| if (!ExecuteDocumentPageAction(subaction, type, visited)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::IsValidField( |
| const CPDF_Dictionary* pFieldDict) { |
| DCHECK(pFieldDict); |
| |
| CPDFSDK_InteractiveForm* pForm = GetInteractiveForm(); |
| CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm(); |
| return !!pPDFForm->GetFieldByDict(pFieldDict); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::ExecuteFieldAction( |
| const CPDF_Action& action, |
| CPDF_AAction::AActionType type, |
| CPDF_FormField* pFormField, |
| CFFL_FieldAction* data, |
| std::set<const CPDF_Dictionary*>* visited) { |
| const CPDF_Dictionary* pDict = action.GetDict(); |
| if (pdfium::Contains(*visited, pDict)) |
| return false; |
| |
| visited->insert(pDict); |
| |
| if (action.GetType() == CPDF_Action::Type::kJavaScript) { |
| if (IsJSPlatformPresent()) { |
| WideString swJS = action.GetJavaScript(); |
| if (!swJS.IsEmpty()) { |
| RunFieldJavaScript(pFormField, type, data, swJS); |
| if (!IsValidField(pFormField->GetFieldDict())) |
| return false; |
| } |
| } |
| } else { |
| DoActionNoJs(action, type); |
| } |
| |
| for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) { |
| CPDF_Action subaction = action.GetSubAction(i); |
| if (!ExecuteFieldAction(subaction, type, pFormField, data, visited)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void CPDFSDK_FormFillEnvironment::DoActionNoJs(const CPDF_Action& action, |
| CPDF_AAction::AActionType type) { |
| switch (action.GetType()) { |
| case CPDF_Action::Type::kGoTo: |
| DoActionGoTo(action); |
| break; |
| case CPDF_Action::Type::kURI: |
| if (CPDF_AAction::IsUserInput(type)) |
| DoActionURI(action, Mask<FWL_EVENTFLAG>{}); |
| break; |
| case CPDF_Action::Type::kHide: |
| DoActionHide(action); |
| break; |
| case CPDF_Action::Type::kNamed: |
| DoActionNamed(action); |
| break; |
| case CPDF_Action::Type::kSubmitForm: |
| if (CPDF_AAction::IsUserInput(type)) |
| DoActionSubmitForm(action); |
| break; |
| case CPDF_Action::Type::kResetForm: |
| DoActionResetForm(action); |
| break; |
| case CPDF_Action::Type::kJavaScript: |
| NOTREACHED_NORETURN(); |
| case CPDF_Action::Type::kSetOCGState: |
| case CPDF_Action::Type::kThread: |
| case CPDF_Action::Type::kSound: |
| case CPDF_Action::Type::kMovie: |
| case CPDF_Action::Type::kRendition: |
| case CPDF_Action::Type::kTrans: |
| case CPDF_Action::Type::kGoTo3DView: |
| case CPDF_Action::Type::kGoToR: |
| case CPDF_Action::Type::kGoToE: |
| case CPDF_Action::Type::kLaunch: |
| case CPDF_Action::Type::kImportData: |
| // Unimplemented |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void CPDFSDK_FormFillEnvironment::DoActionGoTo(const CPDF_Action& action) { |
| DCHECK(action.GetDict()); |
| |
| CPDF_Document* pPDFDocument = GetPDFDocument(); |
| DCHECK(pPDFDocument); |
| |
| CPDF_Dest MyDest = action.GetDest(pPDFDocument); |
| DoActionDestination(MyDest); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::DoActionURI(const CPDF_Action& action, |
| Mask<FWL_EVENTFLAG> modifiers) { |
| DCHECK(action.GetDict()); |
| DoURIAction(action.GetURI(GetPDFDocument()), modifiers); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::DoActionNamed(const CPDF_Action& action) { |
| DCHECK(action.GetDict()); |
| ExecuteNamedAction(action.GetNamedAction()); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::RunFieldJavaScript( |
| CPDF_FormField* pFormField, |
| CPDF_AAction::AActionType type, |
| CFFL_FieldAction* data, |
| const WideString& script) { |
| DCHECK(type != CPDF_AAction::kCalculate); |
| DCHECK(type != CPDF_AAction::kFormat); |
| |
| RunScript(script, [type, data, pFormField](IJS_EventContext* context) { |
| switch (type) { |
| case CPDF_AAction::kCursorEnter: |
| context->OnField_MouseEnter(data->bModifier, data->bShift, pFormField); |
| break; |
| case CPDF_AAction::kCursorExit: |
| context->OnField_MouseExit(data->bModifier, data->bShift, pFormField); |
| break; |
| case CPDF_AAction::kButtonDown: |
| context->OnField_MouseDown(data->bModifier, data->bShift, pFormField); |
| break; |
| case CPDF_AAction::kButtonUp: |
| context->OnField_MouseUp(data->bModifier, data->bShift, pFormField); |
| break; |
| case CPDF_AAction::kGetFocus: |
| context->OnField_Focus(data->bModifier, data->bShift, pFormField, |
| &data->sValue); |
| break; |
| case CPDF_AAction::kLoseFocus: |
| context->OnField_Blur(data->bModifier, data->bShift, pFormField, |
| &data->sValue); |
| break; |
| case CPDF_AAction::kKeyStroke: |
| context->OnField_Keystroke( |
| &data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier, |
| &data->nSelEnd, &data->nSelStart, data->bShift, pFormField, |
| &data->sValue, data->bWillCommit, data->bFieldFull, &data->bRC); |
| break; |
| case CPDF_AAction::kValidate: |
| context->OnField_Validate(&data->sChange, data->sChangeEx, |
| data->bKeyDown, data->bModifier, data->bShift, |
| pFormField, &data->sValue, &data->bRC); |
| break; |
| default: |
| NOTREACHED_NORETURN(); |
| } |
| }); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::RunDocumentOpenJavaScript( |
| const WideString& sScriptName, |
| const WideString& script) { |
| RunScript(script, [sScriptName](IJS_EventContext* context) { |
| context->OnDoc_Open(sScriptName); |
| }); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::RunDocumentPageJavaScript( |
| CPDF_AAction::AActionType type, |
| const WideString& script) { |
| RunScript(script, [type](IJS_EventContext* context) { |
| switch (type) { |
| case CPDF_AAction::kOpenPage: |
| context->OnPage_Open(); |
| break; |
| case CPDF_AAction::kClosePage: |
| context->OnPage_Close(); |
| break; |
| case CPDF_AAction::kCloseDocument: |
| context->OnDoc_WillClose(); |
| break; |
| case CPDF_AAction::kSaveDocument: |
| context->OnDoc_WillSave(); |
| break; |
| case CPDF_AAction::kDocumentSaved: |
| context->OnDoc_DidSave(); |
| break; |
| case CPDF_AAction::kPrintDocument: |
| context->OnDoc_WillPrint(); |
| break; |
| case CPDF_AAction::kDocumentPrinted: |
| context->OnDoc_DidPrint(); |
| break; |
| case CPDF_AAction::kPageVisible: |
| context->OnPage_InView(); |
| break; |
| case CPDF_AAction::kPageInvisible: |
| context->OnPage_OutView(); |
| break; |
| default: |
| NOTREACHED_NORETURN(); |
| } |
| }); |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionHide(const CPDF_Action& action) { |
| CPDFSDK_InteractiveForm* pForm = GetInteractiveForm(); |
| if (pForm->DoAction_Hide(action)) { |
| SetChangeMark(); |
| return true; |
| } |
| return false; |
| } |
| |
| bool CPDFSDK_FormFillEnvironment::DoActionSubmitForm( |
| const CPDF_Action& action) { |
| CPDFSDK_InteractiveForm* pForm = GetInteractiveForm(); |
| return pForm->DoAction_SubmitForm(action); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::DoActionResetForm(const CPDF_Action& action) { |
| CPDFSDK_InteractiveForm* pForm = GetInteractiveForm(); |
| pForm->DoAction_ResetForm(action); |
| } |
| |
| void CPDFSDK_FormFillEnvironment::RunScript(const WideString& script, |
| const RunScriptCallback& cb) { |
| IJS_Runtime::ScopedEventContext pContext(GetIJSRuntime()); |
| cb(pContext.Get()); |
| pContext->RunScript(script); |
| // TODO(dsinclair): Return error if RunScript returns a IJS_Runtime::JS_Error. |
| } |