// 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 #ifndef FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_ #define FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_ #include #include #include #include #include #include #include "core/fpdfapi/page/cpdf_occontext.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfdoc/cpdf_aaction.h" #include "core/fxcrt/cfx_timer.h" #include "core/fxcrt/mask.h" #include "core/fxcrt/observed_ptr.h" #include "core/fxcrt/retain_ptr.h" #include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/pwl/cpwl_wnd.h" #include "fpdfsdk/pwl/ipwl_fillernotify.h" #include "public/fpdf_formfill.h" #include "third_party/base/containers/span.h" class CPDF_Action; class CPDF_FormField; class CPDFSDK_InteractiveForm; class CPDFSDK_PageView; class IJS_EventContext; class IJS_Runtime; class IPDF_Page; struct CFFL_FieldAction; // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken // since modifying the result would impact |bsUTF16LE|. FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE); // The CPDFSDK_FormFillEnvironment is "owned" by the embedder across the // C API as a FPDF_FormHandle, and may pop out of existence at any time, // so long as the associated embedder-owned FPDF_Document outlives it. // Pointers from objects in the FPDF_Document ownership hierarchy should // be ObservedPtr<> so as to clear themselves when the embedder "exits" // the form fill environment. Pointers from objects in this ownership // heirarcy to objects in the FPDF_Document ownership hierarcy should be // UnownedPtr<>, as should pointers from objects in this ownership // hierarcy back to the form fill environment itself, so as to flag any // lingering lifetime issues via the memory tools. class CPDFSDK_FormFillEnvironment final : public CFX_Timer::HandlerIface, public CFFL_InteractiveFormFiller::CallbackIface { public: CPDFSDK_FormFillEnvironment(CPDF_Document* pDoc, FPDF_FORMFILLINFO* pFFinfo); ~CPDFSDK_FormFillEnvironment() override; // TimerHandlerIface: int32_t SetTimer(int32_t uElapse, TimerCallback lpTimerFunc) override; void KillTimer(int32_t nTimerID) override; // CFFL_InteractiveFormFiller::CallbackIface: void InvalidateRect(CPDFSDK_Widget* widget, const CFX_FloatRect& rect) override; void OutputSelectedRect(CFFL_FormField* pFormField, const CFX_FloatRect& rect) override; bool IsSelectionImplemented() const override; void SetCursor(IPWL_FillerNotify::CursorStyle nCursorType) override; void OnSetFieldInputFocus(const WideString& text) override; void OnCalculate(ObservedPtr& pAnnot) override; void OnFormat(ObservedPtr& pAnnot) override; void Invalidate(IPDF_Page* page, const FX_RECT& rect) override; CPDFSDK_PageView* GetOrCreatePageView(IPDF_Page* pUnderlyingPage) override; CPDFSDK_PageView* GetPageView(IPDF_Page* pUnderlyingPage) override; CFX_Timer::HandlerIface* GetTimerHandler() override; CPDFSDK_Annot* GetFocusAnnot() const override; bool SetFocusAnnot(ObservedPtr& pAnnot) override; bool HasPermissions(uint32_t flags) const override; void OnChange() override; CPDFSDK_PageView* GetPageViewAtIndex(int nIndex); void RemovePageView(IPDF_Page* pUnderlyingPage); void UpdateAllViews(CPDFSDK_Annot* pAnnot); bool KillFocusAnnot(Mask nFlags); void ClearAllFocusedAnnots(); int GetPageCount() const; bool GetChangeMark() const { return m_bChangeMask; } void SetChangeMark() { m_bChangeMask = true; } void ClearChangeMark() { m_bChangeMask = false; } void ProcJavascriptAction(); bool ProcOpenAction(); void ExecuteNamedAction(const ByteString& namedAction); void DoURIAction(const ByteString& bsURI, Mask modifiers); void DoGoToAction(int nPageIndex, int zoomMode, pdfium::span fPosArray); CPDF_Document* GetPDFDocument() const { return m_pCPDFDoc; } CPDF_Document::Extension* GetDocExtension() const { return m_pCPDFDoc->GetExtension(); } bool IsJSPlatformPresent() const { return m_pInfo && m_pInfo->m_pJsPlatform; } IPDF_JSPLATFORM* GetJSPlatform() const { return m_pInfo ? m_pInfo->m_pJsPlatform : nullptr; } // Actions. bool DoActionDocOpen(const CPDF_Action& action); bool DoActionJavaScript(const CPDF_Action& JsAction, WideString csJSName); bool DoActionPage(const CPDF_Action& action, CPDF_AAction::AActionType eType); bool DoActionDocument(const CPDF_Action& action, CPDF_AAction::AActionType eType); bool DoActionField(const CPDF_Action& action, CPDF_AAction::AActionType type, CPDF_FormField* pFormField, CFFL_FieldAction* data); bool DoActionFieldJavaScript(const CPDF_Action& JsAction, CPDF_AAction::AActionType type, CPDF_FormField* pFormField, CFFL_FieldAction* data); bool DoActionLink(const CPDF_Action& action, CPDF_AAction::AActionType type, Mask modifiers); bool DoActionDestination(const CPDF_Dest& dest); void DoActionNoJs(const CPDF_Action& action, CPDF_AAction::AActionType type); void DoActionGoTo(const CPDF_Action& action); void DoActionLaunch(const CPDF_Action& action); void DoActionURI(const CPDF_Action& action, Mask modifiers); void DoActionNamed(const CPDF_Action& action); bool DoActionHide(const CPDF_Action& action); bool DoActionSubmitForm(const CPDF_Action& action); void DoActionResetForm(const CPDF_Action& action); #ifdef PDF_ENABLE_V8 CPDFSDK_PageView* GetCurrentView(); IPDF_Page* GetCurrentPage() const; WideString GetLanguage(); WideString GetPlatform(); int JS_appAlert(const WideString& Msg, const WideString& Title, int Type, int Icon); int JS_appResponse(const WideString& Question, const WideString& Title, const WideString& Default, const WideString& cLabel, FPDF_BOOL bPassword, pdfium::span response); void JS_appBeep(int nType); WideString JS_fieldBrowse(); void JS_docmailForm(pdfium::span mailData, FPDF_BOOL bUI, const WideString& To, const WideString& Subject, const WideString& CC, const WideString& BCC, const WideString& Msg); void JS_docprint(FPDF_BOOL bUI, int nStart, int nEnd, FPDF_BOOL bSilent, FPDF_BOOL bShrinkToFit, FPDF_BOOL bPrintAsImage, FPDF_BOOL bReverse, FPDF_BOOL bAnnotations); void JS_docgotoPage(int nPageNum); WideString JS_docGetFilePath(); #ifdef PDF_ENABLE_XFA int GetPageViewCount() const; void DisplayCaret(IPDF_Page* page, FPDF_BOOL bVisible, double left, double top, double right, double bottom); int GetCurrentPageIndex() const; void SetCurrentPage(int iCurPage); // TODO(dsinclair): This should probably change to PDFium? WideString FFI_GetAppName() const { return WideString(L"Acrobat"); } void GotoURL(const WideString& wsURL); FS_RECTF GetPageViewRect(IPDF_Page* page); bool PopupMenu(IPDF_Page* page, int menuFlag, const CFX_PointF& pt); void EmailTo(FPDF_FILEHANDLER* fileHandler, FPDF_WIDESTRING pTo, FPDF_WIDESTRING pSubject, FPDF_WIDESTRING pCC, FPDF_WIDESTRING pBcc, FPDF_WIDESTRING pMsg); void UploadTo(FPDF_FILEHANDLER* fileHandler, int fileFlag, FPDF_WIDESTRING uploadTo); FPDF_FILEHANDLER* OpenFile(int fileType, FPDF_WIDESTRING wsURL, const char* mode); RetainPtr DownloadFromURL(const WideString& url); WideString PostRequestURL(const WideString& wsURL, const WideString& wsData, const WideString& wsContentType, const WideString& wsEncode, const WideString& wsHeader); FPDF_BOOL PutRequestURL(const WideString& wsURL, const WideString& wsData, const WideString& wsEncode); void PageEvent(int iPageCount, uint32_t dwEventType) const; #endif // PDF_ENABLE_XFA #endif // PDF_ENABLE_V8 WideString GetFilePath() const; ByteString GetAppName() const { return ByteString(); } FPDF_FORMFILLINFO* GetFormFillInfo() const { return m_pInfo; } void SubmitForm(pdfium::span form_data, const WideString& URL); void SetFocusableAnnotSubtypes( const std::vector& focusableAnnotTypes) { m_FocusableAnnotTypes = focusableAnnotTypes; } const std::vector& GetFocusableAnnotSubtypes() const { return m_FocusableAnnotTypes; } // Never returns null. CFFL_InteractiveFormFiller* GetInteractiveFormFiller() { return m_pInteractiveFormFiller.get(); } IJS_Runtime* GetIJSRuntime(); // Creates if not present. CPDFSDK_InteractiveForm* GetInteractiveForm(); // Creates if not present. private: using RunScriptCallback = std::function; IPDF_Page* GetPage(int nIndex) const; void OnSetFieldInputFocusInternal(const WideString& text, bool bFocus); void SendOnFocusChange(ObservedPtr& pAnnot); // Support methods for Actions. void RunScript(const WideString& script, const RunScriptCallback& cb); bool ExecuteDocumentOpenAction(const CPDF_Action& action, std::set* visited); bool ExecuteDocumentPageAction(const CPDF_Action& action, CPDF_AAction::AActionType type, std::set* visited); bool ExecuteFieldAction(const CPDF_Action& action, CPDF_AAction::AActionType type, CPDF_FormField* pFormField, CFFL_FieldAction* data, std::set* visited); void RunDocumentPageJavaScript(CPDF_AAction::AActionType type, const WideString& script); void RunDocumentOpenJavaScript(const WideString& sScriptName, const WideString& script); void RunFieldJavaScript(CPDF_FormField* pFormField, CPDF_AAction::AActionType type, CFFL_FieldAction* data, const WideString& script); bool IsValidField(const CPDF_Dictionary* pFieldDict); UnownedPtr const m_pInfo; std::unique_ptr m_pIJSRuntime; // Iterator stability guarantees as provided by std::map<> required. std::map> m_PageMap; std::unique_ptr m_pInteractiveForm; ObservedPtr m_pFocusAnnot; UnownedPtr const m_pCPDFDoc; std::unique_ptr m_pInteractiveFormFiller; bool m_bChangeMask = false; bool m_bBeingDestroyed = false; // Holds the list of focusable annot types. // Annotations of type WIDGET are by default focusable. std::vector m_FocusableAnnotTypes = { CPDF_Annot::Subtype::WIDGET}; }; #endif // FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_