1 // Copyright 2016 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_ 8 #define FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_ 9 10 #include <stdint.h> 11 12 #include <map> 13 #include <memory> 14 #include <set> 15 #include <utility> 16 #include <vector> 17 18 #include "core/fpdfapi/page/cpdf_occontext.h" 19 #include "core/fpdfapi/parser/cpdf_document.h" 20 #include "core/fpdfdoc/cpdf_aaction.h" 21 #include "core/fxcrt/cfx_timer.h" 22 #include "core/fxcrt/mask.h" 23 #include "core/fxcrt/observed_ptr.h" 24 #include "core/fxcrt/retain_ptr.h" 25 #include "core/fxcrt/unowned_ptr.h" 26 #include "fpdfsdk/cpdfsdk_annot.h" 27 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" 28 #include "fpdfsdk/pwl/cpwl_wnd.h" 29 #include "fpdfsdk/pwl/ipwl_fillernotify.h" 30 #include "public/fpdf_formfill.h" 31 #include "third_party/base/span.h" 32 33 class CPDF_Action; 34 class CPDF_FormField; 35 class CPDFSDK_InteractiveForm; 36 class CPDFSDK_PageView; 37 class IJS_EventContext; 38 class IJS_Runtime; 39 class IPDF_Page; 40 struct CFFL_FieldAction; 41 42 // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken 43 // since modifying the result would impact |bsUTF16LE|. 44 FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE); 45 46 // The CPDFSDK_FormFillEnvironment is "owned" by the embedder across the 47 // C API as a FPDF_FormHandle, and may pop out of existence at any time, 48 // so long as the associated embedder-owned FPDF_Document outlives it. 49 // Pointers from objects in the FPDF_Document ownership hierarchy should 50 // be ObservedPtr<> so as to clear themselves when the embedder "exits" 51 // the form fill environment. Pointers from objects in this ownership 52 // heirarcy to objects in the FPDF_Document ownership hierarcy should be 53 // UnownedPtr<>, as should pointers from objects in this ownership 54 // hierarcy back to the form fill environment itself, so as to flag any 55 // lingering lifetime issues via the memory tools. 56 57 class CPDFSDK_FormFillEnvironment final 58 : public CFX_Timer::HandlerIface, 59 public CFFL_InteractiveFormFiller::CallbackIface { 60 public: 61 CPDFSDK_FormFillEnvironment(CPDF_Document* pDoc, FPDF_FORMFILLINFO* pFFinfo); 62 63 ~CPDFSDK_FormFillEnvironment() override; 64 65 // TimerHandlerIface: 66 int32_t SetTimer(int32_t uElapse, TimerCallback lpTimerFunc) override; 67 void KillTimer(int32_t nTimerID) override; 68 69 // CFFL_InteractiveFormFiller::CallbackIface: 70 void InvalidateRect(CPDFSDK_Widget* widget, 71 const CFX_FloatRect& rect) override; 72 void OutputSelectedRect(CFFL_FormField* pFormField, 73 const CFX_FloatRect& rect) override; 74 bool IsSelectionImplemented() const override; 75 void SetCursor(IPWL_FillerNotify::CursorStyle nCursorType) override; 76 void OnSetFieldInputFocus(const WideString& text) override; 77 void OnCalculate(ObservedPtr<CPDFSDK_Annot>& pAnnot) override; 78 void OnFormat(ObservedPtr<CPDFSDK_Annot>& pAnnot) override; 79 void Invalidate(IPDF_Page* page, const FX_RECT& rect) override; 80 CPDFSDK_PageView* GetOrCreatePageView(IPDF_Page* pUnderlyingPage) override; 81 CPDFSDK_PageView* GetPageView(IPDF_Page* pUnderlyingPage) override; 82 CFX_Timer::HandlerIface* GetTimerHandler() override; 83 CPDFSDK_Annot* GetFocusAnnot() const override; 84 bool SetFocusAnnot(ObservedPtr<CPDFSDK_Annot>& pAnnot) override; 85 bool HasPermissions(uint32_t flags) const override; 86 void OnChange() override; 87 88 CPDFSDK_PageView* GetPageViewAtIndex(int nIndex); 89 void RemovePageView(IPDF_Page* pUnderlyingPage); 90 void UpdateAllViews(CPDFSDK_Annot* pAnnot); 91 92 bool KillFocusAnnot(Mask<FWL_EVENTFLAG> nFlags); 93 void ClearAllFocusedAnnots(); 94 95 int GetPageCount() const; 96 GetChangeMark()97 bool GetChangeMark() const { return m_bChangeMask; } SetChangeMark()98 void SetChangeMark() { m_bChangeMask = true; } ClearChangeMark()99 void ClearChangeMark() { m_bChangeMask = false; } 100 101 void ProcJavascriptAction(); 102 bool ProcOpenAction(); 103 104 void ExecuteNamedAction(const ByteString& namedAction); 105 void DoURIAction(const ByteString& bsURI, Mask<FWL_EVENTFLAG> modifiers); 106 void DoGoToAction(int nPageIndex, 107 int zoomMode, 108 pdfium::span<float> fPosArray); 109 GetPDFDocument()110 CPDF_Document* GetPDFDocument() const { return m_pCPDFDoc; } GetDocExtension()111 CPDF_Document::Extension* GetDocExtension() const { 112 return m_pCPDFDoc->GetExtension(); 113 } 114 IsJSPlatformPresent()115 bool IsJSPlatformPresent() const { return m_pInfo && m_pInfo->m_pJsPlatform; } GetJSPlatform()116 IPDF_JSPLATFORM* GetJSPlatform() const { 117 return m_pInfo ? m_pInfo->m_pJsPlatform : nullptr; 118 } 119 120 // Actions. 121 bool DoActionDocOpen(const CPDF_Action& action); 122 bool DoActionJavaScript(const CPDF_Action& JsAction, WideString csJSName); 123 bool DoActionPage(const CPDF_Action& action, CPDF_AAction::AActionType eType); 124 bool DoActionDocument(const CPDF_Action& action, 125 CPDF_AAction::AActionType eType); 126 bool DoActionField(const CPDF_Action& action, 127 CPDF_AAction::AActionType type, 128 CPDF_FormField* pFormField, 129 CFFL_FieldAction* data); 130 bool DoActionFieldJavaScript(const CPDF_Action& JsAction, 131 CPDF_AAction::AActionType type, 132 CPDF_FormField* pFormField, 133 CFFL_FieldAction* data); 134 bool DoActionLink(const CPDF_Action& action, 135 CPDF_AAction::AActionType type, 136 Mask<FWL_EVENTFLAG> modifiers); 137 bool DoActionDestination(const CPDF_Dest& dest); 138 void DoActionNoJs(const CPDF_Action& action, CPDF_AAction::AActionType type); 139 void DoActionGoTo(const CPDF_Action& action); 140 void DoActionLaunch(const CPDF_Action& action); 141 void DoActionURI(const CPDF_Action& action, Mask<FWL_EVENTFLAG> modifiers); 142 void DoActionNamed(const CPDF_Action& action); 143 bool DoActionHide(const CPDF_Action& action); 144 bool DoActionSubmitForm(const CPDF_Action& action); 145 void DoActionResetForm(const CPDF_Action& action); 146 147 #ifdef PDF_ENABLE_V8 148 CPDFSDK_PageView* GetCurrentView(); 149 IPDF_Page* GetCurrentPage() const; 150 151 WideString GetLanguage(); 152 WideString GetPlatform(); 153 154 int JS_appAlert(const WideString& Msg, 155 const WideString& Title, 156 int Type, 157 int Icon); 158 int JS_appResponse(const WideString& Question, 159 const WideString& Title, 160 const WideString& Default, 161 const WideString& cLabel, 162 FPDF_BOOL bPassword, 163 pdfium::span<uint8_t> response); 164 void JS_appBeep(int nType); 165 WideString JS_fieldBrowse(); 166 void JS_docmailForm(pdfium::span<const uint8_t> mailData, 167 FPDF_BOOL bUI, 168 const WideString& To, 169 const WideString& Subject, 170 const WideString& CC, 171 const WideString& BCC, 172 const WideString& Msg); 173 void JS_docprint(FPDF_BOOL bUI, 174 int nStart, 175 int nEnd, 176 FPDF_BOOL bSilent, 177 FPDF_BOOL bShrinkToFit, 178 FPDF_BOOL bPrintAsImage, 179 FPDF_BOOL bReverse, 180 FPDF_BOOL bAnnotations); 181 void JS_docgotoPage(int nPageNum); 182 WideString JS_docGetFilePath(); 183 184 #ifdef PDF_ENABLE_XFA 185 int GetPageViewCount() const; 186 void DisplayCaret(IPDF_Page* page, 187 FPDF_BOOL bVisible, 188 double left, 189 double top, 190 double right, 191 double bottom); 192 int GetCurrentPageIndex() const; 193 void SetCurrentPage(int iCurPage); 194 195 // TODO(dsinclair): This should probably change to PDFium? FFI_GetAppName()196 WideString FFI_GetAppName() const { return WideString(L"Acrobat"); } 197 198 void GotoURL(const WideString& wsURL); 199 FS_RECTF GetPageViewRect(IPDF_Page* page); 200 bool PopupMenu(IPDF_Page* page, int menuFlag, const CFX_PointF& pt); 201 void EmailTo(FPDF_FILEHANDLER* fileHandler, 202 FPDF_WIDESTRING pTo, 203 FPDF_WIDESTRING pSubject, 204 FPDF_WIDESTRING pCC, 205 FPDF_WIDESTRING pBcc, 206 FPDF_WIDESTRING pMsg); 207 void UploadTo(FPDF_FILEHANDLER* fileHandler, 208 int fileFlag, 209 FPDF_WIDESTRING uploadTo); 210 FPDF_FILEHANDLER* OpenFile(int fileType, 211 FPDF_WIDESTRING wsURL, 212 const char* mode); 213 RetainPtr<IFX_SeekableReadStream> DownloadFromURL(const WideString& url); 214 WideString PostRequestURL(const WideString& wsURL, 215 const WideString& wsData, 216 const WideString& wsContentType, 217 const WideString& wsEncode, 218 const WideString& wsHeader); 219 FPDF_BOOL PutRequestURL(const WideString& wsURL, 220 const WideString& wsData, 221 const WideString& wsEncode); 222 223 void PageEvent(int iPageCount, uint32_t dwEventType) const; 224 #endif // PDF_ENABLE_XFA 225 #endif // PDF_ENABLE_V8 226 227 WideString GetFilePath() const; GetAppName()228 ByteString GetAppName() const { return ByteString(); } GetFormFillInfo()229 FPDF_FORMFILLINFO* GetFormFillInfo() const { return m_pInfo; } 230 void SubmitForm(pdfium::span<const uint8_t> form_data, const WideString& URL); 231 SetFocusableAnnotSubtypes(const std::vector<CPDF_Annot::Subtype> & focusableAnnotTypes)232 void SetFocusableAnnotSubtypes( 233 const std::vector<CPDF_Annot::Subtype>& focusableAnnotTypes) { 234 m_FocusableAnnotTypes = focusableAnnotTypes; 235 } GetFocusableAnnotSubtypes()236 const std::vector<CPDF_Annot::Subtype>& GetFocusableAnnotSubtypes() const { 237 return m_FocusableAnnotTypes; 238 } 239 240 // Never returns null. GetInteractiveFormFiller()241 CFFL_InteractiveFormFiller* GetInteractiveFormFiller() { 242 return m_pInteractiveFormFiller.get(); 243 } 244 245 IJS_Runtime* GetIJSRuntime(); // Creates if not present. 246 CPDFSDK_InteractiveForm* GetInteractiveForm(); // Creates if not present. 247 248 private: 249 using RunScriptCallback = std::function<void(IJS_EventContext* context)>; 250 251 IPDF_Page* GetPage(int nIndex) const; 252 void OnSetFieldInputFocusInternal(const WideString& text, bool bFocus); 253 void SendOnFocusChange(ObservedPtr<CPDFSDK_Annot>& pAnnot); 254 255 // Support methods for Actions. 256 void RunScript(const WideString& script, const RunScriptCallback& cb); 257 bool ExecuteDocumentOpenAction(const CPDF_Action& action, 258 std::set<const CPDF_Dictionary*>* visited); 259 bool ExecuteDocumentPageAction(const CPDF_Action& action, 260 CPDF_AAction::AActionType type, 261 std::set<const CPDF_Dictionary*>* visited); 262 bool ExecuteFieldAction(const CPDF_Action& action, 263 CPDF_AAction::AActionType type, 264 CPDF_FormField* pFormField, 265 CFFL_FieldAction* data, 266 std::set<const CPDF_Dictionary*>* visited); 267 void RunDocumentPageJavaScript(CPDF_AAction::AActionType type, 268 const WideString& script); 269 void RunDocumentOpenJavaScript(const WideString& sScriptName, 270 const WideString& script); 271 void RunFieldJavaScript(CPDF_FormField* pFormField, 272 CPDF_AAction::AActionType type, 273 CFFL_FieldAction* data, 274 const WideString& script); 275 bool IsValidField(const CPDF_Dictionary* pFieldDict); 276 277 UnownedPtr<FPDF_FORMFILLINFO> const m_pInfo; 278 std::unique_ptr<IJS_Runtime> m_pIJSRuntime; 279 280 // Iterator stability guarantees as provided by std::map<> required. 281 std::map<IPDF_Page*, std::unique_ptr<CPDFSDK_PageView>> m_PageMap; 282 283 std::unique_ptr<CPDFSDK_InteractiveForm> m_pInteractiveForm; 284 ObservedPtr<CPDFSDK_Annot> m_pFocusAnnot; 285 UnownedPtr<CPDF_Document> const m_pCPDFDoc; 286 std::unique_ptr<CFFL_InteractiveFormFiller> m_pInteractiveFormFiller; 287 bool m_bChangeMask = false; 288 bool m_bBeingDestroyed = false; 289 290 // Holds the list of focusable annot types. 291 // Annotations of type WIDGET are by default focusable. 292 std::vector<CPDF_Annot::Subtype> m_FocusableAnnotTypes = { 293 CPDF_Annot::Subtype::WIDGET}; 294 }; 295 296 #endif // FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_ 297