297 lines
12 KiB
C++
297 lines
12 KiB
C++
// 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 <stdint.h>
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#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/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<CPDFSDK_Annot>& pAnnot) override;
|
|
void OnFormat(ObservedPtr<CPDFSDK_Annot>& 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<CPDFSDK_Annot>& 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<FWL_EVENTFLAG> 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<FWL_EVENTFLAG> modifiers);
|
|
void DoGoToAction(int nPageIndex,
|
|
int zoomMode,
|
|
pdfium::span<float> 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<FWL_EVENTFLAG> 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<FWL_EVENTFLAG> 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<uint8_t> response);
|
|
void JS_appBeep(int nType);
|
|
WideString JS_fieldBrowse();
|
|
void 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);
|
|
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<IFX_SeekableReadStream> 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<const uint8_t> form_data, const WideString& URL);
|
|
|
|
void SetFocusableAnnotSubtypes(
|
|
const std::vector<CPDF_Annot::Subtype>& focusableAnnotTypes) {
|
|
m_FocusableAnnotTypes = focusableAnnotTypes;
|
|
}
|
|
const std::vector<CPDF_Annot::Subtype>& 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<void(IJS_EventContext* context)>;
|
|
|
|
IPDF_Page* GetPage(int nIndex) const;
|
|
void OnSetFieldInputFocusInternal(const WideString& text, bool bFocus);
|
|
void SendOnFocusChange(ObservedPtr<CPDFSDK_Annot>& pAnnot);
|
|
|
|
// Support methods for Actions.
|
|
void RunScript(const WideString& script, const RunScriptCallback& cb);
|
|
bool ExecuteDocumentOpenAction(const CPDF_Action& action,
|
|
std::set<const CPDF_Dictionary*>* visited);
|
|
bool ExecuteDocumentPageAction(const CPDF_Action& action,
|
|
CPDF_AAction::AActionType type,
|
|
std::set<const CPDF_Dictionary*>* visited);
|
|
bool ExecuteFieldAction(const CPDF_Action& action,
|
|
CPDF_AAction::AActionType type,
|
|
CPDF_FormField* pFormField,
|
|
CFFL_FieldAction* data,
|
|
std::set<const CPDF_Dictionary*>* 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<FPDF_FORMFILLINFO> const m_pInfo;
|
|
std::unique_ptr<IJS_Runtime> m_pIJSRuntime;
|
|
|
|
// Iterator stability guarantees as provided by std::map<> required.
|
|
std::map<IPDF_Page*, std::unique_ptr<CPDFSDK_PageView>> m_PageMap;
|
|
|
|
std::unique_ptr<CPDFSDK_InteractiveForm> m_pInteractiveForm;
|
|
ObservedPtr<CPDFSDK_Annot> m_pFocusAnnot;
|
|
UnownedPtr<CPDF_Document> const m_pCPDFDoc;
|
|
std::unique_ptr<CFFL_InteractiveFormFiller> 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<CPDF_Annot::Subtype> m_FocusableAnnotTypes = {
|
|
CPDF_Annot::Subtype::WIDGET};
|
|
};
|
|
|
|
#endif // FPDFSDK_CPDFSDK_FORMFILLENVIRONMENT_H_
|