• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
8 
9 #include <stdint.h>
10 
11 #include <memory>
12 #include <utility>
13 #include <vector>
14 
15 #include "core/fpdfapi/page/cpdf_annotcontext.h"
16 #include "core/fpdfapi/parser/cpdf_array.h"
17 #include "core/fpdfapi/parser/cpdf_dictionary.h"
18 #include "core/fpdfdoc/cpdf_nametree.h"
19 #include "core/fxcrt/data_vector.h"
20 #include "core/fxcrt/stl_util.h"
21 #include "fpdfsdk/cpdfsdk_helpers.h"
22 #include "fpdfsdk/cpdfsdk_interactiveform.h"
23 #include "fpdfsdk/cpdfsdk_pageview.h"
24 #include "fpdfsdk/cpdfsdk_widget.h"
25 #include "fpdfsdk/formfiller/cffl_formfield.h"
26 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
27 #include "fxjs/ijs_event_context.h"
28 #include "fxjs/ijs_runtime.h"
29 #include "third_party/base/check.h"
30 #include "third_party/base/containers/contains.h"
31 #include "third_party/base/notreached.h"
32 #include "third_party/base/numerics/safe_conversions.h"
33 
34 #ifdef PDF_ENABLE_XFA
35 #include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
36 #endif
37 
38 static_assert(FXCT_ARROW ==
39                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kArrow),
40               "kArrow value mismatch");
41 static_assert(FXCT_NESW ==
42                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kNESW),
43               "kNEWS value mismatch");
44 static_assert(FXCT_NWSE ==
45                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kNWSE),
46               "kNWSE value mismatch");
47 static_assert(FXCT_VBEAM ==
48                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kVBeam),
49               "kVBeam value mismatch");
50 static_assert(FXCT_HBEAM ==
51                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kHBeam),
52               "HBeam value mismatch");
53 static_assert(FXCT_HAND ==
54                   static_cast<int>(IPWL_FillerNotify::CursorStyle::kHand),
55               "kHand value mismatch");
56 
AsFPDFWideString(ByteString * bsUTF16LE)57 FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) {
58   // Force a private version of the string, since we're about to hand it off
59   // to the embedder. Should the embedder modify it by accident, it won't
60   // corrupt other shares of the string beyond |bsUTF16LE|.
61   return reinterpret_cast<FPDF_WIDESTRING>(
62       bsUTF16LE->GetBuffer(bsUTF16LE->GetLength()).data());
63 }
64 
CPDFSDK_FormFillEnvironment(CPDF_Document * pDoc,FPDF_FORMFILLINFO * pFFinfo)65 CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment(
66     CPDF_Document* pDoc,
67     FPDF_FORMFILLINFO* pFFinfo)
68     : m_pInfo(pFFinfo),
69       m_pCPDFDoc(pDoc),
70       m_pInteractiveFormFiller(
71           std::make_unique<CFFL_InteractiveFormFiller>(this)) {
72   DCHECK(m_pCPDFDoc);
73 }
74 
~CPDFSDK_FormFillEnvironment()75 CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() {
76   m_bBeingDestroyed = true;
77   ClearAllFocusedAnnots();
78 
79   // |m_PageMap| will try to access |m_pInteractiveForm| when it cleans itself
80   // up. Make sure it is deleted before |m_pInteractiveForm|.
81   m_PageMap.clear();
82 
83   // Must destroy the |m_pInteractiveFormFiller| before the environment (|this|)
84   // because any created form widgets hold a pointer to the environment.
85   // Those widgets may call things like KillTimer() as they are shutdown.
86   m_pInteractiveFormFiller.reset();
87 
88   if (m_pInfo && m_pInfo->Release)
89     m_pInfo->Release(m_pInfo);
90 }
91 
InvalidateRect(CPDFSDK_Widget * widget,const CFX_FloatRect & rect)92 void CPDFSDK_FormFillEnvironment::InvalidateRect(CPDFSDK_Widget* widget,
93                                                  const CFX_FloatRect& rect) {
94   IPDF_Page* pPage = widget->GetPage();
95   if (!pPage)
96     return;
97 
98   CFX_Matrix device2page =
99       widget->GetPageView()->GetCurrentMatrix().GetInverse();
100   CFX_PointF left_top = device2page.Transform(CFX_PointF(rect.left, rect.top));
101   CFX_PointF right_bottom =
102       device2page.Transform(CFX_PointF(rect.right, rect.bottom));
103 
104   CFX_FloatRect rcPDF(left_top.x, right_bottom.y, right_bottom.x, left_top.y);
105   rcPDF.Normalize();
106   Invalidate(pPage, rcPDF.GetOuterRect());
107 }
108 
OutputSelectedRect(CFFL_FormField * pFormField,const CFX_FloatRect & rect)109 void CPDFSDK_FormFillEnvironment::OutputSelectedRect(
110     CFFL_FormField* pFormField,
111     const CFX_FloatRect& rect) {
112   if (!m_pInfo || !m_pInfo->FFI_OutputSelectedRect)
113     return;
114 
115   auto* pPage = FPDFPageFromIPDFPage(pFormField->GetSDKWidget()->GetPage());
116   DCHECK(pPage);
117 
118   CFX_PointF ptA = pFormField->PWLtoFFL(CFX_PointF(rect.left, rect.bottom));
119   CFX_PointF ptB = pFormField->PWLtoFFL(CFX_PointF(rect.right, rect.top));
120   m_pInfo->FFI_OutputSelectedRect(m_pInfo, pPage, ptA.x, ptB.y, ptB.x, ptA.y);
121 }
122 
IsSelectionImplemented() const123 bool CPDFSDK_FormFillEnvironment::IsSelectionImplemented() const {
124   FPDF_FORMFILLINFO* pInfo = GetFormFillInfo();
125   return pInfo && pInfo->FFI_OutputSelectedRect;
126 }
127 
128 #ifdef PDF_ENABLE_V8
GetCurrentView()129 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
130   IPDF_Page* pPage = GetCurrentPage();
131   return pPage ? GetOrCreatePageView(pPage) : nullptr;
132 }
133 
GetCurrentPage() const134 IPDF_Page* CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
135   if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
136     return IPDFPageFromFPDFPage(m_pInfo->FFI_GetCurrentPage(
137         m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc)));
138   }
139   return nullptr;
140 }
141 
GetLanguage()142 WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
143 #ifdef PDF_ENABLE_XFA
144   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetLanguage)
145     return WideString();
146 
147   int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
148   if (nRequiredLen <= 0)
149     return WideString();
150 
151   DataVector<uint8_t> pBuff(nRequiredLen);
152   int nActualLen =
153       m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
154   if (nActualLen <= 0 || nActualLen > nRequiredLen)
155     return WideString();
156 
157   return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
158                                  nActualLen / sizeof(uint16_t));
159 #else   // PDF_ENABLE_XFA
160   return WideString();
161 #endif  // PDF_ENABLE_XFA
162 }
163 
GetPlatform()164 WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
165 #ifdef PDF_ENABLE_XFA
166   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPlatform)
167     return WideString();
168 
169   int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
170   if (nRequiredLen <= 0)
171     return WideString();
172 
173   DataVector<uint8_t> pBuff(nRequiredLen);
174   int nActualLen =
175       m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
176   if (nActualLen <= 0 || nActualLen > nRequiredLen)
177     return WideString();
178 
179   return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
180                                  nActualLen / sizeof(uint16_t));
181 #else   // PDF_ENABLE_XFA
182   return WideString();
183 #endif  // PDF_ENABLE_XFA
184 }
185 
JS_appAlert(const WideString & Msg,const WideString & Title,int Type,int Icon)186 int CPDFSDK_FormFillEnvironment::JS_appAlert(const WideString& Msg,
187                                              const WideString& Title,
188                                              int Type,
189                                              int Icon) {
190   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
191   if (!js_platform || !js_platform->app_alert)
192     return -1;
193 
194   ByteString bsMsg = Msg.ToUTF16LE();
195   ByteString bsTitle = Title.ToUTF16LE();
196   return js_platform->app_alert(js_platform, AsFPDFWideString(&bsMsg),
197                                 AsFPDFWideString(&bsTitle), Type, Icon);
198 }
199 
JS_appResponse(const WideString & Question,const WideString & Title,const WideString & Default,const WideString & Label,FPDF_BOOL bPassword,pdfium::span<uint8_t> response)200 int CPDFSDK_FormFillEnvironment::JS_appResponse(
201     const WideString& Question,
202     const WideString& Title,
203     const WideString& Default,
204     const WideString& Label,
205     FPDF_BOOL bPassword,
206     pdfium::span<uint8_t> response) {
207   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
208   if (!js_platform || !js_platform->app_response)
209     return -1;
210 
211   ByteString bsQuestion = Question.ToUTF16LE();
212   ByteString bsTitle = Title.ToUTF16LE();
213   ByteString bsDefault = Default.ToUTF16LE();
214   ByteString bsLabel = Label.ToUTF16LE();
215   return js_platform->app_response(
216       js_platform, AsFPDFWideString(&bsQuestion), AsFPDFWideString(&bsTitle),
217       AsFPDFWideString(&bsDefault), AsFPDFWideString(&bsLabel), bPassword,
218       response.data(), pdfium::base::checked_cast<int>(response.size()));
219 }
220 
JS_appBeep(int nType)221 void CPDFSDK_FormFillEnvironment::JS_appBeep(int nType) {
222   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
223   if (!js_platform || !js_platform->app_beep)
224     return;
225 
226   js_platform->app_beep(js_platform, nType);
227 }
228 
JS_fieldBrowse()229 WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
230   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
231   if (!js_platform || !js_platform->Field_browse)
232     return WideString();
233 
234   const int nRequiredLen = js_platform->Field_browse(js_platform, nullptr, 0);
235   if (nRequiredLen <= 0)
236     return WideString();
237 
238   DataVector<uint8_t> pBuff(nRequiredLen);
239   const int nActualLen =
240       js_platform->Field_browse(js_platform, pBuff.data(), nRequiredLen);
241   if (nActualLen <= 0 || nActualLen > nRequiredLen)
242     return WideString();
243 
244   // Don't include trailing NUL.
245   pBuff.resize(nActualLen - 1);
246 
247   // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
248   return WideString::FromDefANSI(ByteStringView(pBuff));
249 }
250 
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)251 void CPDFSDK_FormFillEnvironment::JS_docmailForm(
252     pdfium::span<const uint8_t> mailData,
253     FPDF_BOOL bUI,
254     const WideString& To,
255     const WideString& Subject,
256     const WideString& CC,
257     const WideString& BCC,
258     const WideString& Msg) {
259   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
260   if (!js_platform || !js_platform->Doc_mail)
261     return;
262 
263   ByteString bsTo = To.ToUTF16LE();
264   ByteString bsSubject = Subject.ToUTF16LE();
265   ByteString bsCC = CC.ToUTF16LE();
266   ByteString bsBcc = BCC.ToUTF16LE();
267   ByteString bsMsg = Msg.ToUTF16LE();
268   js_platform->Doc_mail(js_platform, const_cast<uint8_t*>(mailData.data()),
269                         pdfium::base::checked_cast<int>(mailData.size()), bUI,
270                         AsFPDFWideString(&bsTo), AsFPDFWideString(&bsSubject),
271                         AsFPDFWideString(&bsCC), AsFPDFWideString(&bsBcc),
272                         AsFPDFWideString(&bsMsg));
273 }
274 
JS_docprint(FPDF_BOOL bUI,int nStart,int nEnd,FPDF_BOOL bSilent,FPDF_BOOL bShrinkToFit,FPDF_BOOL bPrintAsImage,FPDF_BOOL bReverse,FPDF_BOOL bAnnotations)275 void CPDFSDK_FormFillEnvironment::JS_docprint(FPDF_BOOL bUI,
276                                               int nStart,
277                                               int nEnd,
278                                               FPDF_BOOL bSilent,
279                                               FPDF_BOOL bShrinkToFit,
280                                               FPDF_BOOL bPrintAsImage,
281                                               FPDF_BOOL bReverse,
282                                               FPDF_BOOL bAnnotations) {
283   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
284   if (!js_platform || !js_platform->Doc_print)
285     return;
286 
287   js_platform->Doc_print(js_platform, bUI, nStart, nEnd, bSilent, bShrinkToFit,
288                          bPrintAsImage, bReverse, bAnnotations);
289 }
290 
JS_docgotoPage(int nPageNum)291 void CPDFSDK_FormFillEnvironment::JS_docgotoPage(int nPageNum) {
292   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
293   if (!js_platform || !js_platform->Doc_gotoPage)
294     return;
295 
296   js_platform->Doc_gotoPage(js_platform, nPageNum);
297 }
298 
JS_docGetFilePath()299 WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() {
300   return GetFilePath();
301 }
302 #endif  // PDF_ENABLE_V8
303 
GetFilePath() const304 WideString CPDFSDK_FormFillEnvironment::GetFilePath() const {
305   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
306   if (!js_platform || !js_platform->Doc_getFilePath)
307     return WideString();
308 
309   const int nRequiredLen =
310       js_platform->Doc_getFilePath(js_platform, nullptr, 0);
311   if (nRequiredLen <= 0)
312     return WideString();
313 
314   DataVector<uint8_t> pBuff(nRequiredLen);
315   const int nActualLen =
316       js_platform->Doc_getFilePath(js_platform, pBuff.data(), nRequiredLen);
317   if (nActualLen <= 0 || nActualLen > nRequiredLen)
318     return WideString();
319 
320   // Don't include trailing NUL.
321   pBuff.resize(nActualLen - 1);
322 
323   // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
324   return WideString::FromDefANSI(ByteStringView(pBuff));
325 }
326 
SubmitForm(pdfium::span<const uint8_t> form_data,const WideString & URL)327 void CPDFSDK_FormFillEnvironment::SubmitForm(
328     pdfium::span<const uint8_t> form_data,
329     const WideString& URL) {
330   IPDF_JSPLATFORM* js_platform = GetJSPlatform();
331   if (!js_platform || !js_platform->Doc_submitForm)
332     return;
333 
334   ByteString bsUrl = URL.ToUTF16LE();
335   js_platform->Doc_submitForm(
336       js_platform, const_cast<uint8_t*>(form_data.data()),
337       fxcrt::CollectionSize<int>(form_data), AsFPDFWideString(&bsUrl));
338 }
339 
GetIJSRuntime()340 IJS_Runtime* CPDFSDK_FormFillEnvironment::GetIJSRuntime() {
341   if (!m_pIJSRuntime)
342     m_pIJSRuntime = IJS_Runtime::Create(this);
343   return m_pIJSRuntime.get();
344 }
345 
Invalidate(IPDF_Page * page,const FX_RECT & rect)346 void CPDFSDK_FormFillEnvironment::Invalidate(IPDF_Page* page,
347                                              const FX_RECT& rect) {
348   if (m_pInfo && m_pInfo->FFI_Invalidate) {
349     m_pInfo->FFI_Invalidate(m_pInfo, FPDFPageFromIPDFPage(page), rect.left,
350                             rect.top, rect.right, rect.bottom);
351   }
352 }
353 
SetCursor(IPWL_FillerNotify::CursorStyle nCursorType)354 void CPDFSDK_FormFillEnvironment::SetCursor(
355     IPWL_FillerNotify::CursorStyle nCursorType) {
356   if (m_pInfo && m_pInfo->FFI_SetCursor)
357     m_pInfo->FFI_SetCursor(m_pInfo, static_cast<int>(nCursorType));
358 }
359 
SetTimer(int uElapse,TimerCallback lpTimerFunc)360 int CPDFSDK_FormFillEnvironment::SetTimer(int uElapse,
361                                           TimerCallback lpTimerFunc) {
362   if (m_pInfo && m_pInfo->FFI_SetTimer)
363     return m_pInfo->FFI_SetTimer(m_pInfo, uElapse, lpTimerFunc);
364   return CFX_Timer::HandlerIface::kInvalidTimerID;
365 }
366 
KillTimer(int nTimerID)367 void CPDFSDK_FormFillEnvironment::KillTimer(int nTimerID) {
368   if (m_pInfo && m_pInfo->FFI_KillTimer)
369     m_pInfo->FFI_KillTimer(m_pInfo, nTimerID);
370 }
371 
OnChange()372 void CPDFSDK_FormFillEnvironment::OnChange() {
373   if (m_pInfo && m_pInfo->FFI_OnChange)
374     m_pInfo->FFI_OnChange(m_pInfo);
375 }
376 
ExecuteNamedAction(const ByteString & namedAction)377 void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(
378     const ByteString& namedAction) {
379   if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
380     m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction.c_str());
381 }
382 
OnSetFieldInputFocus(const WideString & text)383 void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocus(const WideString& text) {
384   OnSetFieldInputFocusInternal(text, true);
385 }
386 
OnSetFieldInputFocusInternal(const WideString & text,bool bFocus)387 void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocusInternal(
388     const WideString& text,
389     bool bFocus) {
390   if (m_pInfo && m_pInfo->FFI_SetTextFieldFocus) {
391     size_t nCharacters = text.GetLength();
392     ByteString bsUTFText = text.ToUTF16LE();
393     auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
394     m_pInfo->FFI_SetTextFieldFocus(
395         m_pInfo, pBuffer, pdfium::base::checked_cast<FPDF_DWORD>(nCharacters),
396         bFocus);
397   }
398 }
399 
OnCalculate(ObservedPtr<CPDFSDK_Annot> & pAnnot)400 void CPDFSDK_FormFillEnvironment::OnCalculate(
401     ObservedPtr<CPDFSDK_Annot>& pAnnot) {
402   CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot.Get());
403   if (pWidget)
404     m_pInteractiveForm->OnCalculate(pWidget->GetFormField());
405 }
406 
OnFormat(ObservedPtr<CPDFSDK_Annot> & pAnnot)407 void CPDFSDK_FormFillEnvironment::OnFormat(ObservedPtr<CPDFSDK_Annot>& pAnnot) {
408   CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot.Get());
409   DCHECK(pWidget);
410 
411   absl::optional<WideString> sValue =
412       m_pInteractiveForm->OnFormat(pWidget->GetFormField());
413   if (!pAnnot)
414     return;
415 
416   if (sValue.has_value()) {
417     m_pInteractiveForm->ResetFieldAppearance(pWidget->GetFormField(), sValue);
418     m_pInteractiveForm->UpdateField(pWidget->GetFormField());
419   }
420 }
421 
DoURIAction(const ByteString & bsURI,Mask<FWL_EVENTFLAG> modifiers)422 void CPDFSDK_FormFillEnvironment::DoURIAction(const ByteString& bsURI,
423                                               Mask<FWL_EVENTFLAG> modifiers) {
424   if (!m_pInfo)
425     return;
426 
427   if (m_pInfo->version >= 2 && m_pInfo->FFI_DoURIActionWithKeyboardModifier) {
428     m_pInfo->FFI_DoURIActionWithKeyboardModifier(m_pInfo, bsURI.c_str(),
429                                                  modifiers.UncheckedValue());
430     return;
431   }
432 
433   if (m_pInfo->FFI_DoURIAction)
434     m_pInfo->FFI_DoURIAction(m_pInfo, bsURI.c_str());
435 }
436 
DoGoToAction(int nPageIndex,int zoomMode,pdfium::span<float> fPosArray)437 void CPDFSDK_FormFillEnvironment::DoGoToAction(int nPageIndex,
438                                                int zoomMode,
439                                                pdfium::span<float> fPosArray) {
440   if (m_pInfo && m_pInfo->FFI_DoGoToAction) {
441     m_pInfo->FFI_DoGoToAction(m_pInfo, nPageIndex, zoomMode, fPosArray.data(),
442                               fxcrt::CollectionSize<int>(fPosArray));
443   }
444 }
445 
446 #ifdef PDF_ENABLE_XFA
GetPageViewCount() const447 int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
448   return fxcrt::CollectionSize<int>(m_PageMap);
449 }
450 
DisplayCaret(IPDF_Page * page,FPDF_BOOL bVisible,double left,double top,double right,double bottom)451 void CPDFSDK_FormFillEnvironment::DisplayCaret(IPDF_Page* page,
452                                                FPDF_BOOL bVisible,
453                                                double left,
454                                                double top,
455                                                double right,
456                                                double bottom) {
457   if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_DisplayCaret) {
458     m_pInfo->FFI_DisplayCaret(m_pInfo, FPDFPageFromIPDFPage(page), bVisible,
459                               left, top, right, bottom);
460   }
461 }
462 
GetCurrentPageIndex() const463 int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex() const {
464   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetCurrentPageIndex)
465     return -1;
466   return m_pInfo->FFI_GetCurrentPageIndex(
467       m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc));
468 }
469 
SetCurrentPage(int iCurPage)470 void CPDFSDK_FormFillEnvironment::SetCurrentPage(int iCurPage) {
471   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_SetCurrentPage)
472     return;
473   m_pInfo->FFI_SetCurrentPage(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc),
474                               iCurPage);
475 }
476 
GotoURL(const WideString & wsURL)477 void CPDFSDK_FormFillEnvironment::GotoURL(const WideString& wsURL) {
478   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GotoURL)
479     return;
480 
481   ByteString bsTo = wsURL.ToUTF16LE();
482   m_pInfo->FFI_GotoURL(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc),
483                        AsFPDFWideString(&bsTo));
484 }
485 
GetPageViewRect(IPDF_Page * page)486 FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(IPDF_Page* page) {
487   FS_RECTF rect = {0.0f, 0.0f, 0.0f, 0.0f};
488   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPageViewRect)
489     return rect;
490 
491   double left;
492   double top;
493   double right;
494   double bottom;
495   m_pInfo->FFI_GetPageViewRect(m_pInfo, FPDFPageFromIPDFPage(page), &left, &top,
496                                &right, &bottom);
497 
498   rect.left = static_cast<float>(left);
499   rect.top = static_cast<float>(top);
500   rect.bottom = static_cast<float>(bottom);
501   rect.right = static_cast<float>(right);
502   return rect;
503 }
504 
PopupMenu(IPDF_Page * page,int menuFlag,const CFX_PointF & pt)505 bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page,
506                                             int menuFlag,
507                                             const CFX_PointF& pt) {
508   return m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PopupMenu &&
509          m_pInfo->FFI_PopupMenu(m_pInfo, FPDFPageFromIPDFPage(page), nullptr,
510                                 menuFlag, pt.x, pt.y);
511 }
512 
EmailTo(FPDF_FILEHANDLER * fileHandler,FPDF_WIDESTRING pTo,FPDF_WIDESTRING pSubject,FPDF_WIDESTRING pCC,FPDF_WIDESTRING pBcc,FPDF_WIDESTRING pMsg)513 void CPDFSDK_FormFillEnvironment::EmailTo(FPDF_FILEHANDLER* fileHandler,
514                                           FPDF_WIDESTRING pTo,
515                                           FPDF_WIDESTRING pSubject,
516                                           FPDF_WIDESTRING pCC,
517                                           FPDF_WIDESTRING pBcc,
518                                           FPDF_WIDESTRING pMsg) {
519   if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_EmailTo)
520     m_pInfo->FFI_EmailTo(m_pInfo, fileHandler, pTo, pSubject, pCC, pBcc, pMsg);
521 }
522 
UploadTo(FPDF_FILEHANDLER * fileHandler,int fileFlag,FPDF_WIDESTRING uploadTo)523 void CPDFSDK_FormFillEnvironment::UploadTo(FPDF_FILEHANDLER* fileHandler,
524                                            int fileFlag,
525                                            FPDF_WIDESTRING uploadTo) {
526   if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_UploadTo)
527     m_pInfo->FFI_UploadTo(m_pInfo, fileHandler, fileFlag, uploadTo);
528 }
529 
OpenFile(int fileType,FPDF_WIDESTRING wsURL,const char * mode)530 FPDF_FILEHANDLER* CPDFSDK_FormFillEnvironment::OpenFile(int fileType,
531                                                         FPDF_WIDESTRING wsURL,
532                                                         const char* mode) {
533   if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_OpenFile)
534     return m_pInfo->FFI_OpenFile(m_pInfo, fileType, wsURL, mode);
535   return nullptr;
536 }
537 
DownloadFromURL(const WideString & url)538 RetainPtr<IFX_SeekableReadStream> CPDFSDK_FormFillEnvironment::DownloadFromURL(
539     const WideString& url) {
540   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_DownloadFromURL)
541     return nullptr;
542 
543   ByteString bstrURL = url.ToUTF16LE();
544   FPDF_FILEHANDLER* fileHandler =
545       m_pInfo->FFI_DownloadFromURL(m_pInfo, AsFPDFWideString(&bstrURL));
546 
547   return MakeSeekableStream(fileHandler);
548 }
549 
PostRequestURL(const WideString & wsURL,const WideString & wsData,const WideString & wsContentType,const WideString & wsEncode,const WideString & wsHeader)550 WideString CPDFSDK_FormFillEnvironment::PostRequestURL(
551     const WideString& wsURL,
552     const WideString& wsData,
553     const WideString& wsContentType,
554     const WideString& wsEncode,
555     const WideString& wsHeader) {
556   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PostRequestURL)
557     return WideString();
558 
559   ByteString bsURL = wsURL.ToUTF16LE();
560   ByteString bsData = wsData.ToUTF16LE();
561   ByteString bsContentType = wsContentType.ToUTF16LE();
562   ByteString bsEncode = wsEncode.ToUTF16LE();
563   ByteString bsHeader = wsHeader.ToUTF16LE();
564 
565   FPDF_BSTR response;
566   FPDF_BStr_Init(&response);
567   m_pInfo->FFI_PostRequestURL(
568       m_pInfo, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData),
569       AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode),
570       AsFPDFWideString(&bsHeader), &response);
571 
572   WideString wsRet =
573       WideString::FromUTF16LE(reinterpret_cast<FPDF_WIDESTRING>(response.str),
574                               response.len / sizeof(FPDF_WCHAR));
575 
576   FPDF_BStr_Clear(&response);
577   return wsRet;
578 }
579 
PutRequestURL(const WideString & wsURL,const WideString & wsData,const WideString & wsEncode)580 FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(
581     const WideString& wsURL,
582     const WideString& wsData,
583     const WideString& wsEncode) {
584   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PutRequestURL)
585     return false;
586 
587   ByteString bsURL = wsURL.ToUTF16LE();
588   ByteString bsData = wsData.ToUTF16LE();
589   ByteString bsEncode = wsEncode.ToUTF16LE();
590 
591   return m_pInfo->FFI_PutRequestURL(m_pInfo, AsFPDFWideString(&bsURL),
592                                     AsFPDFWideString(&bsData),
593                                     AsFPDFWideString(&bsEncode));
594 }
595 
PageEvent(int iPageCount,uint32_t dwEventType) const596 void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount,
597                                             uint32_t dwEventType) const {
598   if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PageEvent)
599     m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType);
600 }
601 #endif  // PDF_ENABLE_XFA
602 
ClearAllFocusedAnnots()603 void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() {
604   for (auto& it : m_PageMap) {
605     if (it.second->IsValidSDKAnnot(GetFocusAnnot())) {
606       ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
607       KillFocusAnnot({});
608       if (!pObserved)
609         break;
610     }
611   }
612 }
613 
GetOrCreatePageView(IPDF_Page * pUnderlyingPage)614 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetOrCreatePageView(
615     IPDF_Page* pUnderlyingPage) {
616   CPDFSDK_PageView* pExisting = GetPageView(pUnderlyingPage);
617   if (pExisting)
618     return pExisting;
619 
620   auto pNew = std::make_unique<CPDFSDK_PageView>(this, pUnderlyingPage);
621   CPDFSDK_PageView* pPageView = pNew.get();
622   m_PageMap[pUnderlyingPage] = std::move(pNew);
623 
624   // Delay to load all the annotations, to avoid endless loop.
625   pPageView->LoadFXAnnots();
626   return pPageView;
627 }
628 
GetPageView(IPDF_Page * pUnderlyingPage)629 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(
630     IPDF_Page* pUnderlyingPage) {
631   auto it = m_PageMap.find(pUnderlyingPage);
632   return it != m_PageMap.end() ? it->second.get() : nullptr;
633 }
634 
GetTimerHandler()635 CFX_Timer::HandlerIface* CPDFSDK_FormFillEnvironment::GetTimerHandler() {
636   return this;
637 }
638 
GetPageViewAtIndex(int nIndex)639 CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageViewAtIndex(int nIndex) {
640   IPDF_Page* pTempPage = GetPage(nIndex);
641   return pTempPage ? GetPageView(pTempPage) : nullptr;
642 }
643 
ProcJavascriptAction()644 void CPDFSDK_FormFillEnvironment::ProcJavascriptAction() {
645   auto name_tree = CPDF_NameTree::Create(m_pCPDFDoc, "JavaScript");
646   if (!name_tree)
647     return;
648 
649   size_t count = name_tree->GetCount();
650   for (size_t i = 0; i < count; ++i) {
651     WideString name;
652     CPDF_Action action(ToDictionary(name_tree->LookupValueAndName(i, &name)));
653     DoActionJavaScript(action, name);
654   }
655 }
656 
ProcOpenAction()657 bool CPDFSDK_FormFillEnvironment::ProcOpenAction() {
658   const CPDF_Dictionary* pRoot = m_pCPDFDoc->GetRoot();
659   if (!pRoot)
660     return false;
661 
662   RetainPtr<const CPDF_Object> pOpenAction(pRoot->GetDictFor("OpenAction"));
663   if (!pOpenAction)
664     pOpenAction = pRoot->GetArrayFor("OpenAction");
665   if (!pOpenAction)
666     return false;
667 
668   if (pOpenAction->IsArray())
669     return true;
670 
671   RetainPtr<const CPDF_Dictionary> pDict = ToDictionary(pOpenAction);
672   if (!pDict)
673     return false;
674 
675   DoActionDocOpen(CPDF_Action(std::move(pDict)));
676   return true;
677 }
678 
RemovePageView(IPDF_Page * pUnderlyingPage)679 void CPDFSDK_FormFillEnvironment::RemovePageView(IPDF_Page* pUnderlyingPage) {
680   auto it = m_PageMap.find(pUnderlyingPage);
681   if (it == m_PageMap.end())
682     return;
683 
684   CPDFSDK_PageView* pPageView = it->second.get();
685   if (pPageView->IsLocked() || pPageView->IsBeingDestroyed())
686     return;
687 
688   // Mark the page view so we do not come into |RemovePageView| a second
689   // time while we're in the process of removing.
690   pPageView->SetBeingDestroyed();
691 
692   // This must happen before we remove |pPageView| from the map because
693   // |KillFocusAnnot| can call into the |GetPage| method which will
694   // look for this page view in the map, if it doesn't find it a new one will
695   // be created. We then have two page views pointing to the same page and
696   // bad things happen.
697   if (pPageView->IsValidSDKAnnot(GetFocusAnnot()))
698     KillFocusAnnot({});
699 
700   // Remove the page from the map to make sure we don't accidentally attempt
701   // to use the |pPageView| while we're cleaning it up.
702   m_PageMap.erase(it);
703 }
704 
GetPage(int nIndex) const705 IPDF_Page* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) const {
706   if (!m_pInfo || !m_pInfo->FFI_GetPage)
707     return nullptr;
708   return IPDFPageFromFPDFPage(m_pInfo->FFI_GetPage(
709       m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), nIndex));
710 }
711 
GetInteractiveForm()712 CPDFSDK_InteractiveForm* CPDFSDK_FormFillEnvironment::GetInteractiveForm() {
713   if (!m_pInteractiveForm)
714     m_pInteractiveForm = std::make_unique<CPDFSDK_InteractiveForm>(this);
715   return m_pInteractiveForm.get();
716 }
717 
UpdateAllViews(CPDFSDK_Annot * pAnnot)718 void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_Annot* pAnnot) {
719   for (const auto& it : m_PageMap) {
720     ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
721     if (pObserved) {
722       pObserved->UpdateView(pAnnot);
723       if (!pObserved)
724         break;
725     }
726   }
727 }
728 
GetFocusAnnot() const729 CPDFSDK_Annot* CPDFSDK_FormFillEnvironment::GetFocusAnnot() const {
730   return m_pFocusAnnot.Get();
731 }
732 
SetFocusAnnot(ObservedPtr<CPDFSDK_Annot> & pAnnot)733 bool CPDFSDK_FormFillEnvironment::SetFocusAnnot(
734     ObservedPtr<CPDFSDK_Annot>& pAnnot) {
735   if (m_bBeingDestroyed)
736     return false;
737   if (m_pFocusAnnot == pAnnot)
738     return true;
739   if (m_pFocusAnnot && !KillFocusAnnot({}))
740     return false;
741   if (!pAnnot)
742     return false;
743   if (!pAnnot->GetPageView()->IsValid())
744     return false;
745 
746   if (m_pFocusAnnot)
747     return false;
748 
749 #ifdef PDF_ENABLE_XFA
750   CPDFXFA_Widget* pXFAWidget = pAnnot->AsXFAWidget();
751   if (pXFAWidget && pXFAWidget->OnChangedFocus())
752     return false;
753 
754   // `pAnnot` may be destroyed in `OnChangedFocus()`.
755   if (!pAnnot)
756     return false;
757 #endif  // PDF_ENABLE_XFA
758 
759   if (!CPDFSDK_Annot::OnSetFocus(pAnnot, {}))
760     return false;
761   if (m_pFocusAnnot)
762     return false;
763 
764   m_pFocusAnnot.Reset(pAnnot.Get());
765 
766   // If we are not able to inform the client about the focus change, it
767   // shouldn't be considered as failure.
768   SendOnFocusChange(pAnnot);
769   return true;
770 }
771 
KillFocusAnnot(Mask<FWL_EVENTFLAG> nFlags)772 bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(Mask<FWL_EVENTFLAG> nFlags) {
773   if (!m_pFocusAnnot)
774     return false;
775 
776   ObservedPtr<CPDFSDK_Annot> pFocusAnnot(m_pFocusAnnot.Get());
777   m_pFocusAnnot.Reset();
778 
779   if (!CPDFSDK_Annot::OnKillFocus(pFocusAnnot, nFlags)) {
780     m_pFocusAnnot.Reset(pFocusAnnot.Get());
781     return false;
782   }
783 
784   // Might have been destroyed by OnKillFocus().
785   if (!pFocusAnnot)
786     return false;
787 
788   if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
789     CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pFocusAnnot.Get());
790     FormFieldType fieldType = pWidget->GetFieldType();
791     if (fieldType == FormFieldType::kTextField ||
792         fieldType == FormFieldType::kComboBox) {
793       OnSetFieldInputFocusInternal(WideString(), false);
794     }
795   }
796   return !m_pFocusAnnot;
797 }
798 
GetPageCount() const799 int CPDFSDK_FormFillEnvironment::GetPageCount() const {
800   CPDF_Document::Extension* pExtension = m_pCPDFDoc->GetExtension();
801   return pExtension ? pExtension->GetPageCount() : m_pCPDFDoc->GetPageCount();
802 }
803 
HasPermissions(uint32_t flags) const804 bool CPDFSDK_FormFillEnvironment::HasPermissions(uint32_t flags) const {
805   return !!(m_pCPDFDoc->GetUserPermissions() & flags);
806 }
807 
SendOnFocusChange(ObservedPtr<CPDFSDK_Annot> & pAnnot)808 void CPDFSDK_FormFillEnvironment::SendOnFocusChange(
809     ObservedPtr<CPDFSDK_Annot>& pAnnot) {
810   if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_OnFocusChange)
811     return;
812 
813   // TODO(crbug.com/pdfium/1482): Handle XFA case.
814   if (pAnnot->AsXFAWidget())
815     return;
816 
817   CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
818   if (!pPageView->IsValid())
819     return;
820 
821   IPDF_Page* page = pAnnot->GetPage();
822   if (!page)
823     return;
824 
825   RetainPtr<CPDF_Dictionary> annot_dict =
826       pAnnot->GetPDFAnnot()->GetMutableAnnotDict();
827   auto focused_annot = std::make_unique<CPDF_AnnotContext>(annot_dict, page);
828   FPDF_ANNOTATION fpdf_annot =
829       FPDFAnnotationFromCPDFAnnotContext(focused_annot.get());
830 
831   m_pInfo->FFI_OnFocusChange(m_pInfo, fpdf_annot, pPageView->GetPageIndex());
832 }
833 
DoActionDocOpen(const CPDF_Action & action)834 bool CPDFSDK_FormFillEnvironment::DoActionDocOpen(const CPDF_Action& action) {
835   std::set<const CPDF_Dictionary*> visited;
836   return ExecuteDocumentOpenAction(action, &visited);
837 }
838 
DoActionJavaScript(const CPDF_Action & JsAction,WideString csJSName)839 bool CPDFSDK_FormFillEnvironment::DoActionJavaScript(
840     const CPDF_Action& JsAction,
841     WideString csJSName) {
842   if (JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
843     WideString swJS = JsAction.GetJavaScript();
844     if (!swJS.IsEmpty()) {
845       RunDocumentOpenJavaScript(csJSName, swJS);
846       return true;
847     }
848   }
849 
850   return false;
851 }
852 
DoActionFieldJavaScript(const CPDF_Action & JsAction,CPDF_AAction::AActionType type,CPDF_FormField * pFormField,CFFL_FieldAction * data)853 bool CPDFSDK_FormFillEnvironment::DoActionFieldJavaScript(
854     const CPDF_Action& JsAction,
855     CPDF_AAction::AActionType type,
856     CPDF_FormField* pFormField,
857     CFFL_FieldAction* data) {
858   if (IsJSPlatformPresent() &&
859       JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
860     WideString swJS = JsAction.GetJavaScript();
861     if (!swJS.IsEmpty()) {
862       RunFieldJavaScript(pFormField, type, data, swJS);
863       return true;
864     }
865   }
866   return false;
867 }
868 
DoActionLink(const CPDF_Action & action,CPDF_AAction::AActionType type,Mask<FWL_EVENTFLAG> modifiers)869 bool CPDFSDK_FormFillEnvironment::DoActionLink(const CPDF_Action& action,
870                                                CPDF_AAction::AActionType type,
871                                                Mask<FWL_EVENTFLAG> modifiers) {
872   if (!CPDF_AAction::IsUserInput(type))
873     return false;
874 
875   switch (action.GetType()) {
876     case CPDF_Action::Type::kGoTo:
877       DoActionGoTo(action);
878       return true;
879     case CPDF_Action::Type::kURI:
880       DoActionURI(action, modifiers);
881       return true;
882     default:
883       return false;
884   }
885 }
886 
DoActionDestination(const CPDF_Dest & dest)887 bool CPDFSDK_FormFillEnvironment::DoActionDestination(const CPDF_Dest& dest) {
888   CPDF_Document* document = GetPDFDocument();
889   DCHECK(document);
890 
891   std::vector<float> positions = dest.GetScrollPositionArray();
892   DoGoToAction(dest.GetDestPageIndex(document), dest.GetZoomMode(), positions);
893   return true;
894 }
895 
DoActionPage(const CPDF_Action & action,CPDF_AAction::AActionType eType)896 bool CPDFSDK_FormFillEnvironment::DoActionPage(
897     const CPDF_Action& action,
898     CPDF_AAction::AActionType eType) {
899   std::set<const CPDF_Dictionary*> visited;
900   return ExecuteDocumentPageAction(action, eType, &visited);
901 }
902 
DoActionDocument(const CPDF_Action & action,CPDF_AAction::AActionType eType)903 bool CPDFSDK_FormFillEnvironment::DoActionDocument(
904     const CPDF_Action& action,
905     CPDF_AAction::AActionType eType) {
906   std::set<const CPDF_Dictionary*> visited;
907   return ExecuteDocumentPageAction(action, eType, &visited);
908 }
909 
DoActionField(const CPDF_Action & action,CPDF_AAction::AActionType type,CPDF_FormField * pFormField,CFFL_FieldAction * data)910 bool CPDFSDK_FormFillEnvironment::DoActionField(const CPDF_Action& action,
911                                                 CPDF_AAction::AActionType type,
912                                                 CPDF_FormField* pFormField,
913                                                 CFFL_FieldAction* data) {
914   std::set<const CPDF_Dictionary*> visited;
915   return ExecuteFieldAction(action, type, pFormField, data, &visited);
916 }
917 
ExecuteDocumentOpenAction(const CPDF_Action & action,std::set<const CPDF_Dictionary * > * visited)918 bool CPDFSDK_FormFillEnvironment::ExecuteDocumentOpenAction(
919     const CPDF_Action& action,
920     std::set<const CPDF_Dictionary*>* visited) {
921   const CPDF_Dictionary* pDict = action.GetDict();
922   if (pdfium::Contains(*visited, pDict))
923     return false;
924 
925   visited->insert(pDict);
926 
927   if (action.GetType() == CPDF_Action::Type::kJavaScript) {
928     if (IsJSPlatformPresent()) {
929       WideString swJS = action.GetJavaScript();
930       if (!swJS.IsEmpty())
931         RunDocumentOpenJavaScript(WideString(), swJS);
932     }
933   } else {
934     DoActionNoJs(action, CPDF_AAction::AActionType::kDocumentOpen);
935   }
936 
937   for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
938     CPDF_Action subaction = action.GetSubAction(i);
939     if (!ExecuteDocumentOpenAction(subaction, visited))
940       return false;
941   }
942 
943   return true;
944 }
945 
ExecuteDocumentPageAction(const CPDF_Action & action,CPDF_AAction::AActionType type,std::set<const CPDF_Dictionary * > * visited)946 bool CPDFSDK_FormFillEnvironment::ExecuteDocumentPageAction(
947     const CPDF_Action& action,
948     CPDF_AAction::AActionType type,
949     std::set<const CPDF_Dictionary*>* visited) {
950   const CPDF_Dictionary* pDict = action.GetDict();
951   if (pdfium::Contains(*visited, pDict))
952     return false;
953 
954   visited->insert(pDict);
955 
956   if (action.GetType() == CPDF_Action::Type::kJavaScript) {
957     if (IsJSPlatformPresent()) {
958       WideString swJS = action.GetJavaScript();
959       if (!swJS.IsEmpty())
960         RunDocumentPageJavaScript(type, swJS);
961     }
962   } else {
963     DoActionNoJs(action, type);
964   }
965 
966   for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
967     CPDF_Action subaction = action.GetSubAction(i);
968     if (!ExecuteDocumentPageAction(subaction, type, visited))
969       return false;
970   }
971 
972   return true;
973 }
974 
IsValidField(const CPDF_Dictionary * pFieldDict)975 bool CPDFSDK_FormFillEnvironment::IsValidField(
976     const CPDF_Dictionary* pFieldDict) {
977   DCHECK(pFieldDict);
978 
979   CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
980   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
981   return !!pPDFForm->GetFieldByDict(pFieldDict);
982 }
983 
ExecuteFieldAction(const CPDF_Action & action,CPDF_AAction::AActionType type,CPDF_FormField * pFormField,CFFL_FieldAction * data,std::set<const CPDF_Dictionary * > * visited)984 bool CPDFSDK_FormFillEnvironment::ExecuteFieldAction(
985     const CPDF_Action& action,
986     CPDF_AAction::AActionType type,
987     CPDF_FormField* pFormField,
988     CFFL_FieldAction* data,
989     std::set<const CPDF_Dictionary*>* visited) {
990   const CPDF_Dictionary* pDict = action.GetDict();
991   if (pdfium::Contains(*visited, pDict))
992     return false;
993 
994   visited->insert(pDict);
995 
996   if (action.GetType() == CPDF_Action::Type::kJavaScript) {
997     if (IsJSPlatformPresent()) {
998       WideString swJS = action.GetJavaScript();
999       if (!swJS.IsEmpty()) {
1000         RunFieldJavaScript(pFormField, type, data, swJS);
1001         if (!IsValidField(pFormField->GetFieldDict()))
1002           return false;
1003       }
1004     }
1005   } else {
1006     DoActionNoJs(action, type);
1007   }
1008 
1009   for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
1010     CPDF_Action subaction = action.GetSubAction(i);
1011     if (!ExecuteFieldAction(subaction, type, pFormField, data, visited))
1012       return false;
1013   }
1014 
1015   return true;
1016 }
1017 
DoActionNoJs(const CPDF_Action & action,CPDF_AAction::AActionType type)1018 void CPDFSDK_FormFillEnvironment::DoActionNoJs(const CPDF_Action& action,
1019                                                CPDF_AAction::AActionType type) {
1020   switch (action.GetType()) {
1021     case CPDF_Action::Type::kGoTo:
1022       DoActionGoTo(action);
1023       break;
1024     case CPDF_Action::Type::kURI:
1025       if (CPDF_AAction::IsUserInput(type))
1026         DoActionURI(action, Mask<FWL_EVENTFLAG>{});
1027       break;
1028     case CPDF_Action::Type::kHide:
1029       DoActionHide(action);
1030       break;
1031     case CPDF_Action::Type::kNamed:
1032       DoActionNamed(action);
1033       break;
1034     case CPDF_Action::Type::kSubmitForm:
1035       if (CPDF_AAction::IsUserInput(type))
1036         DoActionSubmitForm(action);
1037       break;
1038     case CPDF_Action::Type::kResetForm:
1039       DoActionResetForm(action);
1040       break;
1041     case CPDF_Action::Type::kJavaScript:
1042       NOTREACHED_NORETURN();
1043       break;
1044     case CPDF_Action::Type::kSetOCGState:
1045     case CPDF_Action::Type::kThread:
1046     case CPDF_Action::Type::kSound:
1047     case CPDF_Action::Type::kMovie:
1048     case CPDF_Action::Type::kRendition:
1049     case CPDF_Action::Type::kTrans:
1050     case CPDF_Action::Type::kGoTo3DView:
1051     case CPDF_Action::Type::kGoToR:
1052     case CPDF_Action::Type::kGoToE:
1053     case CPDF_Action::Type::kLaunch:
1054     case CPDF_Action::Type::kImportData:
1055       // Unimplemented
1056       break;
1057     default:
1058       break;
1059   }
1060 }
1061 
DoActionGoTo(const CPDF_Action & action)1062 void CPDFSDK_FormFillEnvironment::DoActionGoTo(const CPDF_Action& action) {
1063   DCHECK(action.GetDict());
1064 
1065   CPDF_Document* pPDFDocument = GetPDFDocument();
1066   DCHECK(pPDFDocument);
1067 
1068   CPDF_Dest MyDest = action.GetDest(pPDFDocument);
1069   DoActionDestination(MyDest);
1070 }
1071 
DoActionURI(const CPDF_Action & action,Mask<FWL_EVENTFLAG> modifiers)1072 void CPDFSDK_FormFillEnvironment::DoActionURI(const CPDF_Action& action,
1073                                               Mask<FWL_EVENTFLAG> modifiers) {
1074   DCHECK(action.GetDict());
1075   DoURIAction(action.GetURI(GetPDFDocument()), modifiers);
1076 }
1077 
DoActionNamed(const CPDF_Action & action)1078 void CPDFSDK_FormFillEnvironment::DoActionNamed(const CPDF_Action& action) {
1079   DCHECK(action.GetDict());
1080   ExecuteNamedAction(action.GetNamedAction());
1081 }
1082 
RunFieldJavaScript(CPDF_FormField * pFormField,CPDF_AAction::AActionType type,CFFL_FieldAction * data,const WideString & script)1083 void CPDFSDK_FormFillEnvironment::RunFieldJavaScript(
1084     CPDF_FormField* pFormField,
1085     CPDF_AAction::AActionType type,
1086     CFFL_FieldAction* data,
1087     const WideString& script) {
1088   DCHECK(type != CPDF_AAction::kCalculate);
1089   DCHECK(type != CPDF_AAction::kFormat);
1090 
1091   RunScript(script, [type, data, pFormField](IJS_EventContext* context) {
1092     switch (type) {
1093       case CPDF_AAction::kCursorEnter:
1094         context->OnField_MouseEnter(data->bModifier, data->bShift, pFormField);
1095         break;
1096       case CPDF_AAction::kCursorExit:
1097         context->OnField_MouseExit(data->bModifier, data->bShift, pFormField);
1098         break;
1099       case CPDF_AAction::kButtonDown:
1100         context->OnField_MouseDown(data->bModifier, data->bShift, pFormField);
1101         break;
1102       case CPDF_AAction::kButtonUp:
1103         context->OnField_MouseUp(data->bModifier, data->bShift, pFormField);
1104         break;
1105       case CPDF_AAction::kGetFocus:
1106         context->OnField_Focus(data->bModifier, data->bShift, pFormField,
1107                                &data->sValue);
1108         break;
1109       case CPDF_AAction::kLoseFocus:
1110         context->OnField_Blur(data->bModifier, data->bShift, pFormField,
1111                               &data->sValue);
1112         break;
1113       case CPDF_AAction::kKeyStroke:
1114         context->OnField_Keystroke(
1115             &data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier,
1116             &data->nSelEnd, &data->nSelStart, data->bShift, pFormField,
1117             &data->sValue, data->bWillCommit, data->bFieldFull, &data->bRC);
1118         break;
1119       case CPDF_AAction::kValidate:
1120         context->OnField_Validate(&data->sChange, data->sChangeEx,
1121                                   data->bKeyDown, data->bModifier, data->bShift,
1122                                   pFormField, &data->sValue, &data->bRC);
1123         break;
1124       default:
1125         NOTREACHED_NORETURN();
1126         break;
1127     }
1128   });
1129 }
1130 
RunDocumentOpenJavaScript(const WideString & sScriptName,const WideString & script)1131 void CPDFSDK_FormFillEnvironment::RunDocumentOpenJavaScript(
1132     const WideString& sScriptName,
1133     const WideString& script) {
1134   RunScript(script, [sScriptName](IJS_EventContext* context) {
1135     context->OnDoc_Open(sScriptName);
1136   });
1137 }
1138 
RunDocumentPageJavaScript(CPDF_AAction::AActionType type,const WideString & script)1139 void CPDFSDK_FormFillEnvironment::RunDocumentPageJavaScript(
1140     CPDF_AAction::AActionType type,
1141     const WideString& script) {
1142   RunScript(script, [type](IJS_EventContext* context) {
1143     switch (type) {
1144       case CPDF_AAction::kOpenPage:
1145         context->OnPage_Open();
1146         break;
1147       case CPDF_AAction::kClosePage:
1148         context->OnPage_Close();
1149         break;
1150       case CPDF_AAction::kCloseDocument:
1151         context->OnDoc_WillClose();
1152         break;
1153       case CPDF_AAction::kSaveDocument:
1154         context->OnDoc_WillSave();
1155         break;
1156       case CPDF_AAction::kDocumentSaved:
1157         context->OnDoc_DidSave();
1158         break;
1159       case CPDF_AAction::kPrintDocument:
1160         context->OnDoc_WillPrint();
1161         break;
1162       case CPDF_AAction::kDocumentPrinted:
1163         context->OnDoc_DidPrint();
1164         break;
1165       case CPDF_AAction::kPageVisible:
1166         context->OnPage_InView();
1167         break;
1168       case CPDF_AAction::kPageInvisible:
1169         context->OnPage_OutView();
1170         break;
1171       default:
1172         NOTREACHED_NORETURN();
1173         break;
1174     }
1175   });
1176 }
1177 
DoActionHide(const CPDF_Action & action)1178 bool CPDFSDK_FormFillEnvironment::DoActionHide(const CPDF_Action& action) {
1179   CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1180   if (pForm->DoAction_Hide(action)) {
1181     SetChangeMark();
1182     return true;
1183   }
1184   return false;
1185 }
1186 
DoActionSubmitForm(const CPDF_Action & action)1187 bool CPDFSDK_FormFillEnvironment::DoActionSubmitForm(
1188     const CPDF_Action& action) {
1189   CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1190   return pForm->DoAction_SubmitForm(action);
1191 }
1192 
DoActionResetForm(const CPDF_Action & action)1193 void CPDFSDK_FormFillEnvironment::DoActionResetForm(const CPDF_Action& action) {
1194   CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1195   pForm->DoAction_ResetForm(action);
1196 }
1197 
RunScript(const WideString & script,const RunScriptCallback & cb)1198 void CPDFSDK_FormFillEnvironment::RunScript(const WideString& script,
1199                                             const RunScriptCallback& cb) {
1200   IJS_Runtime::ScopedEventContext pContext(GetIJSRuntime());
1201   cb(pContext.Get());
1202   pContext->RunScript(script);
1203   // TODO(dsinclair): Return error if RunScript returns a IJS_Runtime::JS_Error.
1204 }
1205