blob: 9d6d56b25cfd933d59ce4c624788dbb6f82aae27 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2016 The PDFium Authors
dsinclairf34518b2016-09-13 12:03:48 -07002// 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
dsinclair735606d2016-10-05 15:47:02 -07007#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclairf34518b2016-09-13 12:03:48 -07008
Lei Zhang549bfb22022-08-11 19:45:29 +00009#include <stdint.h>
10
thestigd4c34f22016-09-28 17:04:51 -070011#include <memory>
Tom Sepezfe91c6c2017-05-16 15:33:20 -070012#include <utility>
Tom Sepezd04de262019-12-03 23:27:59 +000013#include <vector>
thestigd4c34f22016-09-28 17:04:51 -070014
Aayush Dhirc63913e2020-02-12 09:45:34 +000015#include "core/fpdfapi/page/cpdf_annotcontext.h"
dsinclair7cbe68e2016-10-12 11:56:23 -070016#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000017#include "core/fpdfapi/parser/cpdf_dictionary.h"
Tom Sepez20d08092020-01-29 21:27:44 +000018#include "core/fpdfdoc/cpdf_nametree.h"
Lei Zhang91085882024-02-22 00:49:57 +000019#include "core/fxcrt/check.h"
Lei Zhangf778d3c2024-02-16 20:44:14 +000020#include "core/fxcrt/containers/contains.h"
Lei Zhang549bfb22022-08-11 19:45:29 +000021#include "core/fxcrt/data_vector.h"
Lei Zhang91085882024-02-22 00:49:57 +000022#include "core/fxcrt/notreached.h"
Lei Zhangf36006c2024-02-17 00:56:24 +000023#include "core/fxcrt/numerics/safe_conversions.h"
Lei Zhang549fe5d2021-06-18 23:46:09 +000024#include "core/fxcrt/stl_util.h"
Tom Sepez8e94c182019-06-11 23:57:25 +000025#include "fpdfsdk/cpdfsdk_helpers.h"
Lei Zhangc3450652018-10-11 16:54:42 +000026#include "fpdfsdk/cpdfsdk_interactiveform.h"
dsinclair7cbe68e2016-10-12 11:56:23 -070027#include "fpdfsdk/cpdfsdk_pageview.h"
28#include "fpdfsdk/cpdfsdk_widget.h"
Tom Sepezfa408642021-05-27 21:46:51 +000029#include "fpdfsdk/formfiller/cffl_formfield.h"
dsinclairb94d7c92016-09-21 12:07:00 -070030#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
Tom Sepez946bf0f2022-04-08 22:06:41 +000031#include "fxjs/ijs_event_context.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000032#include "fxjs/ijs_runtime.h"
dsinclairf34518b2016-09-13 12:03:48 -070033
Lei Zhang822b6ea2022-04-05 03:40:40 +000034#ifdef PDF_ENABLE_XFA
35#include "fpdfsdk/fpdfxfa/cpdfxfa_widget.h"
36#endif
37
Tom Sepez230db1d2021-05-19 01:56:54 +000038static_assert(FXCT_ARROW ==
Tom Sepez02cb5702022-05-09 23:41:19 +000039 static_cast<int>(IPWL_FillerNotify::CursorStyle::kArrow),
Tom Sepez230db1d2021-05-19 01:56:54 +000040 "kArrow value mismatch");
41static_assert(FXCT_NESW ==
Tom Sepez02cb5702022-05-09 23:41:19 +000042 static_cast<int>(IPWL_FillerNotify::CursorStyle::kNESW),
Tom Sepez230db1d2021-05-19 01:56:54 +000043 "kNEWS value mismatch");
44static_assert(FXCT_NWSE ==
Tom Sepez02cb5702022-05-09 23:41:19 +000045 static_cast<int>(IPWL_FillerNotify::CursorStyle::kNWSE),
Tom Sepez230db1d2021-05-19 01:56:54 +000046 "kNWSE value mismatch");
47static_assert(FXCT_VBEAM ==
Tom Sepez02cb5702022-05-09 23:41:19 +000048 static_cast<int>(IPWL_FillerNotify::CursorStyle::kVBeam),
Tom Sepez230db1d2021-05-19 01:56:54 +000049 "kVBeam value mismatch");
50static_assert(FXCT_HBEAM ==
Tom Sepez02cb5702022-05-09 23:41:19 +000051 static_cast<int>(IPWL_FillerNotify::CursorStyle::kHBeam),
Tom Sepez230db1d2021-05-19 01:56:54 +000052 "HBeam value mismatch");
53static_assert(FXCT_HAND ==
Tom Sepez02cb5702022-05-09 23:41:19 +000054 static_cast<int>(IPWL_FillerNotify::CursorStyle::kHand),
Tom Sepez230db1d2021-05-19 01:56:54 +000055 "kHand value mismatch");
56
Ryan Harrison275e2602017-09-18 14:23:18 -040057FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) {
Tom Sepez1e934f62018-04-11 21:11:28 +000058 // 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|.
dsinclairf34518b2016-09-13 12:03:48 -070061 return reinterpret_cast<FPDF_WIDESTRING>(
Tom Sepez1dbfe992018-04-17 17:19:30 +000062 bsUTF16LE->GetBuffer(bsUTF16LE->GetLength()).data());
dsinclairf34518b2016-09-13 12:03:48 -070063}
64
dsinclair735606d2016-10-05 15:47:02 -070065CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment(
Tom Sepezda8063f2018-04-30 17:41:49 +000066 CPDF_Document* pDoc,
Lei Zhang20143282022-04-08 21:16:52 +000067 FPDF_FORMFILLINFO* pFFinfo)
Tom Sepez49357702019-08-19 17:17:18 +000068 : m_pInfo(pFFinfo),
69 m_pCPDFDoc(pDoc),
Tom Sepez50985a02021-09-13 18:25:19 +000070 m_pInteractiveFormFiller(
71 std::make_unique<CFFL_InteractiveFormFiller>(this)) {
Tom Sepez9c78c0d2021-01-27 20:13:14 +000072 DCHECK(m_pCPDFDoc);
Lei Zhangf97fd062019-08-09 22:18:39 +000073}
dsinclairf34518b2016-09-13 12:03:48 -070074
dsinclair735606d2016-10-05 15:47:02 -070075CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() {
dsinclair6c659ab2016-10-12 13:41:38 -070076 m_bBeingDestroyed = true;
dsinclair7cbe68e2016-10-12 11:56:23 -070077 ClearAllFocusedAnnots();
dsinclair7cbe68e2016-10-12 11:56:23 -070078
Lei Zhang073ecf42018-10-11 16:56:00 +000079 // |m_PageMap| will try to access |m_pInteractiveForm| when it cleans itself
80 // up. Make sure it is deleted before |m_pInteractiveForm|.
tsepez2599ff72016-11-08 14:38:59 -080081 m_PageMap.clear();
82
Tom Sepezb566cd92021-05-28 00:45:28 +000083 // Must destroy the |m_pInteractiveFormFiller| before the environment (|this|)
dsinclair709f5a92016-10-11 14:21:16 -070084 // because any created form widgets hold a pointer to the environment.
85 // Those widgets may call things like KillTimer() as they are shutdown.
Tom Sepezb566cd92021-05-28 00:45:28 +000086 m_pInteractiveFormFiller.reset();
dsinclair709f5a92016-10-11 14:21:16 -070087
dsinclairf34518b2016-09-13 12:03:48 -070088 if (m_pInfo && m_pInfo->Release)
89 m_pInfo->Release(m_pInfo);
90}
91
Tom Sepezec0e07b2022-05-14 00:14:18 +000092void CPDFSDK_FormFillEnvironment::InvalidateRect(CPDFSDK_Widget* widget,
93 const CFX_FloatRect& rect) {
Tom Sepez3c168bb2019-08-07 23:00:06 +000094 IPDF_Page* pPage = widget->GetPage();
Lei Zhangc2ad6282020-02-13 20:50:57 +000095 if (!pPage)
Tom Sepez3c168bb2019-08-07 23:00:06 +000096 return;
97
Lei Zhangc2ad6282020-02-13 20:50:57 +000098 CFX_Matrix device2page =
99 widget->GetPageView()->GetCurrentMatrix().GetInverse();
Tom Sepez3c168bb2019-08-07 23:00:06 +0000100 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
109void CPDFSDK_FormFillEnvironment::OutputSelectedRect(
Tom Sepezec0e07b2022-05-14 00:14:18 +0000110 CFFL_FormField* pFormField,
Tom Sepez3c168bb2019-08-07 23:00:06 +0000111 const CFX_FloatRect& rect) {
Tom Sepezf351aab2021-09-10 22:38:29 +0000112 if (!m_pInfo || !m_pInfo->FFI_OutputSelectedRect)
113 return;
114
Tom Sepeze6d88212021-09-22 19:52:28 +0000115 auto* pPage = FPDFPageFromIPDFPage(pFormField->GetSDKWidget()->GetPage());
Tom Sepez9c78c0d2021-01-27 20:13:14 +0000116 DCHECK(pPage);
Tom Sepez3c168bb2019-08-07 23:00:06 +0000117
Tom Sepezc8f89af2021-05-28 15:22:58 +0000118 CFX_PointF ptA = pFormField->PWLtoFFL(CFX_PointF(rect.left, rect.bottom));
119 CFX_PointF ptB = pFormField->PWLtoFFL(CFX_PointF(rect.right, rect.top));
Tom Sepez3c168bb2019-08-07 23:00:06 +0000120 m_pInfo->FFI_OutputSelectedRect(m_pInfo, pPage, ptA.x, ptB.y, ptB.x, ptA.y);
121}
122
123bool CPDFSDK_FormFillEnvironment::IsSelectionImplemented() const {
124 FPDF_FORMFILLINFO* pInfo = GetFormFillInfo();
125 return pInfo && pInfo->FFI_OutputSelectedRect;
126}
127
Tom Sepezeb98dac2018-11-07 20:04:03 +0000128#ifdef PDF_ENABLE_V8
Tom Sepezd48bd292019-08-14 19:48:55 +0000129CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
Tom Sepez4b718ca2022-08-09 20:22:30 +0000130 IPDF_Page* pPage = GetCurrentPage();
Tom Sepezcee8fbd2021-06-04 19:21:40 +0000131 return pPage ? GetOrCreatePageView(pPage) : nullptr;
Tom Sepezd48bd292019-08-14 19:48:55 +0000132}
133
Tom Sepez4b718ca2022-08-09 20:22:30 +0000134IPDF_Page* CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
Tom Sepezd48bd292019-08-14 19:48:55 +0000135 if (m_pInfo && m_pInfo->FFI_GetCurrentPage) {
Tom Sepez4b718ca2022-08-09 20:22:30 +0000136 return IPDFPageFromFPDFPage(m_pInfo->FFI_GetCurrentPage(
Tom Sepezc4acde52022-10-28 00:47:46 +0000137 m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc)));
Tom Sepezd48bd292019-08-14 19:48:55 +0000138 }
139 return nullptr;
140}
141
142WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
143#ifdef PDF_ENABLE_XFA
Tom Sepez197d0d82019-12-18 20:28:20 +0000144 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetLanguage)
Tom Sepezd48bd292019-08-14 19:48:55 +0000145 return WideString();
146
147 int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
148 if (nRequiredLen <= 0)
149 return WideString();
150
Lei Zhang549bfb22022-08-11 19:45:29 +0000151 DataVector<uint8_t> pBuff(nRequiredLen);
Tom Sepezd48bd292019-08-14 19:48:55 +0000152 int nActualLen =
153 m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
154 if (nActualLen <= 0 || nActualLen > nRequiredLen)
155 return WideString();
156
Nico Weber40d92c42023-11-29 03:25:30 +0000157 return WideString::FromUTF16LE(
Tom Sepez3b679fe2024-04-09 18:49:32 +0000158 pdfium::make_span(pBuff).first(static_cast<size_t>(nActualLen)));
Tom Sepezd48bd292019-08-14 19:48:55 +0000159#else // PDF_ENABLE_XFA
160 return WideString();
161#endif // PDF_ENABLE_XFA
162}
163
164WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
165#ifdef PDF_ENABLE_XFA
Tom Sepez197d0d82019-12-18 20:28:20 +0000166 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPlatform)
Tom Sepezd48bd292019-08-14 19:48:55 +0000167 return WideString();
168
169 int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
170 if (nRequiredLen <= 0)
171 return WideString();
172
Lei Zhang549bfb22022-08-11 19:45:29 +0000173 DataVector<uint8_t> pBuff(nRequiredLen);
Tom Sepezd48bd292019-08-14 19:48:55 +0000174 int nActualLen =
175 m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
176 if (nActualLen <= 0 || nActualLen > nRequiredLen)
177 return WideString();
178
Nico Weber40d92c42023-11-29 03:25:30 +0000179 return WideString::FromUTF16LE(
Tom Sepez3b679fe2024-04-09 18:49:32 +0000180 pdfium::make_span(pBuff).first(static_cast<size_t>(nActualLen)));
Tom Sepezd48bd292019-08-14 19:48:55 +0000181#else // PDF_ENABLE_XFA
182 return WideString();
183#endif // PDF_ENABLE_XFA
184}
185
Tom Sepez35939f82018-04-17 21:23:58 +0000186int CPDFSDK_FormFillEnvironment::JS_appAlert(const WideString& Msg,
187 const WideString& Title,
Ryan Harrisonc3cc2ab2018-06-21 21:09:54 +0000188 int Type,
189 int Icon) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000190 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
191 if (!js_platform || !js_platform->app_alert)
dsinclairf34518b2016-09-13 12:03:48 -0700192 return -1;
Ryan Harrisonc3cc2ab2018-06-21 21:09:54 +0000193
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000194 ByteString bsMsg = Msg.ToUTF16LE();
195 ByteString bsTitle = Title.ToUTF16LE();
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000196 return js_platform->app_alert(js_platform, AsFPDFWideString(&bsMsg),
197 AsFPDFWideString(&bsTitle), Type, Icon);
dsinclairf34518b2016-09-13 12:03:48 -0700198}
199
Tom Sepez8d64cb52021-11-11 21:41:27 +0000200int 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) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000207 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
208 if (!js_platform || !js_platform->app_response)
dsinclairf34518b2016-09-13 12:03:48 -0700209 return -1;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000210
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000211 ByteString bsQuestion = Question.ToUTF16LE();
212 ByteString bsTitle = Title.ToUTF16LE();
213 ByteString bsDefault = Default.ToUTF16LE();
214 ByteString bsLabel = Label.ToUTF16LE();
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000215 return js_platform->app_response(
216 js_platform, AsFPDFWideString(&bsQuestion), AsFPDFWideString(&bsTitle),
217 AsFPDFWideString(&bsDefault), AsFPDFWideString(&bsLabel), bPassword,
Lei Zhangf36006c2024-02-17 00:56:24 +0000218 response.data(), pdfium::checked_cast<int>(response.size()));
dsinclairf34518b2016-09-13 12:03:48 -0700219}
220
dsinclair735606d2016-10-05 15:47:02 -0700221void CPDFSDK_FormFillEnvironment::JS_appBeep(int nType) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000222 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
223 if (!js_platform || !js_platform->app_beep)
dsinclairf34518b2016-09-13 12:03:48 -0700224 return;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000225
226 js_platform->app_beep(js_platform, nType);
dsinclairf34518b2016-09-13 12:03:48 -0700227}
228
Ryan Harrison275e2602017-09-18 14:23:18 -0400229WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000230 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
231 if (!js_platform || !js_platform->Field_browse)
Ryan Harrison275e2602017-09-18 14:23:18 -0400232 return WideString();
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000233
234 const int nRequiredLen = js_platform->Field_browse(js_platform, nullptr, 0);
dsinclairf34518b2016-09-13 12:03:48 -0700235 if (nRequiredLen <= 0)
Ryan Harrison275e2602017-09-18 14:23:18 -0400236 return WideString();
dsinclairf34518b2016-09-13 12:03:48 -0700237
Lei Zhang549bfb22022-08-11 19:45:29 +0000238 DataVector<uint8_t> pBuff(nRequiredLen);
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000239 const int nActualLen =
240 js_platform->Field_browse(js_platform, pBuff.data(), nRequiredLen);
dsinclairf34518b2016-09-13 12:03:48 -0700241 if (nActualLen <= 0 || nActualLen > nRequiredLen)
Ryan Harrison275e2602017-09-18 14:23:18 -0400242 return WideString();
dsinclairf34518b2016-09-13 12:03:48 -0700243
Tom Sepez322c0af2019-12-09 21:44:14 +0000244 // Don't include trailing NUL.
245 pBuff.resize(nActualLen - 1);
Tom Sepez3da2eca2022-05-19 00:10:38 +0000246
247 // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
Tom Sepez40317142018-11-27 00:18:33 +0000248 return WideString::FromDefANSI(ByteStringView(pBuff));
dsinclairf34518b2016-09-13 12:03:48 -0700249}
250
Lei Zhang80524632022-08-16 20:31:46 +0000251void 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) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000259 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
260 if (!js_platform || !js_platform->Doc_mail)
dsinclairf34518b2016-09-13 12:03:48 -0700261 return;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000262
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000263 ByteString bsTo = To.ToUTF16LE();
264 ByteString bsSubject = Subject.ToUTF16LE();
265 ByteString bsCC = CC.ToUTF16LE();
266 ByteString bsBcc = BCC.ToUTF16LE();
267 ByteString bsMsg = Msg.ToUTF16LE();
Lei Zhang80524632022-08-16 20:31:46 +0000268 js_platform->Doc_mail(js_platform, const_cast<uint8_t*>(mailData.data()),
Lei Zhangf36006c2024-02-17 00:56:24 +0000269 pdfium::checked_cast<int>(mailData.size()), bUI,
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000270 AsFPDFWideString(&bsTo), AsFPDFWideString(&bsSubject),
271 AsFPDFWideString(&bsCC), AsFPDFWideString(&bsBcc),
272 AsFPDFWideString(&bsMsg));
dsinclairf34518b2016-09-13 12:03:48 -0700273}
274
dsinclair735606d2016-10-05 15:47:02 -0700275void 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) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000283 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
284 if (!js_platform || !js_platform->Doc_print)
dsinclairf34518b2016-09-13 12:03:48 -0700285 return;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000286
287 js_platform->Doc_print(js_platform, bUI, nStart, nEnd, bSilent, bShrinkToFit,
288 bPrintAsImage, bReverse, bAnnotations);
dsinclairf34518b2016-09-13 12:03:48 -0700289}
290
dsinclair735606d2016-10-05 15:47:02 -0700291void CPDFSDK_FormFillEnvironment::JS_docgotoPage(int nPageNum) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000292 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
293 if (!js_platform || !js_platform->Doc_gotoPage)
dsinclairf34518b2016-09-13 12:03:48 -0700294 return;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000295
296 js_platform->Doc_gotoPage(js_platform, nPageNum);
dsinclairf34518b2016-09-13 12:03:48 -0700297}
Tom Sepezeb98dac2018-11-07 20:04:03 +0000298
299WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() {
Tom Sepeze9703972019-08-09 21:24:29 +0000300 return GetFilePath();
301}
302#endif // PDF_ENABLE_V8
303
304WideString CPDFSDK_FormFillEnvironment::GetFilePath() const {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000305 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
306 if (!js_platform || !js_platform->Doc_getFilePath)
Tom Sepezeb98dac2018-11-07 20:04:03 +0000307 return WideString();
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000308
309 const int nRequiredLen =
310 js_platform->Doc_getFilePath(js_platform, nullptr, 0);
Tom Sepezeb98dac2018-11-07 20:04:03 +0000311 if (nRequiredLen <= 0)
312 return WideString();
313
Lei Zhang549bfb22022-08-11 19:45:29 +0000314 DataVector<uint8_t> pBuff(nRequiredLen);
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000315 const int nActualLen =
316 js_platform->Doc_getFilePath(js_platform, pBuff.data(), nRequiredLen);
Tom Sepezeb98dac2018-11-07 20:04:03 +0000317 if (nActualLen <= 0 || nActualLen > nRequiredLen)
318 return WideString();
319
Tom Sepez322c0af2019-12-09 21:44:14 +0000320 // Don't include trailing NUL.
321 pBuff.resize(nActualLen - 1);
Tom Sepez3da2eca2022-05-19 00:10:38 +0000322
323 // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
Tom Sepez40317142018-11-27 00:18:33 +0000324 return WideString::FromDefANSI(ByteStringView(pBuff));
Tom Sepezeb98dac2018-11-07 20:04:03 +0000325}
326
Lei Zhanga4eb5f62022-08-15 19:42:45 +0000327void CPDFSDK_FormFillEnvironment::SubmitForm(
328 pdfium::span<const uint8_t> form_data,
329 const WideString& URL) {
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000330 IPDF_JSPLATFORM* js_platform = GetJSPlatform();
331 if (!js_platform || !js_platform->Doc_submitForm)
Tom Sepezeb98dac2018-11-07 20:04:03 +0000332 return;
Daniel Hosseinianb67b94d2020-05-04 18:43:54 +0000333
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000334 ByteString bsUrl = URL.ToUTF16LE();
Lei Zhanga4eb5f62022-08-15 19:42:45 +0000335 js_platform->Doc_submitForm(
336 js_platform, const_cast<uint8_t*>(form_data.data()),
337 fxcrt::CollectionSize<int>(form_data), AsFPDFWideString(&bsUrl));
Tom Sepezeb98dac2018-11-07 20:04:03 +0000338}
dsinclairf34518b2016-09-13 12:03:48 -0700339
Tom Sepezf5ca90c2018-02-01 02:15:44 +0000340IJS_Runtime* CPDFSDK_FormFillEnvironment::GetIJSRuntime() {
Tom Sepezf5ca90c2018-02-01 02:15:44 +0000341 if (!m_pIJSRuntime)
342 m_pIJSRuntime = IJS_Runtime::Create(this);
343 return m_pIJSRuntime.get();
dsinclairf34518b2016-09-13 12:03:48 -0700344}
345
Tom Sepez101535f2018-06-12 13:36:05 +0000346void CPDFSDK_FormFillEnvironment::Invalidate(IPDF_Page* page,
Dan Sinclair6eec1c42017-02-21 17:20:43 -0500347 const FX_RECT& rect) {
348 if (m_pInfo && m_pInfo->FFI_Invalidate) {
Tom Sepez101535f2018-06-12 13:36:05 +0000349 m_pInfo->FFI_Invalidate(m_pInfo, FPDFPageFromIPDFPage(page), rect.left,
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000350 rect.top, rect.right, rect.bottom);
Dan Sinclair6eec1c42017-02-21 17:20:43 -0500351 }
dsinclair735606d2016-10-05 15:47:02 -0700352}
353
Tom Sepez02cb5702022-05-09 23:41:19 +0000354void CPDFSDK_FormFillEnvironment::SetCursor(
355 IPWL_FillerNotify::CursorStyle nCursorType) {
dsinclair577ad2c2016-09-22 10:20:43 -0700356 if (m_pInfo && m_pInfo->FFI_SetCursor)
Tom Sepez230db1d2021-05-19 01:56:54 +0000357 m_pInfo->FFI_SetCursor(m_pInfo, static_cast<int>(nCursorType));
dsinclair577ad2c2016-09-22 10:20:43 -0700358}
359
dsinclair735606d2016-10-05 15:47:02 -0700360int CPDFSDK_FormFillEnvironment::SetTimer(int uElapse,
361 TimerCallback lpTimerFunc) {
dsinclair577ad2c2016-09-22 10:20:43 -0700362 if (m_pInfo && m_pInfo->FFI_SetTimer)
363 return m_pInfo->FFI_SetTimer(m_pInfo, uElapse, lpTimerFunc);
Tom Sepez8a5699d2020-10-13 21:23:53 +0000364 return CFX_Timer::HandlerIface::kInvalidTimerID;
dsinclair577ad2c2016-09-22 10:20:43 -0700365}
366
dsinclair735606d2016-10-05 15:47:02 -0700367void CPDFSDK_FormFillEnvironment::KillTimer(int nTimerID) {
dsinclair577ad2c2016-09-22 10:20:43 -0700368 if (m_pInfo && m_pInfo->FFI_KillTimer)
369 m_pInfo->FFI_KillTimer(m_pInfo, nTimerID);
370}
371
dsinclair735606d2016-10-05 15:47:02 -0700372void CPDFSDK_FormFillEnvironment::OnChange() {
dsinclair577ad2c2016-09-22 10:20:43 -0700373 if (m_pInfo && m_pInfo->FFI_OnChange)
374 m_pInfo->FFI_OnChange(m_pInfo);
375}
376
Tom Sepezb3208f52021-07-30 17:41:12 +0000377void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(
378 const ByteString& namedAction) {
dsinclair577ad2c2016-09-22 10:20:43 -0700379 if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
Tom Sepezb3208f52021-07-30 17:41:12 +0000380 m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction.c_str());
dsinclair577ad2c2016-09-22 10:20:43 -0700381}
382
Tom Sepezd5ba1692021-09-13 20:36:19 +0000383void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocus(const WideString& text) {
384 OnSetFieldInputFocusInternal(text, true);
385}
386
387void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocusInternal(
388 const WideString& text,
tsepez4cf55152016-11-02 14:37:54 -0700389 bool bFocus) {
Tom Sepezd5ba1692021-09-13 20:36:19 +0000390 if (m_pInfo && m_pInfo->FFI_SetTextFieldFocus) {
Tom Sepez5ea5fa92022-03-08 00:15:23 +0000391 size_t nCharacters = text.GetLength();
Tom Sepezd5ba1692021-09-13 20:36:19 +0000392 ByteString bsUTFText = text.ToUTF16LE();
393 auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
Tom Sepez8ef63b92022-03-08 19:53:34 +0000394 m_pInfo->FFI_SetTextFieldFocus(
Lei Zhangf36006c2024-02-17 00:56:24 +0000395 m_pInfo, pBuffer, pdfium::checked_cast<FPDF_DWORD>(nCharacters),
Tom Sepez8ef63b92022-03-08 19:53:34 +0000396 bFocus);
Tom Sepezd5ba1692021-09-13 20:36:19 +0000397 }
dsinclair577ad2c2016-09-22 10:20:43 -0700398}
399
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000400void CPDFSDK_FormFillEnvironment::OnCalculate(
Tom Sepez1d737dd2021-09-22 22:46:29 +0000401 ObservedPtr<CPDFSDK_Annot>& pAnnot) {
Tom Sepeza0d85582024-05-20 22:25:24 +0000402 ObservedPtr<CPDFSDK_Widget> pWidget(ToCPDFSDKWidget(pAnnot.Get()));
403 if (pWidget) {
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000404 m_pInteractiveForm->OnCalculate(pWidget->GetFormField());
Tom Sepeza0d85582024-05-20 22:25:24 +0000405 }
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000406}
407
Tom Sepez1d737dd2021-09-22 22:46:29 +0000408void CPDFSDK_FormFillEnvironment::OnFormat(ObservedPtr<CPDFSDK_Annot>& pAnnot) {
Tom Sepeza0d85582024-05-20 22:25:24 +0000409 ObservedPtr<CPDFSDK_Widget> pWidget(ToCPDFSDKWidget(pAnnot.Get()));
Lei Zhang24c6be62024-02-08 20:06:48 +0000410 std::optional<WideString> sValue =
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000411 m_pInteractiveForm->OnFormat(pWidget->GetFormField());
Tom Sepeza0d85582024-05-20 22:25:24 +0000412 if (!pWidget) {
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000413 return;
Tom Sepeza0d85582024-05-20 22:25:24 +0000414 }
Tom Sepezbf6f9b02021-09-13 23:45:59 +0000415 if (sValue.has_value()) {
416 m_pInteractiveForm->ResetFieldAppearance(pWidget->GetFormField(), sValue);
417 m_pInteractiveForm->UpdateField(pWidget->GetFormField());
418 }
419}
420
Tom Sepezb3208f52021-07-30 17:41:12 +0000421void CPDFSDK_FormFillEnvironment::DoURIAction(const ByteString& bsURI,
Tom Sepez6f9e9f62021-08-11 17:01:53 +0000422 Mask<FWL_EVENTFLAG> modifiers) {
Badhri Ravikumardacaac72020-04-23 18:00:38 +0000423 if (!m_pInfo)
424 return;
425
426 if (m_pInfo->version >= 2 && m_pInfo->FFI_DoURIActionWithKeyboardModifier) {
Tom Sepezb3208f52021-07-30 17:41:12 +0000427 m_pInfo->FFI_DoURIActionWithKeyboardModifier(m_pInfo, bsURI.c_str(),
Tom Sepez6f9e9f62021-08-11 17:01:53 +0000428 modifiers.UncheckedValue());
Badhri Ravikumardacaac72020-04-23 18:00:38 +0000429 return;
430 }
431
432 if (m_pInfo->FFI_DoURIAction)
Tom Sepezb3208f52021-07-30 17:41:12 +0000433 m_pInfo->FFI_DoURIAction(m_pInfo, bsURI.c_str());
dsinclair577ad2c2016-09-22 10:20:43 -0700434}
435
dsinclair735606d2016-10-05 15:47:02 -0700436void CPDFSDK_FormFillEnvironment::DoGoToAction(int nPageIndex,
437 int zoomMode,
Tom Sepez1559cc22022-01-19 19:03:40 +0000438 pdfium::span<float> fPosArray) {
dsinclair577ad2c2016-09-22 10:20:43 -0700439 if (m_pInfo && m_pInfo->FFI_DoGoToAction) {
Tom Sepez1559cc22022-01-19 19:03:40 +0000440 m_pInfo->FFI_DoGoToAction(m_pInfo, nPageIndex, zoomMode, fPosArray.data(),
441 fxcrt::CollectionSize<int>(fPosArray));
dsinclair577ad2c2016-09-22 10:20:43 -0700442 }
443}
444
445#ifdef PDF_ENABLE_XFA
Tom Sepezd48bd292019-08-14 19:48:55 +0000446int CPDFSDK_FormFillEnvironment::GetPageViewCount() const {
Lei Zhang549fe5d2021-06-18 23:46:09 +0000447 return fxcrt::CollectionSize<int>(m_PageMap);
Tom Sepezd48bd292019-08-14 19:48:55 +0000448}
449
450void CPDFSDK_FormFillEnvironment::DisplayCaret(IPDF_Page* page,
dsinclair735606d2016-10-05 15:47:02 -0700451 FPDF_BOOL bVisible,
452 double left,
453 double top,
454 double right,
455 double bottom) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000456 if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_DisplayCaret) {
Tom Sepez101535f2018-06-12 13:36:05 +0000457 m_pInfo->FFI_DisplayCaret(m_pInfo, FPDFPageFromIPDFPage(page), bVisible,
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000458 left, top, right, bottom);
dsinclair577ad2c2016-09-22 10:20:43 -0700459 }
460}
461
Tom Sepez74136f52018-04-27 20:29:37 +0000462int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex() const {
Tom Sepez197d0d82019-12-18 20:28:20 +0000463 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetCurrentPageIndex)
dsinclair577ad2c2016-09-22 10:20:43 -0700464 return -1;
Tom Sepezda8063f2018-04-30 17:41:49 +0000465 return m_pInfo->FFI_GetCurrentPageIndex(
Tom Sepezc4acde52022-10-28 00:47:46 +0000466 m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc));
dsinclair577ad2c2016-09-22 10:20:43 -0700467}
468
Tom Sepez74136f52018-04-27 20:29:37 +0000469void CPDFSDK_FormFillEnvironment::SetCurrentPage(int iCurPage) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000470 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_SetCurrentPage)
Tom Sepezda8063f2018-04-30 17:41:49 +0000471 return;
Tom Sepezc4acde52022-10-28 00:47:46 +0000472 m_pInfo->FFI_SetCurrentPage(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc),
473 iCurPage);
dsinclair577ad2c2016-09-22 10:20:43 -0700474}
475
Tom Sepez74136f52018-04-27 20:29:37 +0000476void CPDFSDK_FormFillEnvironment::GotoURL(const WideString& wsURL) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000477 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GotoURL)
dsinclair577ad2c2016-09-22 10:20:43 -0700478 return;
479
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000480 ByteString bsTo = wsURL.ToUTF16LE();
Tom Sepezc4acde52022-10-28 00:47:46 +0000481 m_pInfo->FFI_GotoURL(m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc),
Tom Sepez74136f52018-04-27 20:29:37 +0000482 AsFPDFWideString(&bsTo));
dsinclair577ad2c2016-09-22 10:20:43 -0700483}
484
Tom Sepezd48bd292019-08-14 19:48:55 +0000485FS_RECTF CPDFSDK_FormFillEnvironment::GetPageViewRect(IPDF_Page* page) {
Lei Zhang95008dd2018-12-13 21:10:23 +0000486 FS_RECTF rect = {0.0f, 0.0f, 0.0f, 0.0f};
Tom Sepez197d0d82019-12-18 20:28:20 +0000487 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_GetPageViewRect)
Lei Zhang95008dd2018-12-13 21:10:23 +0000488 return rect;
dsinclair577ad2c2016-09-22 10:20:43 -0700489
490 double left;
491 double top;
492 double right;
493 double bottom;
Tom Sepez101535f2018-06-12 13:36:05 +0000494 m_pInfo->FFI_GetPageViewRect(m_pInfo, FPDFPageFromIPDFPage(page), &left, &top,
495 &right, &bottom);
dsinclair577ad2c2016-09-22 10:20:43 -0700496
Lei Zhang95008dd2018-12-13 21:10:23 +0000497 rect.left = static_cast<float>(left);
498 rect.top = static_cast<float>(top);
499 rect.bottom = static_cast<float>(bottom);
500 rect.right = static_cast<float>(right);
501 return rect;
dsinclair577ad2c2016-09-22 10:20:43 -0700502}
503
Tom Sepezd48bd292019-08-14 19:48:55 +0000504bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page,
tsepez4cf55152016-11-02 14:37:54 -0700505 int menuFlag,
Lei Zhangc1cd2ea2019-07-10 20:00:42 +0000506 const CFX_PointF& pt) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000507 return m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PopupMenu &&
Tom Sepez094f8e62020-04-01 21:01:44 +0000508 m_pInfo->FFI_PopupMenu(m_pInfo, FPDFPageFromIPDFPage(page), nullptr,
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000509 menuFlag, pt.x, pt.y);
dsinclair577ad2c2016-09-22 10:20:43 -0700510}
511
dsinclair735606d2016-10-05 15:47:02 -0700512void CPDFSDK_FormFillEnvironment::EmailTo(FPDF_FILEHANDLER* fileHandler,
513 FPDF_WIDESTRING pTo,
514 FPDF_WIDESTRING pSubject,
515 FPDF_WIDESTRING pCC,
516 FPDF_WIDESTRING pBcc,
517 FPDF_WIDESTRING pMsg) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000518 if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_EmailTo)
dsinclair577ad2c2016-09-22 10:20:43 -0700519 m_pInfo->FFI_EmailTo(m_pInfo, fileHandler, pTo, pSubject, pCC, pBcc, pMsg);
520}
521
dsinclair735606d2016-10-05 15:47:02 -0700522void CPDFSDK_FormFillEnvironment::UploadTo(FPDF_FILEHANDLER* fileHandler,
523 int fileFlag,
524 FPDF_WIDESTRING uploadTo) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000525 if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_UploadTo)
dsinclair577ad2c2016-09-22 10:20:43 -0700526 m_pInfo->FFI_UploadTo(m_pInfo, fileHandler, fileFlag, uploadTo);
527}
528
dsinclair735606d2016-10-05 15:47:02 -0700529FPDF_FILEHANDLER* CPDFSDK_FormFillEnvironment::OpenFile(int fileType,
530 FPDF_WIDESTRING wsURL,
531 const char* mode) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000532 if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_OpenFile)
dsinclair577ad2c2016-09-22 10:20:43 -0700533 return m_pInfo->FFI_OpenFile(m_pInfo, fileType, wsURL, mode);
534 return nullptr;
535}
536
Dan Sinclair0b950422017-09-21 15:49:49 -0400537RetainPtr<IFX_SeekableReadStream> CPDFSDK_FormFillEnvironment::DownloadFromURL(
Tom Sepez35939f82018-04-17 21:23:58 +0000538 const WideString& url) {
Lei Zhangf93f4392024-08-16 18:10:00 +0000539 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_DownloadFromURL) {
dsinclair577ad2c2016-09-22 10:20:43 -0700540 return nullptr;
Lei Zhangf93f4392024-08-16 18:10:00 +0000541 }
dsinclair577ad2c2016-09-22 10:20:43 -0700542
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000543 ByteString bstrURL = url.ToUTF16LE();
Lei Zhangf93f4392024-08-16 18:10:00 +0000544 FPDF_FILEHANDLER* file_handler =
Tom Sepez1e934f62018-04-11 21:11:28 +0000545 m_pInfo->FFI_DownloadFromURL(m_pInfo, AsFPDFWideString(&bstrURL));
Lei Zhangf93f4392024-08-16 18:10:00 +0000546 if (!file_handler) {
547 return nullptr;
548 }
dsinclair577ad2c2016-09-22 10:20:43 -0700549
Lei Zhangf93f4392024-08-16 18:10:00 +0000550 return MakeSeekableStream(file_handler);
dsinclair577ad2c2016-09-22 10:20:43 -0700551}
552
Ryan Harrison275e2602017-09-18 14:23:18 -0400553WideString CPDFSDK_FormFillEnvironment::PostRequestURL(
Tom Sepez35939f82018-04-17 21:23:58 +0000554 const WideString& wsURL,
555 const WideString& wsData,
556 const WideString& wsContentType,
557 const WideString& wsEncode,
558 const WideString& wsHeader) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000559 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PostRequestURL)
Tom Sepez890eac22018-12-03 20:35:51 +0000560 return WideString();
dsinclair577ad2c2016-09-22 10:20:43 -0700561
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000562 ByteString bsURL = wsURL.ToUTF16LE();
563 ByteString bsData = wsData.ToUTF16LE();
564 ByteString bsContentType = wsContentType.ToUTF16LE();
565 ByteString bsEncode = wsEncode.ToUTF16LE();
566 ByteString bsHeader = wsHeader.ToUTF16LE();
dsinclair577ad2c2016-09-22 10:20:43 -0700567
568 FPDF_BSTR response;
569 FPDF_BStr_Init(&response);
Tom Sepez1e934f62018-04-11 21:11:28 +0000570 m_pInfo->FFI_PostRequestURL(
571 m_pInfo, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData),
572 AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode),
573 AsFPDFWideString(&bsHeader), &response);
dsinclair577ad2c2016-09-22 10:20:43 -0700574
Tom Sepez3b679fe2024-04-09 18:49:32 +0000575 // SAFETY: required from FFI callback.
576 WideString wsRet = WideString::FromUTF16LE(UNSAFE_BUFFERS(
577 pdfium::make_span(reinterpret_cast<const uint8_t*>(response.str),
578 static_cast<size_t>(response.len))));
Tom Sepez1e934f62018-04-11 21:11:28 +0000579
dsinclair577ad2c2016-09-22 10:20:43 -0700580 FPDF_BStr_Clear(&response);
dsinclair577ad2c2016-09-22 10:20:43 -0700581 return wsRet;
582}
583
Tom Sepez35939f82018-04-17 21:23:58 +0000584FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(
585 const WideString& wsURL,
586 const WideString& wsData,
587 const WideString& wsEncode) {
Tom Sepez197d0d82019-12-18 20:28:20 +0000588 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_PutRequestURL)
tsepez4cf55152016-11-02 14:37:54 -0700589 return false;
dsinclair577ad2c2016-09-22 10:20:43 -0700590
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000591 ByteString bsURL = wsURL.ToUTF16LE();
592 ByteString bsData = wsData.ToUTF16LE();
593 ByteString bsEncode = wsEncode.ToUTF16LE();
dsinclair577ad2c2016-09-22 10:20:43 -0700594
Tom Sepez1e934f62018-04-11 21:11:28 +0000595 return m_pInfo->FFI_PutRequestURL(m_pInfo, AsFPDFWideString(&bsURL),
596 AsFPDFWideString(&bsData),
597 AsFPDFWideString(&bsEncode));
dsinclair577ad2c2016-09-22 10:20:43 -0700598}
599
dsinclair735606d2016-10-05 15:47:02 -0700600void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount,
601 uint32_t dwEventType) const {
Tom Sepez197d0d82019-12-18 20:28:20 +0000602 if (m_pInfo && m_pInfo->version >= 2 && m_pInfo->FFI_PageEvent)
dsinclair577ad2c2016-09-22 10:20:43 -0700603 m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType);
604}
605#endif // PDF_ENABLE_XFA
dsinclair7cbe68e2016-10-12 11:56:23 -0700606
607void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() {
tsepez2599ff72016-11-08 14:38:59 -0800608 for (auto& it : m_PageMap) {
Tom Sepeza6646db2022-06-22 21:56:03 +0000609 if (it.second->IsValidSDKAnnot(GetFocusAnnot())) {
610 ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
Tom Sepez6f9e9f62021-08-11 17:01:53 +0000611 KillFocusAnnot({});
Tom Sepeza6646db2022-06-22 21:56:03 +0000612 if (!pObserved)
613 break;
614 }
dsinclair7cbe68e2016-10-12 11:56:23 -0700615 }
616}
617
Tom Sepezcee8fbd2021-06-04 19:21:40 +0000618CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetOrCreatePageView(
619 IPDF_Page* pUnderlyingPage) {
620 CPDFSDK_PageView* pExisting = GetPageView(pUnderlyingPage);
621 if (pExisting)
622 return pExisting;
dsinclair7cbe68e2016-10-12 11:56:23 -0700623
Tom Sepez5af95432020-05-15 22:55:16 +0000624 auto pNew = std::make_unique<CPDFSDK_PageView>(this, pUnderlyingPage);
Tom Sepezfe91c6c2017-05-16 15:33:20 -0700625 CPDFSDK_PageView* pPageView = pNew.get();
626 m_PageMap[pUnderlyingPage] = std::move(pNew);
627
dsinclair7cbe68e2016-10-12 11:56:23 -0700628 // Delay to load all the annotations, to avoid endless loop.
629 pPageView->LoadFXAnnots();
630 return pPageView;
631}
632
Tom Sepezcee8fbd2021-06-04 19:21:40 +0000633CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(
634 IPDF_Page* pUnderlyingPage) {
635 auto it = m_PageMap.find(pUnderlyingPage);
636 return it != m_PageMap.end() ? it->second.get() : nullptr;
637}
638
Tom Sepezd5ba1692021-09-13 20:36:19 +0000639CFX_Timer::HandlerIface* CPDFSDK_FormFillEnvironment::GetTimerHandler() {
640 return this;
641}
642
Lei Zhangb2432932020-03-20 18:17:44 +0000643CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageViewAtIndex(int nIndex) {
Tom Sepez101535f2018-06-12 13:36:05 +0000644 IPDF_Page* pTempPage = GetPage(nIndex);
Tom Sepezcee8fbd2021-06-04 19:21:40 +0000645 return pTempPage ? GetPageView(pTempPage) : nullptr;
dsinclair7cbe68e2016-10-12 11:56:23 -0700646}
647
Tom Sepez20d08092020-01-29 21:27:44 +0000648void CPDFSDK_FormFillEnvironment::ProcJavascriptAction() {
Tom Sepezc4acde52022-10-28 00:47:46 +0000649 auto name_tree = CPDF_NameTree::Create(m_pCPDFDoc, "JavaScript");
Lei Zhang1575b472020-04-02 23:09:15 +0000650 if (!name_tree)
651 return;
652
653 size_t count = name_tree->GetCount();
654 for (size_t i = 0; i < count; ++i) {
Tom Sepez20d08092020-01-29 21:27:44 +0000655 WideString name;
Tom Sepez525a4272022-09-28 21:35:24 +0000656 CPDF_Action action(ToDictionary(name_tree->LookupValueAndName(i, &name)));
Tom Sepez946bf0f2022-04-08 22:06:41 +0000657 DoActionJavaScript(action, name);
dsinclair7cbe68e2016-10-12 11:56:23 -0700658 }
659}
660
tsepez4cf55152016-11-02 14:37:54 -0700661bool CPDFSDK_FormFillEnvironment::ProcOpenAction() {
Tom Sepezaa51f002022-06-25 00:46:38 +0000662 const CPDF_Dictionary* pRoot = m_pCPDFDoc->GetRoot();
dsinclair7cbe68e2016-10-12 11:56:23 -0700663 if (!pRoot)
tsepez4cf55152016-11-02 14:37:54 -0700664 return false;
dsinclair7cbe68e2016-10-12 11:56:23 -0700665
Tom Sepezc84dc1f2022-09-19 23:06:33 +0000666 RetainPtr<const CPDF_Object> pOpenAction(pRoot->GetDictFor("OpenAction"));
dsinclair7cbe68e2016-10-12 11:56:23 -0700667 if (!pOpenAction)
668 pOpenAction = pRoot->GetArrayFor("OpenAction");
dsinclair7cbe68e2016-10-12 11:56:23 -0700669 if (!pOpenAction)
tsepez4cf55152016-11-02 14:37:54 -0700670 return false;
dsinclair7cbe68e2016-10-12 11:56:23 -0700671
672 if (pOpenAction->IsArray())
tsepez4cf55152016-11-02 14:37:54 -0700673 return true;
dsinclair7cbe68e2016-10-12 11:56:23 -0700674
Tom Sepezaf0fcf12022-09-27 18:12:53 +0000675 RetainPtr<const CPDF_Dictionary> pDict = ToDictionary(pOpenAction);
Lei Zhang222e1a42017-06-20 14:47:00 -0700676 if (!pDict)
677 return false;
678
Tom Sepezaf0fcf12022-09-27 18:12:53 +0000679 DoActionDocOpen(CPDF_Action(std::move(pDict)));
Lei Zhang222e1a42017-06-20 14:47:00 -0700680 return true;
dsinclair7cbe68e2016-10-12 11:56:23 -0700681}
682
Tom Sepez101535f2018-06-12 13:36:05 +0000683void CPDFSDK_FormFillEnvironment::RemovePageView(IPDF_Page* pUnderlyingPage) {
tsepez2599ff72016-11-08 14:38:59 -0800684 auto it = m_PageMap.find(pUnderlyingPage);
685 if (it == m_PageMap.end())
dsinclair7cbe68e2016-10-12 11:56:23 -0700686 return;
687
dsinclair6c659ab2016-10-12 13:41:38 -0700688 CPDFSDK_PageView* pPageView = it->second.get();
dsinclair7cbe68e2016-10-12 11:56:23 -0700689 if (pPageView->IsLocked() || pPageView->IsBeingDestroyed())
690 return;
691
692 // Mark the page view so we do not come into |RemovePageView| a second
693 // time while we're in the process of removing.
694 pPageView->SetBeingDestroyed();
695
696 // This must happen before we remove |pPageView| from the map because
697 // |KillFocusAnnot| can call into the |GetPage| method which will
698 // look for this page view in the map, if it doesn't find it a new one will
699 // be created. We then have two page views pointing to the same page and
700 // bad things happen.
701 if (pPageView->IsValidSDKAnnot(GetFocusAnnot()))
Tom Sepez6f9e9f62021-08-11 17:01:53 +0000702 KillFocusAnnot({});
dsinclair7cbe68e2016-10-12 11:56:23 -0700703
704 // Remove the page from the map to make sure we don't accidentally attempt
705 // to use the |pPageView| while we're cleaning it up.
tsepez2599ff72016-11-08 14:38:59 -0800706 m_PageMap.erase(it);
dsinclair7cbe68e2016-10-12 11:56:23 -0700707}
708
Tom Sepezcee8fbd2021-06-04 19:21:40 +0000709IPDF_Page* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) const {
Lei Zhang60fa2fc2017-07-21 17:42:19 -0700710 if (!m_pInfo || !m_pInfo->FFI_GetPage)
711 return nullptr;
Tom Sepez101535f2018-06-12 13:36:05 +0000712 return IPDFPageFromFPDFPage(m_pInfo->FFI_GetPage(
Tom Sepezc4acde52022-10-28 00:47:46 +0000713 m_pInfo, FPDFDocumentFromCPDFDocument(m_pCPDFDoc), nIndex));
dsinclair7cbe68e2016-10-12 11:56:23 -0700714}
715
Lei Zhang073ecf42018-10-11 16:56:00 +0000716CPDFSDK_InteractiveForm* CPDFSDK_FormFillEnvironment::GetInteractiveForm() {
717 if (!m_pInteractiveForm)
Tom Sepez5af95432020-05-15 22:55:16 +0000718 m_pInteractiveForm = std::make_unique<CPDFSDK_InteractiveForm>(this);
Lei Zhang073ecf42018-10-11 16:56:00 +0000719 return m_pInteractiveForm.get();
dsinclair7cbe68e2016-10-12 11:56:23 -0700720}
721
Tom Sepez2120c852021-10-28 23:34:26 +0000722void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_Annot* pAnnot) {
tsepez2599ff72016-11-08 14:38:59 -0800723 for (const auto& it : m_PageMap) {
Tom Sepeza6646db2022-06-22 21:56:03 +0000724 ObservedPtr<CPDFSDK_PageView> pObserved(it.second.get());
725 if (pObserved) {
726 pObserved->UpdateView(pAnnot);
727 if (!pObserved)
728 break;
729 }
dsinclair7cbe68e2016-10-12 11:56:23 -0700730 }
731}
732
Tom Sepezd5ba1692021-09-13 20:36:19 +0000733CPDFSDK_Annot* CPDFSDK_FormFillEnvironment::GetFocusAnnot() const {
734 return m_pFocusAnnot.Get();
735}
736
tsepez4cf55152016-11-02 14:37:54 -0700737bool CPDFSDK_FormFillEnvironment::SetFocusAnnot(
Tom Sepez1d737dd2021-09-22 22:46:29 +0000738 ObservedPtr<CPDFSDK_Annot>& pAnnot) {
dsinclair7cbe68e2016-10-12 11:56:23 -0700739 if (m_bBeingDestroyed)
tsepez4cf55152016-11-02 14:37:54 -0700740 return false;
Tom Sepez1d737dd2021-09-22 22:46:29 +0000741 if (m_pFocusAnnot == pAnnot)
tsepez4cf55152016-11-02 14:37:54 -0700742 return true;
Tom Sepez6f9e9f62021-08-11 17:01:53 +0000743 if (m_pFocusAnnot && !KillFocusAnnot({}))
tsepez4cf55152016-11-02 14:37:54 -0700744 return false;
Tom Sepez1d737dd2021-09-22 22:46:29 +0000745 if (!pAnnot)
tsepez4cf55152016-11-02 14:37:54 -0700746 return false;
Tom Sepez1d737dd2021-09-22 22:46:29 +0000747 if (!pAnnot->GetPageView()->IsValid())
Lei Zhang222e1a42017-06-20 14:47:00 -0700748 return false;
749
Lei Zhang222e1a42017-06-20 14:47:00 -0700750 if (m_pFocusAnnot)
751 return false;
752
dsinclair7cbe68e2016-10-12 11:56:23 -0700753#ifdef PDF_ENABLE_XFA
Lei Zhangb5910cf2022-04-08 21:22:51 +0000754 CPDFXFA_Widget* pXFAWidget = pAnnot->AsXFAWidget();
Lei Zhang822b6ea2022-04-05 03:40:40 +0000755 if (pXFAWidget && pXFAWidget->OnChangedFocus())
Lei Zhang222e1a42017-06-20 14:47:00 -0700756 return false;
Minh Tran0e71ce22019-07-29 22:28:49 +0000757
Lei Zhang822b6ea2022-04-05 03:40:40 +0000758 // `pAnnot` may be destroyed in `OnChangedFocus()`.
Tom Sepez1d737dd2021-09-22 22:46:29 +0000759 if (!pAnnot)
Minh Tran0e71ce22019-07-29 22:28:49 +0000760 return false;
dsinclair7cbe68e2016-10-12 11:56:23 -0700761#endif // PDF_ENABLE_XFA
Tom Sepez02d71072021-09-21 22:43:01 +0000762
Tom Sepeza0d85582024-05-20 22:25:24 +0000763 if (!CPDFSDK_Annot::OnSetFocus(pAnnot, {})) {
Lei Zhang222e1a42017-06-20 14:47:00 -0700764 return false;
Tom Sepeza0d85582024-05-20 22:25:24 +0000765 }
766 if (m_pFocusAnnot) {
Lei Zhang222e1a42017-06-20 14:47:00 -0700767 return false;
Tom Sepeza0d85582024-05-20 22:25:24 +0000768 }
769 m_pFocusAnnot = pAnnot;
Aayush Dhirc63913e2020-02-12 09:45:34 +0000770
771 // If we are not able to inform the client about the focus change, it
772 // shouldn't be considered as failure.
773 SendOnFocusChange(pAnnot);
Lei Zhang222e1a42017-06-20 14:47:00 -0700774 return true;
dsinclair7cbe68e2016-10-12 11:56:23 -0700775}
776
Lei Zhang2ea512b2022-04-08 21:10:01 +0000777bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(Mask<FWL_EVENTFLAG> nFlags) {
Lei Zhang222e1a42017-06-20 14:47:00 -0700778 if (!m_pFocusAnnot)
779 return false;
780
Tom Sepezd8ae8f82019-06-12 17:58:33 +0000781 ObservedPtr<CPDFSDK_Annot> pFocusAnnot(m_pFocusAnnot.Get());
Lei Zhang222e1a42017-06-20 14:47:00 -0700782 m_pFocusAnnot.Reset();
dsinclair7cbe68e2016-10-12 11:56:23 -0700783
Lei Zhang2ea512b2022-04-08 21:10:01 +0000784 if (!CPDFSDK_Annot::OnKillFocus(pFocusAnnot, nFlags)) {
Tom Sepeza0d85582024-05-20 22:25:24 +0000785 m_pFocusAnnot = pFocusAnnot;
Lei Zhang222e1a42017-06-20 14:47:00 -0700786 return false;
787 }
788
Lei Zhang2ea512b2022-04-08 21:10:01 +0000789 // Might have been destroyed by OnKillFocus().
Tom Sepez1c21d862020-07-24 22:14:41 +0000790 if (!pFocusAnnot)
791 return false;
792
Lei Zhang222e1a42017-06-20 14:47:00 -0700793 if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
Tom Sepeza0d85582024-05-20 22:25:24 +0000794 const FormFieldType field_type =
795 ToCPDFSDKWidget(pFocusAnnot.Get())->GetFieldType();
796 if (field_type == FormFieldType::kTextField ||
797 field_type == FormFieldType::kComboBox) {
Tom Sepezd5ba1692021-09-13 20:36:19 +0000798 OnSetFieldInputFocusInternal(WideString(), false);
dsinclair7cbe68e2016-10-12 11:56:23 -0700799 }
800 }
Lei Zhang222e1a42017-06-20 14:47:00 -0700801 return !m_pFocusAnnot;
dsinclair7cbe68e2016-10-12 11:56:23 -0700802}
Tom Sepeza88399c2019-06-11 16:39:51 +0000803
Tom Sepeza1d34422018-04-24 20:54:41 +0000804int CPDFSDK_FormFillEnvironment::GetPageCount() const {
Tom Sepezdf93cd32018-05-25 22:58:39 +0000805 CPDF_Document::Extension* pExtension = m_pCPDFDoc->GetExtension();
806 return pExtension ? pExtension->GetPageCount() : m_pCPDFDoc->GetPageCount();
Tom Sepeza1d34422018-04-24 20:54:41 +0000807}
808
Lei Zhang1f893992020-01-31 00:20:24 +0000809bool CPDFSDK_FormFillEnvironment::HasPermissions(uint32_t flags) const {
JD Pierce1d550b82023-09-28 08:35:42 +0000810 return !!(m_pCPDFDoc->GetUserPermissions(/*get_owner_perms=*/true) & flags);
dsinclair7cbe68e2016-10-12 11:56:23 -0700811}
Aayush Dhirc63913e2020-02-12 09:45:34 +0000812
813void CPDFSDK_FormFillEnvironment::SendOnFocusChange(
Tom Sepez1d737dd2021-09-22 22:46:29 +0000814 ObservedPtr<CPDFSDK_Annot>& pAnnot) {
Aayush Dhirc63913e2020-02-12 09:45:34 +0000815 if (!m_pInfo || m_pInfo->version < 2 || !m_pInfo->FFI_OnFocusChange)
816 return;
817
Lei Zhangc0d79282020-04-11 00:04:56 +0000818 // TODO(crbug.com/pdfium/1482): Handle XFA case.
Tom Sepez1d737dd2021-09-22 22:46:29 +0000819 if (pAnnot->AsXFAWidget())
Aayush Dhirc63913e2020-02-12 09:45:34 +0000820 return;
Aayush Dhirc63913e2020-02-12 09:45:34 +0000821
Tom Sepez1d737dd2021-09-22 22:46:29 +0000822 CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
Lei Zhangc2ad6282020-02-13 20:50:57 +0000823 if (!pPageView->IsValid())
Aayush Dhirc63913e2020-02-12 09:45:34 +0000824 return;
825
Tom Sepez1d737dd2021-09-22 22:46:29 +0000826 IPDF_Page* page = pAnnot->GetPage();
Lei Zhangc0d79282020-04-11 00:04:56 +0000827 if (!page)
Aayush Dhirc63913e2020-02-12 09:45:34 +0000828 return;
829
Tom Sepezb5649d92022-07-19 00:45:22 +0000830 RetainPtr<CPDF_Dictionary> annot_dict =
831 pAnnot->GetPDFAnnot()->GetMutableAnnotDict();
Tom Sepez5af95432020-05-15 22:55:16 +0000832 auto focused_annot = std::make_unique<CPDF_AnnotContext>(annot_dict, page);
Aayush Dhirc63913e2020-02-12 09:45:34 +0000833 FPDF_ANNOTATION fpdf_annot =
834 FPDFAnnotationFromCPDFAnnotContext(focused_annot.get());
835
836 m_pInfo->FFI_OnFocusChange(m_pInfo, fpdf_annot, pPageView->GetPageIndex());
Lei Zhangc2ad6282020-02-13 20:50:57 +0000837}
Tom Sepez946bf0f2022-04-08 22:06:41 +0000838
839bool CPDFSDK_FormFillEnvironment::DoActionDocOpen(const CPDF_Action& action) {
840 std::set<const CPDF_Dictionary*> visited;
841 return ExecuteDocumentOpenAction(action, &visited);
842}
843
844bool CPDFSDK_FormFillEnvironment::DoActionJavaScript(
845 const CPDF_Action& JsAction,
846 WideString csJSName) {
847 if (JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
848 WideString swJS = JsAction.GetJavaScript();
849 if (!swJS.IsEmpty()) {
850 RunDocumentOpenJavaScript(csJSName, swJS);
851 return true;
852 }
853 }
854
855 return false;
856}
857
858bool CPDFSDK_FormFillEnvironment::DoActionFieldJavaScript(
859 const CPDF_Action& JsAction,
860 CPDF_AAction::AActionType type,
861 CPDF_FormField* pFormField,
862 CFFL_FieldAction* data) {
863 if (IsJSPlatformPresent() &&
864 JsAction.GetType() == CPDF_Action::Type::kJavaScript) {
865 WideString swJS = JsAction.GetJavaScript();
866 if (!swJS.IsEmpty()) {
867 RunFieldJavaScript(pFormField, type, data, swJS);
868 return true;
869 }
870 }
871 return false;
872}
873
874bool CPDFSDK_FormFillEnvironment::DoActionLink(const CPDF_Action& action,
875 CPDF_AAction::AActionType type,
876 Mask<FWL_EVENTFLAG> modifiers) {
877 if (!CPDF_AAction::IsUserInput(type))
878 return false;
879
880 switch (action.GetType()) {
881 case CPDF_Action::Type::kGoTo:
882 DoActionGoTo(action);
883 return true;
884 case CPDF_Action::Type::kURI:
885 DoActionURI(action, modifiers);
886 return true;
887 default:
888 return false;
889 }
890}
891
892bool CPDFSDK_FormFillEnvironment::DoActionDestination(const CPDF_Dest& dest) {
893 CPDF_Document* document = GetPDFDocument();
894 DCHECK(document);
895
Tom Sepez14b3b8c2022-10-07 23:41:41 +0000896 std::vector<float> positions = dest.GetScrollPositionArray();
897 DoGoToAction(dest.GetDestPageIndex(document), dest.GetZoomMode(), positions);
Tom Sepez946bf0f2022-04-08 22:06:41 +0000898 return true;
899}
900
901bool CPDFSDK_FormFillEnvironment::DoActionPage(
902 const CPDF_Action& action,
903 CPDF_AAction::AActionType eType) {
904 std::set<const CPDF_Dictionary*> visited;
905 return ExecuteDocumentPageAction(action, eType, &visited);
906}
907
908bool CPDFSDK_FormFillEnvironment::DoActionDocument(
909 const CPDF_Action& action,
910 CPDF_AAction::AActionType eType) {
911 std::set<const CPDF_Dictionary*> visited;
912 return ExecuteDocumentPageAction(action, eType, &visited);
913}
914
915bool CPDFSDK_FormFillEnvironment::DoActionField(const CPDF_Action& action,
916 CPDF_AAction::AActionType type,
917 CPDF_FormField* pFormField,
918 CFFL_FieldAction* data) {
919 std::set<const CPDF_Dictionary*> visited;
920 return ExecuteFieldAction(action, type, pFormField, data, &visited);
921}
922
923bool CPDFSDK_FormFillEnvironment::ExecuteDocumentOpenAction(
924 const CPDF_Action& action,
925 std::set<const CPDF_Dictionary*>* visited) {
926 const CPDF_Dictionary* pDict = action.GetDict();
927 if (pdfium::Contains(*visited, pDict))
928 return false;
929
930 visited->insert(pDict);
931
932 if (action.GetType() == CPDF_Action::Type::kJavaScript) {
933 if (IsJSPlatformPresent()) {
934 WideString swJS = action.GetJavaScript();
935 if (!swJS.IsEmpty())
936 RunDocumentOpenJavaScript(WideString(), swJS);
937 }
938 } else {
939 DoActionNoJs(action, CPDF_AAction::AActionType::kDocumentOpen);
940 }
941
942 for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
943 CPDF_Action subaction = action.GetSubAction(i);
944 if (!ExecuteDocumentOpenAction(subaction, visited))
945 return false;
946 }
947
948 return true;
949}
950
951bool CPDFSDK_FormFillEnvironment::ExecuteDocumentPageAction(
952 const CPDF_Action& action,
953 CPDF_AAction::AActionType type,
954 std::set<const CPDF_Dictionary*>* visited) {
955 const CPDF_Dictionary* pDict = action.GetDict();
956 if (pdfium::Contains(*visited, pDict))
957 return false;
958
959 visited->insert(pDict);
960
961 if (action.GetType() == CPDF_Action::Type::kJavaScript) {
962 if (IsJSPlatformPresent()) {
963 WideString swJS = action.GetJavaScript();
964 if (!swJS.IsEmpty())
965 RunDocumentPageJavaScript(type, swJS);
966 }
967 } else {
968 DoActionNoJs(action, type);
969 }
970
971 for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
972 CPDF_Action subaction = action.GetSubAction(i);
973 if (!ExecuteDocumentPageAction(subaction, type, visited))
974 return false;
975 }
976
977 return true;
978}
979
Tom Sepezb5649d92022-07-19 00:45:22 +0000980bool CPDFSDK_FormFillEnvironment::IsValidField(
981 const CPDF_Dictionary* pFieldDict) {
Tom Sepez946bf0f2022-04-08 22:06:41 +0000982 DCHECK(pFieldDict);
983
984 CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
985 CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
986 return !!pPDFForm->GetFieldByDict(pFieldDict);
987}
988
989bool CPDFSDK_FormFillEnvironment::ExecuteFieldAction(
990 const CPDF_Action& action,
991 CPDF_AAction::AActionType type,
992 CPDF_FormField* pFormField,
993 CFFL_FieldAction* data,
994 std::set<const CPDF_Dictionary*>* visited) {
995 const CPDF_Dictionary* pDict = action.GetDict();
996 if (pdfium::Contains(*visited, pDict))
997 return false;
998
999 visited->insert(pDict);
1000
1001 if (action.GetType() == CPDF_Action::Type::kJavaScript) {
1002 if (IsJSPlatformPresent()) {
1003 WideString swJS = action.GetJavaScript();
1004 if (!swJS.IsEmpty()) {
1005 RunFieldJavaScript(pFormField, type, data, swJS);
1006 if (!IsValidField(pFormField->GetFieldDict()))
1007 return false;
1008 }
1009 }
1010 } else {
1011 DoActionNoJs(action, type);
1012 }
1013
1014 for (size_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
1015 CPDF_Action subaction = action.GetSubAction(i);
1016 if (!ExecuteFieldAction(subaction, type, pFormField, data, visited))
1017 return false;
1018 }
1019
1020 return true;
1021}
1022
1023void CPDFSDK_FormFillEnvironment::DoActionNoJs(const CPDF_Action& action,
1024 CPDF_AAction::AActionType type) {
1025 switch (action.GetType()) {
1026 case CPDF_Action::Type::kGoTo:
1027 DoActionGoTo(action);
1028 break;
1029 case CPDF_Action::Type::kURI:
1030 if (CPDF_AAction::IsUserInput(type))
1031 DoActionURI(action, Mask<FWL_EVENTFLAG>{});
1032 break;
1033 case CPDF_Action::Type::kHide:
1034 DoActionHide(action);
1035 break;
1036 case CPDF_Action::Type::kNamed:
1037 DoActionNamed(action);
1038 break;
1039 case CPDF_Action::Type::kSubmitForm:
1040 if (CPDF_AAction::IsUserInput(type))
1041 DoActionSubmitForm(action);
1042 break;
1043 case CPDF_Action::Type::kResetForm:
1044 DoActionResetForm(action);
1045 break;
1046 case CPDF_Action::Type::kJavaScript:
Peter Boström75a7c4d2024-11-12 02:14:47 +00001047 NOTREACHED();
Tom Sepez946bf0f2022-04-08 22:06:41 +00001048 case CPDF_Action::Type::kSetOCGState:
1049 case CPDF_Action::Type::kThread:
1050 case CPDF_Action::Type::kSound:
1051 case CPDF_Action::Type::kMovie:
1052 case CPDF_Action::Type::kRendition:
1053 case CPDF_Action::Type::kTrans:
1054 case CPDF_Action::Type::kGoTo3DView:
1055 case CPDF_Action::Type::kGoToR:
1056 case CPDF_Action::Type::kGoToE:
1057 case CPDF_Action::Type::kLaunch:
1058 case CPDF_Action::Type::kImportData:
1059 // Unimplemented
1060 break;
1061 default:
1062 break;
1063 }
1064}
1065
1066void CPDFSDK_FormFillEnvironment::DoActionGoTo(const CPDF_Action& action) {
1067 DCHECK(action.GetDict());
1068
1069 CPDF_Document* pPDFDocument = GetPDFDocument();
1070 DCHECK(pPDFDocument);
1071
1072 CPDF_Dest MyDest = action.GetDest(pPDFDocument);
1073 DoActionDestination(MyDest);
1074}
1075
1076void CPDFSDK_FormFillEnvironment::DoActionURI(const CPDF_Action& action,
1077 Mask<FWL_EVENTFLAG> modifiers) {
1078 DCHECK(action.GetDict());
1079 DoURIAction(action.GetURI(GetPDFDocument()), modifiers);
1080}
1081
1082void CPDFSDK_FormFillEnvironment::DoActionNamed(const CPDF_Action& action) {
1083 DCHECK(action.GetDict());
1084 ExecuteNamedAction(action.GetNamedAction());
1085}
1086
1087void CPDFSDK_FormFillEnvironment::RunFieldJavaScript(
1088 CPDF_FormField* pFormField,
1089 CPDF_AAction::AActionType type,
1090 CFFL_FieldAction* data,
1091 const WideString& script) {
1092 DCHECK(type != CPDF_AAction::kCalculate);
1093 DCHECK(type != CPDF_AAction::kFormat);
1094
1095 RunScript(script, [type, data, pFormField](IJS_EventContext* context) {
1096 switch (type) {
1097 case CPDF_AAction::kCursorEnter:
1098 context->OnField_MouseEnter(data->bModifier, data->bShift, pFormField);
1099 break;
1100 case CPDF_AAction::kCursorExit:
1101 context->OnField_MouseExit(data->bModifier, data->bShift, pFormField);
1102 break;
1103 case CPDF_AAction::kButtonDown:
1104 context->OnField_MouseDown(data->bModifier, data->bShift, pFormField);
1105 break;
1106 case CPDF_AAction::kButtonUp:
1107 context->OnField_MouseUp(data->bModifier, data->bShift, pFormField);
1108 break;
1109 case CPDF_AAction::kGetFocus:
1110 context->OnField_Focus(data->bModifier, data->bShift, pFormField,
1111 &data->sValue);
1112 break;
1113 case CPDF_AAction::kLoseFocus:
1114 context->OnField_Blur(data->bModifier, data->bShift, pFormField,
1115 &data->sValue);
1116 break;
1117 case CPDF_AAction::kKeyStroke:
1118 context->OnField_Keystroke(
1119 &data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier,
1120 &data->nSelEnd, &data->nSelStart, data->bShift, pFormField,
1121 &data->sValue, data->bWillCommit, data->bFieldFull, &data->bRC);
1122 break;
1123 case CPDF_AAction::kValidate:
1124 context->OnField_Validate(&data->sChange, data->sChangeEx,
1125 data->bKeyDown, data->bModifier, data->bShift,
1126 pFormField, &data->sValue, &data->bRC);
1127 break;
1128 default:
Peter Boström75a7c4d2024-11-12 02:14:47 +00001129 NOTREACHED();
Tom Sepez946bf0f2022-04-08 22:06:41 +00001130 }
1131 });
1132}
1133
1134void CPDFSDK_FormFillEnvironment::RunDocumentOpenJavaScript(
1135 const WideString& sScriptName,
1136 const WideString& script) {
1137 RunScript(script, [sScriptName](IJS_EventContext* context) {
1138 context->OnDoc_Open(sScriptName);
1139 });
1140}
1141
1142void CPDFSDK_FormFillEnvironment::RunDocumentPageJavaScript(
1143 CPDF_AAction::AActionType type,
1144 const WideString& script) {
1145 RunScript(script, [type](IJS_EventContext* context) {
1146 switch (type) {
1147 case CPDF_AAction::kOpenPage:
1148 context->OnPage_Open();
1149 break;
1150 case CPDF_AAction::kClosePage:
1151 context->OnPage_Close();
1152 break;
1153 case CPDF_AAction::kCloseDocument:
1154 context->OnDoc_WillClose();
1155 break;
1156 case CPDF_AAction::kSaveDocument:
1157 context->OnDoc_WillSave();
1158 break;
1159 case CPDF_AAction::kDocumentSaved:
1160 context->OnDoc_DidSave();
1161 break;
1162 case CPDF_AAction::kPrintDocument:
1163 context->OnDoc_WillPrint();
1164 break;
1165 case CPDF_AAction::kDocumentPrinted:
1166 context->OnDoc_DidPrint();
1167 break;
1168 case CPDF_AAction::kPageVisible:
1169 context->OnPage_InView();
1170 break;
1171 case CPDF_AAction::kPageInvisible:
1172 context->OnPage_OutView();
1173 break;
1174 default:
Peter Boström75a7c4d2024-11-12 02:14:47 +00001175 NOTREACHED();
Tom Sepez946bf0f2022-04-08 22:06:41 +00001176 }
1177 });
1178}
1179
1180bool CPDFSDK_FormFillEnvironment::DoActionHide(const CPDF_Action& action) {
1181 CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1182 if (pForm->DoAction_Hide(action)) {
1183 SetChangeMark();
1184 return true;
1185 }
1186 return false;
1187}
1188
1189bool CPDFSDK_FormFillEnvironment::DoActionSubmitForm(
1190 const CPDF_Action& action) {
1191 CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1192 return pForm->DoAction_SubmitForm(action);
1193}
1194
1195void CPDFSDK_FormFillEnvironment::DoActionResetForm(const CPDF_Action& action) {
1196 CPDFSDK_InteractiveForm* pForm = GetInteractiveForm();
1197 pForm->DoAction_ResetForm(action);
1198}
1199
1200void CPDFSDK_FormFillEnvironment::RunScript(const WideString& script,
1201 const RunScriptCallback& cb) {
1202 IJS_Runtime::ScopedEventContext pContext(GetIJSRuntime());
1203 cb(pContext.Get());
1204 pContext->RunScript(script);
1205 // TODO(dsinclair): Return error if RunScript returns a IJS_Runtime::JS_Error.
1206}