• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 PDFium Authors. All rights reserved.
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 "fxjs/cjs_document.h"
8 
9 #include <utility>
10 
11 #include "core/fpdfapi/page/cpdf_pageobject.h"
12 #include "core/fpdfapi/page/cpdf_textobject.h"
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fpdfapi/parser/cpdf_name.h"
16 #include "core/fpdfapi/parser/cpdf_string.h"
17 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
18 #include "core/fpdfdoc/cpdf_interactiveform.h"
19 #include "core/fpdfdoc/cpdf_nametree.h"
20 #include "fpdfsdk/cpdfsdk_annotiteration.h"
21 #include "fpdfsdk/cpdfsdk_interactiveform.h"
22 #include "fpdfsdk/cpdfsdk_pageview.h"
23 #include "fxjs/cjs_annot.h"
24 #include "fxjs/cjs_app.h"
25 #include "fxjs/cjs_delaydata.h"
26 #include "fxjs/cjs_event_context.h"
27 #include "fxjs/cjs_field.h"
28 #include "fxjs/cjs_icon.h"
29 #include "fxjs/js_resources.h"
30 
31 const JSPropertySpec CJS_Document::PropertySpecs[] = {
32     {"ADBE", get_ADBE_static, set_ADBE_static},
33     {"author", get_author_static, set_author_static},
34     {"baseURL", get_base_URL_static, set_base_URL_static},
35     {"bookmarkRoot", get_bookmark_root_static, set_bookmark_root_static},
36     {"calculate", get_calculate_static, set_calculate_static},
37     {"Collab", get_collab_static, set_collab_static},
38     {"creationDate", get_creation_date_static, set_creation_date_static},
39     {"creator", get_creator_static, set_creator_static},
40     {"delay", get_delay_static, set_delay_static},
41     {"dirty", get_dirty_static, set_dirty_static},
42     {"documentFileName", get_document_file_name_static,
43      set_document_file_name_static},
44     {"external", get_external_static, set_external_static},
45     {"filesize", get_filesize_static, set_filesize_static},
46     {"icons", get_icons_static, set_icons_static},
47     {"info", get_info_static, set_info_static},
48     {"keywords", get_keywords_static, set_keywords_static},
49     {"layout", get_layout_static, set_layout_static},
50     {"media", get_media_static, set_media_static},
51     {"modDate", get_mod_date_static, set_mod_date_static},
52     {"mouseX", get_mouse_x_static, set_mouse_x_static},
53     {"mouseY", get_mouse_y_static, set_mouse_y_static},
54     {"numFields", get_num_fields_static, set_num_fields_static},
55     {"numPages", get_num_pages_static, set_num_pages_static},
56     {"pageNum", get_page_num_static, set_page_num_static},
57     {"pageWindowRect", get_page_window_rect_static,
58      set_page_window_rect_static},
59     {"path", get_path_static, set_path_static},
60     {"producer", get_producer_static, set_producer_static},
61     {"subject", get_subject_static, set_subject_static},
62     {"title", get_title_static, set_title_static},
63     {"URL", get_URL_static, set_URL_static},
64     {"zoom", get_zoom_static, set_zoom_static},
65     {"zoomType", get_zoom_type_static, set_zoom_type_static}};
66 
67 const JSMethodSpec CJS_Document::MethodSpecs[] = {
68     {"addAnnot", addAnnot_static},
69     {"addField", addField_static},
70     {"addLink", addLink_static},
71     {"addIcon", addIcon_static},
72     {"calculateNow", calculateNow_static},
73     {"closeDoc", closeDoc_static},
74     {"createDataObject", createDataObject_static},
75     {"deletePages", deletePages_static},
76     {"exportAsText", exportAsText_static},
77     {"exportAsFDF", exportAsFDF_static},
78     {"exportAsXFDF", exportAsXFDF_static},
79     {"extractPages", extractPages_static},
80     {"getAnnot", getAnnot_static},
81     {"getAnnots", getAnnots_static},
82     {"getAnnot3D", getAnnot3D_static},
83     {"getAnnots3D", getAnnots3D_static},
84     {"getField", getField_static},
85     {"getIcon", getIcon_static},
86     {"getLinks", getLinks_static},
87     {"getNthFieldName", getNthFieldName_static},
88     {"getOCGs", getOCGs_static},
89     {"getPageBox", getPageBox_static},
90     {"getPageNthWord", getPageNthWord_static},
91     {"getPageNthWordQuads", getPageNthWordQuads_static},
92     {"getPageNumWords", getPageNumWords_static},
93     {"getPrintParams", getPrintParams_static},
94     {"getURL", getURL_static},
95     {"gotoNamedDest", gotoNamedDest_static},
96     {"importAnFDF", importAnFDF_static},
97     {"importAnXFDF", importAnXFDF_static},
98     {"importTextData", importTextData_static},
99     {"insertPages", insertPages_static},
100     {"mailDoc", mailDoc_static},
101     {"mailForm", mailForm_static},
102     {"print", print_static},
103     {"removeField", removeField_static},
104     {"replacePages", replacePages_static},
105     {"resetForm", resetForm_static},
106     {"removeIcon", removeIcon_static},
107     {"saveAs", saveAs_static},
108     {"submitForm", submitForm_static},
109     {"syncAnnotScan", syncAnnotScan_static}};
110 
111 int CJS_Document::ObjDefnID = -1;
112 const char CJS_Document::kName[] = "Document";
113 
114 // static
GetObjDefnID()115 int CJS_Document::GetObjDefnID() {
116   return ObjDefnID;
117 }
118 
119 // static
DefineJSObjects(CFXJS_Engine * pEngine)120 void CJS_Document::DefineJSObjects(CFXJS_Engine* pEngine) {
121   ObjDefnID = pEngine->DefineObj(CJS_Document::kName, FXJSOBJTYPE_GLOBAL,
122                                  JSConstructor<CJS_Document>, JSDestructor);
123   DefineProps(pEngine, ObjDefnID, PropertySpecs);
124   DefineMethods(pEngine, ObjDefnID, MethodSpecs);
125 }
126 
CJS_Document(v8::Local<v8::Object> pObject,CJS_Runtime * pRuntime)127 CJS_Document::CJS_Document(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
128     : CJS_Object(pObject, pRuntime) {
129   SetFormFillEnv(GetRuntime()->GetFormFillEnv());
130 }
131 
132 CJS_Document::~CJS_Document() = default;
133 
134 // The total number of fields in document.
get_num_fields(CJS_Runtime * pRuntime)135 CJS_Result CJS_Document::get_num_fields(CJS_Runtime* pRuntime) {
136   if (!m_pFormFillEnv)
137     return CJS_Result::Failure(JSMessage::kBadObjectError);
138 
139   CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm();
140   return CJS_Result::Success(pRuntime->NewNumber(
141       static_cast<int>(pPDFForm->CountFields(WideString()))));
142 }
143 
set_num_fields(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)144 CJS_Result CJS_Document::set_num_fields(CJS_Runtime* pRuntime,
145                                         v8::Local<v8::Value> vp) {
146   return CJS_Result::Failure(JSMessage::kReadOnlyError);
147 }
148 
get_dirty(CJS_Runtime * pRuntime)149 CJS_Result CJS_Document::get_dirty(CJS_Runtime* pRuntime) {
150   if (!m_pFormFillEnv)
151     return CJS_Result::Failure(JSMessage::kBadObjectError);
152 
153   return CJS_Result::Success(
154       pRuntime->NewBoolean(!!m_pFormFillEnv->GetChangeMark()));
155 }
156 
set_dirty(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)157 CJS_Result CJS_Document::set_dirty(CJS_Runtime* pRuntime,
158                                    v8::Local<v8::Value> vp) {
159   if (!m_pFormFillEnv)
160     return CJS_Result::Failure(JSMessage::kBadObjectError);
161 
162   pRuntime->ToBoolean(vp) ? m_pFormFillEnv->SetChangeMark()
163                           : m_pFormFillEnv->ClearChangeMark();
164   return CJS_Result::Success();
165 }
166 
get_ADBE(CJS_Runtime * pRuntime)167 CJS_Result CJS_Document::get_ADBE(CJS_Runtime* pRuntime) {
168   return CJS_Result::Success(pRuntime->NewUndefined());
169 }
170 
set_ADBE(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)171 CJS_Result CJS_Document::set_ADBE(CJS_Runtime* pRuntime,
172                                   v8::Local<v8::Value> vp) {
173   return CJS_Result::Success();
174 }
175 
get_page_num(CJS_Runtime * pRuntime)176 CJS_Result CJS_Document::get_page_num(CJS_Runtime* pRuntime) {
177   if (!m_pFormFillEnv)
178     return CJS_Result::Failure(JSMessage::kBadObjectError);
179 
180   CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetCurrentView();
181   if (!pPageView)
182     return CJS_Result::Success(pRuntime->NewUndefined());
183 
184   return CJS_Result::Success(pRuntime->NewNumber(pPageView->GetPageIndex()));
185 }
186 
set_page_num(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)187 CJS_Result CJS_Document::set_page_num(CJS_Runtime* pRuntime,
188                                       v8::Local<v8::Value> vp) {
189   if (!m_pFormFillEnv)
190     return CJS_Result::Failure(JSMessage::kBadObjectError);
191 
192   int iPageCount = m_pFormFillEnv->GetPageCount();
193   int iPageNum = pRuntime->ToInt32(vp);
194   if (iPageNum >= 0 && iPageNum < iPageCount)
195     m_pFormFillEnv->JS_docgotoPage(iPageNum);
196   else if (iPageNum >= iPageCount)
197     m_pFormFillEnv->JS_docgotoPage(iPageCount - 1);
198   else if (iPageNum < 0)
199     m_pFormFillEnv->JS_docgotoPage(0);
200 
201   return CJS_Result::Success();
202 }
203 
addAnnot(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)204 CJS_Result CJS_Document::addAnnot(
205     CJS_Runtime* pRuntime,
206     const std::vector<v8::Local<v8::Value>>& params) {
207   // Not supported, but do not return an error.
208   return CJS_Result::Success();
209 }
210 
addField(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)211 CJS_Result CJS_Document::addField(
212     CJS_Runtime* pRuntime,
213     const std::vector<v8::Local<v8::Value>>& params) {
214   // Not supported, but do not return an error.
215   return CJS_Result::Success();
216 }
217 
exportAsText(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)218 CJS_Result CJS_Document::exportAsText(
219     CJS_Runtime* pRuntime,
220     const std::vector<v8::Local<v8::Value>>& params) {
221   // Unsafe, not supported, but do not return an error.
222   return CJS_Result::Success();
223 }
224 
exportAsFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)225 CJS_Result CJS_Document::exportAsFDF(
226     CJS_Runtime* pRuntime,
227     const std::vector<v8::Local<v8::Value>>& params) {
228   // Unsafe, not supported, but do not return an error.
229   return CJS_Result::Success();
230 }
231 
exportAsXFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)232 CJS_Result CJS_Document::exportAsXFDF(
233     CJS_Runtime* pRuntime,
234     const std::vector<v8::Local<v8::Value>>& params) {
235   // Unsafe, not supported, but do not return an error.
236   return CJS_Result::Success();
237 }
238 
getField(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)239 CJS_Result CJS_Document::getField(
240     CJS_Runtime* pRuntime,
241     const std::vector<v8::Local<v8::Value>>& params) {
242   if (params.empty())
243     return CJS_Result::Failure(JSMessage::kParamError);
244 
245   if (!m_pFormFillEnv)
246     return CJS_Result::Failure(JSMessage::kBadObjectError);
247 
248   WideString wideName = pRuntime->ToWideString(params[0]);
249   CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm();
250   if (pPDFForm->CountFields(wideName) <= 0)
251     return CJS_Result::Success(pRuntime->NewUndefined());
252 
253   v8::Local<v8::Object> pFieldObj = pRuntime->NewFXJSBoundObject(
254       CJS_Field::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
255   if (pFieldObj.IsEmpty())
256     return CJS_Result::Failure(JSMessage::kBadObjectError);
257 
258   auto* pJSField =
259       static_cast<CJS_Field*>(CFXJS_Engine::GetObjectPrivate(pFieldObj));
260   if (!pJSField)
261     return CJS_Result::Failure(JSMessage::kBadObjectError);
262 
263   pJSField->AttachField(this, wideName);
264   return CJS_Result::Success(pJSField->ToV8Object());
265 }
266 
267 // Gets the name of the nth field in the document
getNthFieldName(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)268 CJS_Result CJS_Document::getNthFieldName(
269     CJS_Runtime* pRuntime,
270     const std::vector<v8::Local<v8::Value>>& params) {
271   if (params.size() != 1)
272     return CJS_Result::Failure(JSMessage::kParamError);
273   if (!m_pFormFillEnv)
274     return CJS_Result::Failure(JSMessage::kBadObjectError);
275 
276   int nIndex = pRuntime->ToInt32(params[0]);
277   if (nIndex < 0)
278     return CJS_Result::Failure(JSMessage::kValueError);
279 
280   CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm();
281   CPDF_FormField* pField = pPDFForm->GetField(nIndex, WideString());
282   if (!pField)
283     return CJS_Result::Failure(JSMessage::kBadObjectError);
284   return CJS_Result::Success(
285       pRuntime->NewString(pField->GetFullName().AsStringView()));
286 }
287 
importAnFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)288 CJS_Result CJS_Document::importAnFDF(
289     CJS_Runtime* pRuntime,
290     const std::vector<v8::Local<v8::Value>>& params) {
291   // Unsafe, not supported.
292   return CJS_Result::Success();
293 }
294 
importAnXFDF(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)295 CJS_Result CJS_Document::importAnXFDF(
296     CJS_Runtime* pRuntime,
297     const std::vector<v8::Local<v8::Value>>& params) {
298   // Unsafe, not supported.
299   return CJS_Result::Success();
300 }
301 
importTextData(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)302 CJS_Result CJS_Document::importTextData(
303     CJS_Runtime* pRuntime,
304     const std::vector<v8::Local<v8::Value>>& params) {
305   // Unsafe, not supported.
306   return CJS_Result::Success();
307 }
308 
mailDoc(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)309 CJS_Result CJS_Document::mailDoc(
310     CJS_Runtime* pRuntime,
311     const std::vector<v8::Local<v8::Value>>& params) {
312   if (!m_pFormFillEnv)
313     return CJS_Result::Failure(JSMessage::kBadObjectError);
314 
315   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
316       pRuntime, params, 6, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMsg");
317 
318   bool bUI = true;
319   if (IsExpandedParamKnown(newParams[0]))
320     bUI = pRuntime->ToBoolean(newParams[0]);
321 
322   WideString cTo;
323   if (IsExpandedParamKnown(newParams[1]))
324     cTo = pRuntime->ToWideString(newParams[1]);
325 
326   WideString cCc;
327   if (IsExpandedParamKnown(newParams[2]))
328     cCc = pRuntime->ToWideString(newParams[2]);
329 
330   WideString cBcc;
331   if (IsExpandedParamKnown(newParams[3]))
332     cBcc = pRuntime->ToWideString(newParams[3]);
333 
334   WideString cSubject;
335   if (IsExpandedParamKnown(newParams[4]))
336     cSubject = pRuntime->ToWideString(newParams[4]);
337 
338   WideString cMsg;
339   if (IsExpandedParamKnown(newParams[5]))
340     cMsg = pRuntime->ToWideString(newParams[5]);
341 
342   pRuntime->BeginBlock();
343   m_pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo, cSubject, cCc, cBcc,
344                                  cMsg);
345   pRuntime->EndBlock();
346   return CJS_Result::Success();
347 }
348 
349 // exports the form data and mails the resulting fdf file as an attachment to
350 // all recipients.
351 // comment: need reader supports
mailForm(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)352 CJS_Result CJS_Document::mailForm(
353     CJS_Runtime* pRuntime,
354     const std::vector<v8::Local<v8::Value>>& params) {
355   if (!m_pFormFillEnv)
356     return CJS_Result::Failure(JSMessage::kBadObjectError);
357   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
358     return CJS_Result::Failure(JSMessage::kPermissionError);
359 
360   CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm();
361   ByteString sTextBuf = pInteractiveForm->ExportFormToFDFTextBuf();
362   if (sTextBuf.IsEmpty())
363     return CJS_Result::Failure(L"Bad FDF format.");
364 
365   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
366       pRuntime, params, 6, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMsg");
367 
368   bool bUI = true;
369   if (IsExpandedParamKnown(newParams[0]))
370     bUI = pRuntime->ToBoolean(newParams[0]);
371 
372   WideString cTo;
373   if (IsExpandedParamKnown(newParams[1]))
374     cTo = pRuntime->ToWideString(newParams[1]);
375 
376   WideString cCc;
377   if (IsExpandedParamKnown(newParams[2]))
378     cCc = pRuntime->ToWideString(newParams[2]);
379 
380   WideString cBcc;
381   if (IsExpandedParamKnown(newParams[3]))
382     cBcc = pRuntime->ToWideString(newParams[3]);
383 
384   WideString cSubject;
385   if (IsExpandedParamKnown(newParams[4]))
386     cSubject = pRuntime->ToWideString(newParams[4]);
387 
388   WideString cMsg;
389   if (IsExpandedParamKnown(newParams[5]))
390     cMsg = pRuntime->ToWideString(newParams[5]);
391 
392   std::vector<char> mutable_buf(sTextBuf.begin(), sTextBuf.end());
393   pRuntime->BeginBlock();
394   m_pFormFillEnv->JS_docmailForm(mutable_buf.data(), mutable_buf.size(), bUI,
395                                  cTo, cSubject, cCc, cBcc, cMsg);
396   pRuntime->EndBlock();
397   return CJS_Result::Success();
398 }
399 
print(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)400 CJS_Result CJS_Document::print(
401     CJS_Runtime* pRuntime,
402     const std::vector<v8::Local<v8::Value>>& params) {
403   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
404       pRuntime, params, 8, "bUI", "nStart", "nEnd", "bSilent", "bShrinkToFit",
405       "bPrintAsImage", "bReverse", "bAnnotations");
406 
407   bool bUI = true;
408   if (IsExpandedParamKnown(newParams[0]))
409     bUI = pRuntime->ToBoolean(newParams[0]);
410 
411   int nStart = 0;
412   if (IsExpandedParamKnown(newParams[1]))
413     nStart = pRuntime->ToInt32(newParams[1]);
414 
415   int nEnd = 0;
416   if (IsExpandedParamKnown(newParams[2]))
417     nEnd = pRuntime->ToInt32(newParams[2]);
418 
419   bool bSilent = false;
420   if (IsExpandedParamKnown(newParams[3]))
421     bSilent = pRuntime->ToBoolean(newParams[3]);
422 
423   bool bShrinkToFit = false;
424   if (IsExpandedParamKnown(newParams[4]))
425     bShrinkToFit = pRuntime->ToBoolean(newParams[4]);
426 
427   bool bPrintAsImage = false;
428   if (IsExpandedParamKnown(newParams[5]))
429     bPrintAsImage = pRuntime->ToBoolean(newParams[5]);
430 
431   bool bReverse = false;
432   if (IsExpandedParamKnown(newParams[6]))
433     bReverse = pRuntime->ToBoolean(newParams[6]);
434 
435   bool bAnnotations = false;
436   if (IsExpandedParamKnown(newParams[7]))
437     bAnnotations = pRuntime->ToBoolean(newParams[7]);
438 
439   if (!m_pFormFillEnv)
440     return CJS_Result::Failure(JSMessage::kBadObjectError);
441 
442   CJS_EventRecorder* pHandler =
443       pRuntime->GetCurrentEventContext()->GetEventRecorder();
444   if (!pHandler->IsUserGesture())
445     return CJS_Result::Failure(JSMessage::kUserGestureRequiredError);
446 
447   m_pFormFillEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit,
448                               bPrintAsImage, bReverse, bAnnotations);
449   return CJS_Result::Success();
450 }
451 
452 // removes the specified field from the document.
453 // comment:
454 // note: if the filed name is not rational, adobe is dumb for it.
removeField(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)455 CJS_Result CJS_Document::removeField(
456     CJS_Runtime* pRuntime,
457     const std::vector<v8::Local<v8::Value>>& params) {
458   if (params.size() != 1)
459     return CJS_Result::Failure(JSMessage::kParamError);
460   if (!m_pFormFillEnv)
461     return CJS_Result::Failure(JSMessage::kBadObjectError);
462 
463   if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
464         m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM))) {
465     return CJS_Result::Failure(JSMessage::kPermissionError);
466   }
467 
468   WideString sFieldName = pRuntime->ToWideString(params[0]);
469   CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm();
470   std::vector<ObservedPtr<CPDFSDK_Annot>> widgets;
471   pInteractiveForm->GetWidgets(sFieldName, &widgets);
472   if (widgets.empty())
473     return CJS_Result::Success();
474 
475   for (const auto& pAnnot : widgets) {
476     CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot.Get());
477     if (!pWidget)
478       continue;
479 
480     IPDF_Page* pPage = pWidget->GetPage();
481     ASSERT(pPage);
482 
483     // If there is currently no pageview associated with the page being used
484     // do not create one. We may be in the process of tearing down the document
485     // and creating a new pageview at this point will cause bad things.
486     CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, false);
487     if (!pPageView)
488       continue;
489 
490     CFX_FloatRect rcAnnot = pWidget->GetRect();
491     rcAnnot.Inflate(1.0f, 1.0f, 1.0f, 1.0f);
492 
493     std::vector<CFX_FloatRect> aRefresh(1, rcAnnot);
494     pPageView->UpdateRects(aRefresh);
495   }
496   m_pFormFillEnv->SetChangeMark();
497   return CJS_Result::Success();
498 }
499 
500 // reset filed values within a document.
501 // comment:
502 // note: if the fields names r not rational, aodbe is dumb for it.
503 
resetForm(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)504 CJS_Result CJS_Document::resetForm(
505     CJS_Runtime* pRuntime,
506     const std::vector<v8::Local<v8::Value>>& params) {
507   if (!m_pFormFillEnv)
508     return CJS_Result::Failure(JSMessage::kBadObjectError);
509   if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
510         m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
511         m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) {
512     return CJS_Result::Failure(JSMessage::kPermissionError);
513   }
514 
515   CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm();
516   if (params.empty()) {
517     pPDFForm->ResetForm(NotificationOption::kNotify);
518     m_pFormFillEnv->SetChangeMark();
519     return CJS_Result::Success();
520   }
521 
522   v8::Local<v8::Array> array;
523   if (params[0]->IsString()) {
524     array = pRuntime->NewArray();
525     pRuntime->PutArrayElement(array, 0, params[0]);
526   } else {
527     array = pRuntime->ToArray(params[0]);
528   }
529 
530   std::vector<CPDF_FormField*> aFields;
531   for (size_t i = 0; i < pRuntime->GetArrayLength(array); ++i) {
532     WideString swVal =
533         pRuntime->ToWideString(pRuntime->GetArrayElement(array, i));
534     for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; ++j)
535       aFields.push_back(pPDFForm->GetField(j, swVal));
536   }
537 
538   if (!aFields.empty()) {
539     pPDFForm->ResetForm(aFields, true, NotificationOption::kNotify);
540     m_pFormFillEnv->SetChangeMark();
541   }
542 
543   return CJS_Result::Success();
544 }
545 
saveAs(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)546 CJS_Result CJS_Document::saveAs(
547     CJS_Runtime* pRuntime,
548     const std::vector<v8::Local<v8::Value>>& params) {
549   // Unsafe, not supported.
550   return CJS_Result::Success();
551 }
552 
syncAnnotScan(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)553 CJS_Result CJS_Document::syncAnnotScan(
554     CJS_Runtime* pRuntime,
555     const std::vector<v8::Local<v8::Value>>& params) {
556   return CJS_Result::Success();
557 }
558 
submitForm(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)559 CJS_Result CJS_Document::submitForm(
560     CJS_Runtime* pRuntime,
561     const std::vector<v8::Local<v8::Value>>& params) {
562   size_t nSize = params.size();
563   if (nSize < 1)
564     return CJS_Result::Failure(JSMessage::kParamError);
565   if (!m_pFormFillEnv)
566     return CJS_Result::Failure(JSMessage::kBadObjectError);
567 
568   CJS_EventRecorder* pHandler =
569       pRuntime->GetCurrentEventContext()->GetEventRecorder();
570   if (!pHandler->IsUserGesture())
571     return CJS_Result::Failure(JSMessage::kUserGestureRequiredError);
572 
573   v8::Local<v8::Array> aFields;
574   WideString strURL;
575   bool bFDF = true;
576   bool bEmpty = false;
577   if (params[0]->IsString()) {
578     strURL = pRuntime->ToWideString(params[0]);
579     if (nSize > 1)
580       bFDF = pRuntime->ToBoolean(params[1]);
581     if (nSize > 2)
582       bEmpty = pRuntime->ToBoolean(params[2]);
583     if (nSize > 3)
584       aFields = pRuntime->ToArray(params[3]);
585   } else if (params[0]->IsObject()) {
586     v8::Local<v8::Object> pObj = pRuntime->ToObject(params[0]);
587     v8::Local<v8::Value> pValue = pRuntime->GetObjectProperty(pObj, "cURL");
588     if (!pValue.IsEmpty())
589       strURL = pRuntime->ToWideString(pValue);
590 
591     bFDF = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, "bFDF"));
592     bEmpty = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, "bEmpty"));
593     aFields = pRuntime->ToArray(pRuntime->GetObjectProperty(pObj, "aFields"));
594   }
595 
596   CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm();
597   if (pRuntime->GetArrayLength(aFields) == 0 && bEmpty) {
598     if (pPDFForm->CheckRequiredFields(nullptr, true)) {
599       pRuntime->BeginBlock();
600       GetSDKInteractiveForm()->SubmitForm(strURL, false);
601       pRuntime->EndBlock();
602     }
603     return CJS_Result::Success();
604   }
605 
606   std::vector<CPDF_FormField*> fieldObjects;
607   for (size_t i = 0; i < pRuntime->GetArrayLength(aFields); ++i) {
608     WideString sName =
609         pRuntime->ToWideString(pRuntime->GetArrayElement(aFields, i));
610     for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) {
611       CPDF_FormField* pField = pPDFForm->GetField(j, sName);
612       if (!bEmpty && pField->GetValue().IsEmpty())
613         continue;
614 
615       fieldObjects.push_back(pField);
616     }
617   }
618 
619   if (pPDFForm->CheckRequiredFields(&fieldObjects, true)) {
620     pRuntime->BeginBlock();
621     GetSDKInteractiveForm()->SubmitFields(strURL, fieldObjects, true, !bFDF);
622     pRuntime->EndBlock();
623   }
624   return CJS_Result::Success();
625 }
626 
SetFormFillEnv(CPDFSDK_FormFillEnvironment * pFormFillEnv)627 void CJS_Document::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
628   m_pFormFillEnv.Reset(pFormFillEnv);
629 }
630 
get_bookmark_root(CJS_Runtime * pRuntime)631 CJS_Result CJS_Document::get_bookmark_root(CJS_Runtime* pRuntime) {
632   return CJS_Result::Success();
633 }
634 
set_bookmark_root(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)635 CJS_Result CJS_Document::set_bookmark_root(CJS_Runtime* pRuntime,
636                                            v8::Local<v8::Value> vp) {
637   return CJS_Result::Success();
638 }
639 
get_author(CJS_Runtime * pRuntime)640 CJS_Result CJS_Document::get_author(CJS_Runtime* pRuntime) {
641   return getPropertyInternal(pRuntime, "Author");
642 }
643 
set_author(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)644 CJS_Result CJS_Document::set_author(CJS_Runtime* pRuntime,
645                                     v8::Local<v8::Value> vp) {
646   return setPropertyInternal(pRuntime, vp, "Author");
647 }
648 
get_info(CJS_Runtime * pRuntime)649 CJS_Result CJS_Document::get_info(CJS_Runtime* pRuntime) {
650   if (!m_pFormFillEnv)
651     return CJS_Result::Failure(JSMessage::kBadObjectError);
652 
653   const auto* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo();
654   if (!pDictionary)
655     return CJS_Result::Failure(JSMessage::kBadObjectError);
656 
657   WideString cwAuthor = pDictionary->GetUnicodeTextFor("Author");
658   WideString cwTitle = pDictionary->GetUnicodeTextFor("Title");
659   WideString cwSubject = pDictionary->GetUnicodeTextFor("Subject");
660   WideString cwKeywords = pDictionary->GetUnicodeTextFor("Keywords");
661   WideString cwCreator = pDictionary->GetUnicodeTextFor("Creator");
662   WideString cwProducer = pDictionary->GetUnicodeTextFor("Producer");
663   WideString cwCreationDate = pDictionary->GetUnicodeTextFor("CreationDate");
664   WideString cwModDate = pDictionary->GetUnicodeTextFor("ModDate");
665   WideString cwTrapped = pDictionary->GetUnicodeTextFor("Trapped");
666 
667   v8::Local<v8::Object> pObj = pRuntime->NewObject();
668   pRuntime->PutObjectProperty(pObj, "Author",
669                               pRuntime->NewString(cwAuthor.AsStringView()));
670   pRuntime->PutObjectProperty(pObj, "Title",
671                               pRuntime->NewString(cwTitle.AsStringView()));
672   pRuntime->PutObjectProperty(pObj, "Subject",
673                               pRuntime->NewString(cwSubject.AsStringView()));
674   pRuntime->PutObjectProperty(pObj, "Keywords",
675                               pRuntime->NewString(cwKeywords.AsStringView()));
676   pRuntime->PutObjectProperty(pObj, "Creator",
677                               pRuntime->NewString(cwCreator.AsStringView()));
678   pRuntime->PutObjectProperty(pObj, "Producer",
679                               pRuntime->NewString(cwProducer.AsStringView()));
680   pRuntime->PutObjectProperty(
681       pObj, "CreationDate", pRuntime->NewString(cwCreationDate.AsStringView()));
682   pRuntime->PutObjectProperty(pObj, "ModDate",
683                               pRuntime->NewString(cwModDate.AsStringView()));
684   pRuntime->PutObjectProperty(pObj, "Trapped",
685                               pRuntime->NewString(cwTrapped.AsStringView()));
686 
687   // PutObjectProperty() calls below may re-enter JS and change info dict.
688   auto pCopy = pDictionary->Clone();
689   CPDF_DictionaryLocker locker(ToDictionary(pCopy.Get()));
690   for (const auto& it : locker) {
691     const ByteString& bsKey = it.first;
692     CPDF_Object* pValueObj = it.second.Get();
693     if (pValueObj->IsString() || pValueObj->IsName()) {
694       pRuntime->PutObjectProperty(
695           pObj, bsKey.AsStringView(),
696           pRuntime->NewString(pValueObj->GetUnicodeText().AsStringView()));
697     } else if (pValueObj->IsNumber()) {
698       pRuntime->PutObjectProperty(pObj, bsKey.AsStringView(),
699                                   pRuntime->NewNumber(pValueObj->GetNumber()));
700     } else if (pValueObj->IsBoolean()) {
701       pRuntime->PutObjectProperty(
702           pObj, bsKey.AsStringView(),
703           pRuntime->NewBoolean(!!pValueObj->GetInteger()));
704     }
705   }
706   return CJS_Result::Success(pObj);
707 }
708 
set_info(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)709 CJS_Result CJS_Document::set_info(CJS_Runtime* pRuntime,
710                                   v8::Local<v8::Value> vp) {
711   return CJS_Result::Failure(JSMessage::kReadOnlyError);
712 }
713 
getPropertyInternal(CJS_Runtime * pRuntime,const ByteString & propName)714 CJS_Result CJS_Document::getPropertyInternal(CJS_Runtime* pRuntime,
715                                              const ByteString& propName) {
716   if (!m_pFormFillEnv)
717     return CJS_Result::Failure(JSMessage::kBadObjectError);
718 
719   CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo();
720   if (!pDictionary)
721     return CJS_Result::Failure(JSMessage::kBadObjectError);
722   return CJS_Result::Success(pRuntime->NewString(
723       pDictionary->GetUnicodeTextFor(propName).AsStringView()));
724 }
725 
setPropertyInternal(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp,const ByteString & propName)726 CJS_Result CJS_Document::setPropertyInternal(CJS_Runtime* pRuntime,
727                                              v8::Local<v8::Value> vp,
728                                              const ByteString& propName) {
729   if (!m_pFormFillEnv)
730     return CJS_Result::Failure(JSMessage::kBadObjectError);
731 
732   CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo();
733   if (!pDictionary)
734     return CJS_Result::Failure(JSMessage::kBadObjectError);
735 
736   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY))
737     return CJS_Result::Failure(JSMessage::kPermissionError);
738 
739   pDictionary->SetNewFor<CPDF_String>(propName, pRuntime->ToWideString(vp));
740   m_pFormFillEnv->SetChangeMark();
741   return CJS_Result::Success();
742 }
743 
get_creation_date(CJS_Runtime * pRuntime)744 CJS_Result CJS_Document::get_creation_date(CJS_Runtime* pRuntime) {
745   return getPropertyInternal(pRuntime, "CreationDate");
746 }
747 
set_creation_date(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)748 CJS_Result CJS_Document::set_creation_date(CJS_Runtime* pRuntime,
749                                            v8::Local<v8::Value> vp) {
750   return setPropertyInternal(pRuntime, vp, "CreationDate");
751 }
752 
get_creator(CJS_Runtime * pRuntime)753 CJS_Result CJS_Document::get_creator(CJS_Runtime* pRuntime) {
754   return getPropertyInternal(pRuntime, "Creator");
755 }
756 
set_creator(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)757 CJS_Result CJS_Document::set_creator(CJS_Runtime* pRuntime,
758                                      v8::Local<v8::Value> vp) {
759   return setPropertyInternal(pRuntime, vp, "Creator");
760 }
761 
get_delay(CJS_Runtime * pRuntime)762 CJS_Result CJS_Document::get_delay(CJS_Runtime* pRuntime) {
763   if (!m_pFormFillEnv)
764     return CJS_Result::Failure(JSMessage::kBadObjectError);
765   return CJS_Result::Success(pRuntime->NewBoolean(m_bDelay));
766 }
767 
set_delay(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)768 CJS_Result CJS_Document::set_delay(CJS_Runtime* pRuntime,
769                                    v8::Local<v8::Value> vp) {
770   if (!m_pFormFillEnv)
771     return CJS_Result::Failure(JSMessage::kBadObjectError);
772   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY))
773     return CJS_Result::Failure(JSMessage::kPermissionError);
774 
775   m_bDelay = pRuntime->ToBoolean(vp);
776   if (m_bDelay) {
777     m_DelayData.clear();
778     return CJS_Result::Success();
779   }
780 
781   std::list<std::unique_ptr<CJS_DelayData>> DelayDataToProcess;
782   DelayDataToProcess.swap(m_DelayData);
783   for (const auto& pData : DelayDataToProcess)
784     CJS_Field::DoDelay(m_pFormFillEnv.Get(), pData.get());
785 
786   return CJS_Result::Success();
787 }
788 
get_keywords(CJS_Runtime * pRuntime)789 CJS_Result CJS_Document::get_keywords(CJS_Runtime* pRuntime) {
790   return getPropertyInternal(pRuntime, "Keywords");
791 }
792 
set_keywords(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)793 CJS_Result CJS_Document::set_keywords(CJS_Runtime* pRuntime,
794                                       v8::Local<v8::Value> vp) {
795   return setPropertyInternal(pRuntime, vp, "Keywords");
796 }
797 
get_mod_date(CJS_Runtime * pRuntime)798 CJS_Result CJS_Document::get_mod_date(CJS_Runtime* pRuntime) {
799   return getPropertyInternal(pRuntime, "ModDate");
800 }
801 
set_mod_date(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)802 CJS_Result CJS_Document::set_mod_date(CJS_Runtime* pRuntime,
803                                       v8::Local<v8::Value> vp) {
804   return setPropertyInternal(pRuntime, vp, "ModDate");
805 }
806 
get_producer(CJS_Runtime * pRuntime)807 CJS_Result CJS_Document::get_producer(CJS_Runtime* pRuntime) {
808   return getPropertyInternal(pRuntime, "Producer");
809 }
810 
set_producer(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)811 CJS_Result CJS_Document::set_producer(CJS_Runtime* pRuntime,
812                                       v8::Local<v8::Value> vp) {
813   return setPropertyInternal(pRuntime, vp, "Producer");
814 }
815 
get_subject(CJS_Runtime * pRuntime)816 CJS_Result CJS_Document::get_subject(CJS_Runtime* pRuntime) {
817   return getPropertyInternal(pRuntime, "Subject");
818 }
819 
set_subject(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)820 CJS_Result CJS_Document::set_subject(CJS_Runtime* pRuntime,
821                                      v8::Local<v8::Value> vp) {
822   return setPropertyInternal(pRuntime, vp, "Subject");
823 }
824 
get_title(CJS_Runtime * pRuntime)825 CJS_Result CJS_Document::get_title(CJS_Runtime* pRuntime) {
826   if (!m_pFormFillEnv)
827     return CJS_Result::Failure(JSMessage::kBadObjectError);
828   return getPropertyInternal(pRuntime, "Title");
829 }
830 
set_title(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)831 CJS_Result CJS_Document::set_title(CJS_Runtime* pRuntime,
832                                    v8::Local<v8::Value> vp) {
833   if (!m_pFormFillEnv)
834     return CJS_Result::Failure(JSMessage::kBadObjectError);
835   return setPropertyInternal(pRuntime, vp, "Title");
836 }
837 
get_num_pages(CJS_Runtime * pRuntime)838 CJS_Result CJS_Document::get_num_pages(CJS_Runtime* pRuntime) {
839   if (!m_pFormFillEnv)
840     return CJS_Result::Failure(JSMessage::kBadObjectError);
841   return CJS_Result::Success(
842       pRuntime->NewNumber(m_pFormFillEnv->GetPageCount()));
843 }
844 
set_num_pages(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)845 CJS_Result CJS_Document::set_num_pages(CJS_Runtime* pRuntime,
846                                        v8::Local<v8::Value> vp) {
847   return CJS_Result::Failure(JSMessage::kReadOnlyError);
848 }
849 
get_external(CJS_Runtime * pRuntime)850 CJS_Result CJS_Document::get_external(CJS_Runtime* pRuntime) {
851   // In Chrome case, should always return true.
852   return CJS_Result::Success(pRuntime->NewBoolean(true));
853 }
854 
set_external(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)855 CJS_Result CJS_Document::set_external(CJS_Runtime* pRuntime,
856                                       v8::Local<v8::Value> vp) {
857   return CJS_Result::Success();
858 }
859 
get_filesize(CJS_Runtime * pRuntime)860 CJS_Result CJS_Document::get_filesize(CJS_Runtime* pRuntime) {
861   return CJS_Result::Success(pRuntime->NewNumber(0));
862 }
863 
set_filesize(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)864 CJS_Result CJS_Document::set_filesize(CJS_Runtime* pRuntime,
865                                       v8::Local<v8::Value> vp) {
866   return CJS_Result::Failure(JSMessage::kReadOnlyError);
867 }
868 
get_mouse_x(CJS_Runtime * pRuntime)869 CJS_Result CJS_Document::get_mouse_x(CJS_Runtime* pRuntime) {
870   return CJS_Result::Success();
871 }
872 
set_mouse_x(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)873 CJS_Result CJS_Document::set_mouse_x(CJS_Runtime* pRuntime,
874                                      v8::Local<v8::Value> vp) {
875   return CJS_Result::Success();
876 }
877 
get_mouse_y(CJS_Runtime * pRuntime)878 CJS_Result CJS_Document::get_mouse_y(CJS_Runtime* pRuntime) {
879   return CJS_Result::Success();
880 }
881 
set_mouse_y(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)882 CJS_Result CJS_Document::set_mouse_y(CJS_Runtime* pRuntime,
883                                      v8::Local<v8::Value> vp) {
884   return CJS_Result::Success();
885 }
886 
get_URL(CJS_Runtime * pRuntime)887 CJS_Result CJS_Document::get_URL(CJS_Runtime* pRuntime) {
888   if (!m_pFormFillEnv)
889     return CJS_Result::Failure(JSMessage::kBadObjectError);
890   return CJS_Result::Success(
891       pRuntime->NewString(m_pFormFillEnv->JS_docGetFilePath().AsStringView()));
892 }
893 
set_URL(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)894 CJS_Result CJS_Document::set_URL(CJS_Runtime* pRuntime,
895                                  v8::Local<v8::Value> vp) {
896   return CJS_Result::Failure(JSMessage::kReadOnlyError);
897 }
898 
get_base_URL(CJS_Runtime * pRuntime)899 CJS_Result CJS_Document::get_base_URL(CJS_Runtime* pRuntime) {
900   return CJS_Result::Success(pRuntime->NewString(m_cwBaseURL.AsStringView()));
901 }
902 
set_base_URL(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)903 CJS_Result CJS_Document::set_base_URL(CJS_Runtime* pRuntime,
904                                       v8::Local<v8::Value> vp) {
905   m_cwBaseURL = pRuntime->ToWideString(vp);
906   return CJS_Result::Success();
907 }
908 
get_calculate(CJS_Runtime * pRuntime)909 CJS_Result CJS_Document::get_calculate(CJS_Runtime* pRuntime) {
910   if (!m_pFormFillEnv)
911     return CJS_Result::Failure(JSMessage::kBadObjectError);
912 
913   CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm();
914   return CJS_Result::Success(
915       pRuntime->NewBoolean(!!pInteractiveForm->IsCalculateEnabled()));
916 }
917 
set_calculate(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)918 CJS_Result CJS_Document::set_calculate(CJS_Runtime* pRuntime,
919                                        v8::Local<v8::Value> vp) {
920   if (!m_pFormFillEnv)
921     return CJS_Result::Failure(JSMessage::kBadObjectError);
922 
923   CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm();
924   pInteractiveForm->EnableCalculate(pRuntime->ToBoolean(vp));
925   return CJS_Result::Success();
926 }
927 
get_document_file_name(CJS_Runtime * pRuntime)928 CJS_Result CJS_Document::get_document_file_name(CJS_Runtime* pRuntime) {
929   if (!m_pFormFillEnv)
930     return CJS_Result::Failure(JSMessage::kBadObjectError);
931 
932   WideString wsFilePath = m_pFormFillEnv->JS_docGetFilePath();
933   size_t i = wsFilePath.GetLength();
934   for (; i > 0; i--) {
935     if (wsFilePath[i - 1] == L'\\' || wsFilePath[i - 1] == L'/')
936       break;
937   }
938   if (i > 0 && i < wsFilePath.GetLength())
939     return CJS_Result::Success(pRuntime->NewString(wsFilePath.c_str() + i));
940 
941   return CJS_Result::Success(pRuntime->NewString(""));
942 }
943 
set_document_file_name(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)944 CJS_Result CJS_Document::set_document_file_name(CJS_Runtime* pRuntime,
945                                                 v8::Local<v8::Value> vp) {
946   return CJS_Result::Failure(JSMessage::kReadOnlyError);
947 }
948 
get_path(CJS_Runtime * pRuntime)949 CJS_Result CJS_Document::get_path(CJS_Runtime* pRuntime) {
950   if (!m_pFormFillEnv)
951     return CJS_Result::Failure(JSMessage::kBadObjectError);
952   return CJS_Result::Success(pRuntime->NewString(
953       CJS_App::SysPathToPDFPath(m_pFormFillEnv->JS_docGetFilePath())
954           .AsStringView()));
955 }
956 
set_path(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)957 CJS_Result CJS_Document::set_path(CJS_Runtime* pRuntime,
958                                   v8::Local<v8::Value> vp) {
959   return CJS_Result::Failure(JSMessage::kReadOnlyError);
960 }
961 
get_page_window_rect(CJS_Runtime * pRuntime)962 CJS_Result CJS_Document::get_page_window_rect(CJS_Runtime* pRuntime) {
963   return CJS_Result::Success();
964 }
965 
set_page_window_rect(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)966 CJS_Result CJS_Document::set_page_window_rect(CJS_Runtime* pRuntime,
967                                               v8::Local<v8::Value> vp) {
968   return CJS_Result::Success();
969 }
970 
get_layout(CJS_Runtime * pRuntime)971 CJS_Result CJS_Document::get_layout(CJS_Runtime* pRuntime) {
972   return CJS_Result::Success();
973 }
974 
set_layout(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)975 CJS_Result CJS_Document::set_layout(CJS_Runtime* pRuntime,
976                                     v8::Local<v8::Value> vp) {
977   return CJS_Result::Success();
978 }
979 
addLink(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)980 CJS_Result CJS_Document::addLink(
981     CJS_Runtime* pRuntime,
982     const std::vector<v8::Local<v8::Value>>& params) {
983   return CJS_Result::Success();
984 }
985 
closeDoc(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)986 CJS_Result CJS_Document::closeDoc(
987     CJS_Runtime* pRuntime,
988     const std::vector<v8::Local<v8::Value>>& params) {
989   return CJS_Result::Success();
990 }
991 
getPageBox(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)992 CJS_Result CJS_Document::getPageBox(
993     CJS_Runtime* pRuntime,
994     const std::vector<v8::Local<v8::Value>>& params) {
995   return CJS_Result::Success();
996 }
997 
getAnnot(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)998 CJS_Result CJS_Document::getAnnot(
999     CJS_Runtime* pRuntime,
1000     const std::vector<v8::Local<v8::Value>>& params) {
1001   if (params.size() != 2)
1002     return CJS_Result::Failure(JSMessage::kParamError);
1003   if (!m_pFormFillEnv)
1004     return CJS_Result::Failure(JSMessage::kBadObjectError);
1005 
1006   int nPageNo = pRuntime->ToInt32(params[0]);
1007   WideString swAnnotName = pRuntime->ToWideString(params[1]);
1008   CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(nPageNo);
1009   if (!pPageView)
1010     return CJS_Result::Failure(JSMessage::kBadObjectError);
1011 
1012   CPDFSDK_AnnotIteration annotIteration(pPageView, false);
1013   CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr;
1014   for (const auto& pSDKAnnotCur : annotIteration) {
1015     auto* pBAAnnot = pSDKAnnotCur->AsBAAnnot();
1016     if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) {
1017       pSDKBAAnnot = pBAAnnot;
1018       break;
1019     }
1020   }
1021   if (!pSDKBAAnnot)
1022     return CJS_Result::Failure(JSMessage::kBadObjectError);
1023 
1024   v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
1025       CJS_Annot::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
1026   if (pObj.IsEmpty())
1027     return CJS_Result::Failure(JSMessage::kBadObjectError);
1028 
1029   auto* pJS_Annot =
1030       static_cast<CJS_Annot*>(CFXJS_Engine::GetObjectPrivate(pObj));
1031   if (!pJS_Annot)
1032     return CJS_Result::Failure(JSMessage::kBadObjectError);
1033 
1034   pJS_Annot->SetSDKAnnot(pSDKBAAnnot);
1035   return CJS_Result::Success(pJS_Annot->ToV8Object());
1036 }
1037 
getAnnots(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1038 CJS_Result CJS_Document::getAnnots(
1039     CJS_Runtime* pRuntime,
1040     const std::vector<v8::Local<v8::Value>>& params) {
1041   if (!m_pFormFillEnv)
1042     return CJS_Result::Failure(JSMessage::kBadObjectError);
1043 
1044   // TODO(tonikitoo): Add support supported parameters as per
1045   // the PDF spec.
1046 
1047   int nPageNo = m_pFormFillEnv->GetPageCount();
1048   v8::Local<v8::Array> annots = pRuntime->NewArray();
1049   for (int i = 0; i < nPageNo; ++i) {
1050     CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(i);
1051     if (!pPageView)
1052       return CJS_Result::Failure(JSMessage::kBadObjectError);
1053 
1054     CPDFSDK_AnnotIteration annotIteration(pPageView, false);
1055     for (const auto& pSDKAnnotCur : annotIteration) {
1056       if (!pSDKAnnotCur)
1057         return CJS_Result::Failure(JSMessage::kBadObjectError);
1058 
1059       v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
1060           CJS_Annot::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
1061       if (pObj.IsEmpty())
1062         return CJS_Result::Failure(JSMessage::kBadObjectError);
1063 
1064       auto* pJS_Annot =
1065           static_cast<CJS_Annot*>(CFXJS_Engine::GetObjectPrivate(pObj));
1066       pJS_Annot->SetSDKAnnot(pSDKAnnotCur->AsBAAnnot());
1067       pRuntime->PutArrayElement(
1068           annots, i,
1069           pJS_Annot ? v8::Local<v8::Value>(pJS_Annot->ToV8Object())
1070                     : v8::Local<v8::Value>());
1071     }
1072   }
1073   return CJS_Result::Success(annots);
1074 }
1075 
getAnnot3D(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1076 CJS_Result CJS_Document::getAnnot3D(
1077     CJS_Runtime* pRuntime,
1078     const std::vector<v8::Local<v8::Value>>& params) {
1079   return CJS_Result::Success(pRuntime->NewUndefined());
1080 }
1081 
getAnnots3D(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1082 CJS_Result CJS_Document::getAnnots3D(
1083     CJS_Runtime* pRuntime,
1084     const std::vector<v8::Local<v8::Value>>& params) {
1085   return CJS_Result::Success();
1086 }
1087 
getOCGs(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1088 CJS_Result CJS_Document::getOCGs(
1089     CJS_Runtime* pRuntime,
1090     const std::vector<v8::Local<v8::Value>>& params) {
1091   return CJS_Result::Success();
1092 }
1093 
getLinks(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1094 CJS_Result CJS_Document::getLinks(
1095     CJS_Runtime* pRuntime,
1096     const std::vector<v8::Local<v8::Value>>& params) {
1097   return CJS_Result::Success();
1098 }
1099 
addIcon(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1100 CJS_Result CJS_Document::addIcon(
1101     CJS_Runtime* pRuntime,
1102     const std::vector<v8::Local<v8::Value>>& params) {
1103   if (params.size() != 2)
1104     return CJS_Result::Failure(JSMessage::kParamError);
1105 
1106   if (!params[1]->IsObject())
1107     return CJS_Result::Failure(JSMessage::kTypeError);
1108 
1109   v8::Local<v8::Object> pObj = pRuntime->ToObject(params[1]);
1110   if (!JSGetObject<CJS_Icon>(pObj))
1111     return CJS_Result::Failure(JSMessage::kTypeError);
1112 
1113   WideString swIconName = pRuntime->ToWideString(params[0]);
1114   m_IconNames.push_back(swIconName);
1115   return CJS_Result::Success();
1116 }
1117 
get_icons(CJS_Runtime * pRuntime)1118 CJS_Result CJS_Document::get_icons(CJS_Runtime* pRuntime) {
1119   // TODO(tsepez): Maybe make consistent with Acrobat Reader behavior which
1120   // is to throw an exception under the default security settings.
1121   if (m_IconNames.empty())
1122     return CJS_Result::Success(pRuntime->NewUndefined());
1123 
1124   v8::Local<v8::Array> Icons = pRuntime->NewArray();
1125   int i = 0;
1126   for (const auto& name : m_IconNames) {
1127     v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
1128         CJS_Icon::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
1129     if (pObj.IsEmpty())
1130       return CJS_Result::Failure(JSMessage::kBadObjectError);
1131 
1132     auto* pJS_Icon =
1133         static_cast<CJS_Icon*>(CFXJS_Engine::GetObjectPrivate(pObj));
1134     pJS_Icon->SetIconName(name);
1135     pRuntime->PutArrayElement(Icons, i++,
1136                               pJS_Icon
1137                                   ? v8::Local<v8::Value>(pJS_Icon->ToV8Object())
1138                                   : v8::Local<v8::Value>());
1139   }
1140   return CJS_Result::Success(Icons);
1141 }
1142 
set_icons(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1143 CJS_Result CJS_Document::set_icons(CJS_Runtime* pRuntime,
1144                                    v8::Local<v8::Value> vp) {
1145   return CJS_Result::Failure(JSMessage::kReadOnlyError);
1146 }
1147 
getIcon(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1148 CJS_Result CJS_Document::getIcon(
1149     CJS_Runtime* pRuntime,
1150     const std::vector<v8::Local<v8::Value>>& params) {
1151   if (params.size() != 1)
1152     return CJS_Result::Failure(JSMessage::kParamError);
1153 
1154   WideString swIconName = pRuntime->ToWideString(params[0]);
1155   auto it = std::find(m_IconNames.begin(), m_IconNames.end(), swIconName);
1156   if (it == m_IconNames.end())
1157     return CJS_Result::Failure(JSMessage::kBadObjectError);
1158 
1159   v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
1160       CJS_Icon::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
1161   if (pObj.IsEmpty())
1162     return CJS_Result::Failure(JSMessage::kBadObjectError);
1163 
1164   auto* pJSIcon = static_cast<CJS_Icon*>(CFXJS_Engine::GetObjectPrivate(pObj));
1165   if (!pJSIcon)
1166     return CJS_Result::Failure(JSMessage::kBadObjectError);
1167 
1168   pJSIcon->SetIconName(*it);
1169   return CJS_Result::Success(pJSIcon->ToV8Object());
1170 }
1171 
removeIcon(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1172 CJS_Result CJS_Document::removeIcon(
1173     CJS_Runtime* pRuntime,
1174     const std::vector<v8::Local<v8::Value>>& params) {
1175   // Unsafe, no supported.
1176   return CJS_Result::Success();
1177 }
1178 
createDataObject(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1179 CJS_Result CJS_Document::createDataObject(
1180     CJS_Runtime* pRuntime,
1181     const std::vector<v8::Local<v8::Value>>& params) {
1182   // Unsafe, not implemented.
1183   return CJS_Result::Success();
1184 }
1185 
get_media(CJS_Runtime * pRuntime)1186 CJS_Result CJS_Document::get_media(CJS_Runtime* pRuntime) {
1187   return CJS_Result::Success();
1188 }
1189 
set_media(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1190 CJS_Result CJS_Document::set_media(CJS_Runtime* pRuntime,
1191                                    v8::Local<v8::Value> vp) {
1192   return CJS_Result::Success();
1193 }
1194 
calculateNow(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1195 CJS_Result CJS_Document::calculateNow(
1196     CJS_Runtime* pRuntime,
1197     const std::vector<v8::Local<v8::Value>>& params) {
1198   if (!m_pFormFillEnv)
1199     return CJS_Result::Failure(JSMessage::kBadObjectError);
1200 
1201   if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
1202         m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
1203         m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) {
1204     return CJS_Result::Failure(JSMessage::kPermissionError);
1205   }
1206 
1207   GetSDKInteractiveForm()->OnCalculate(nullptr);
1208   return CJS_Result::Success();
1209 }
1210 
get_collab(CJS_Runtime * pRuntime)1211 CJS_Result CJS_Document::get_collab(CJS_Runtime* pRuntime) {
1212   return CJS_Result::Success();
1213 }
1214 
set_collab(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1215 CJS_Result CJS_Document::set_collab(CJS_Runtime* pRuntime,
1216                                     v8::Local<v8::Value> vp) {
1217   return CJS_Result::Success();
1218 }
1219 
getPageNthWord(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1220 CJS_Result CJS_Document::getPageNthWord(
1221     CJS_Runtime* pRuntime,
1222     const std::vector<v8::Local<v8::Value>>& params) {
1223   if (!m_pFormFillEnv)
1224     return CJS_Result::Failure(JSMessage::kBadObjectError);
1225   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1226     return CJS_Result::Failure(JSMessage::kPermissionError);
1227 
1228   // TODO(tsepez): check maximum allowable params.
1229 
1230   int nPageNo = params.size() > 0 ? pRuntime->ToInt32(params[0]) : 0;
1231   int nWordNo = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 0;
1232   bool bStrip = params.size() > 2 ? pRuntime->ToBoolean(params[2]) : true;
1233 
1234   CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
1235   if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1236     return CJS_Result::Failure(JSMessage::kValueError);
1237 
1238   CPDF_Dictionary* pPageDict = pDocument->GetPageDictionary(nPageNo);
1239   if (!pPageDict)
1240     return CJS_Result::Failure(JSMessage::kBadObjectError);
1241 
1242   auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict);
1243   page->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(page.Get()));
1244   page->ParseContent();
1245 
1246   int nWords = 0;
1247   WideString swRet;
1248   for (auto& pPageObj : *page) {
1249     if (pPageObj->IsText()) {
1250       CPDF_TextObject* pTextObj = pPageObj->AsText();
1251       int nObjWords = pTextObj->CountWords();
1252       if (nWords + nObjWords >= nWordNo) {
1253         swRet = pTextObj->GetWordString(nWordNo - nWords);
1254         break;
1255       }
1256       nWords += nObjWords;
1257     }
1258   }
1259 
1260   if (bStrip)
1261     swRet.Trim();
1262   return CJS_Result::Success(pRuntime->NewString(swRet.AsStringView()));
1263 }
1264 
getPageNthWordQuads(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1265 CJS_Result CJS_Document::getPageNthWordQuads(
1266     CJS_Runtime* pRuntime,
1267     const std::vector<v8::Local<v8::Value>>& params) {
1268   if (!m_pFormFillEnv)
1269     return CJS_Result::Failure(JSMessage::kBadObjectError);
1270   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1271     return CJS_Result::Failure(JSMessage::kBadObjectError);
1272   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1273 }
1274 
getPageNumWords(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1275 CJS_Result CJS_Document::getPageNumWords(
1276     CJS_Runtime* pRuntime,
1277     const std::vector<v8::Local<v8::Value>>& params) {
1278   if (!m_pFormFillEnv)
1279     return CJS_Result::Failure(JSMessage::kBadObjectError);
1280   if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1281     return CJS_Result::Failure(JSMessage::kPermissionError);
1282 
1283   int nPageNo = params.size() > 0 ? pRuntime->ToInt32(params[0]) : 0;
1284   CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
1285   if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1286     return CJS_Result::Failure(JSMessage::kValueError);
1287 
1288   CPDF_Dictionary* pPageDict = pDocument->GetPageDictionary(nPageNo);
1289   if (!pPageDict)
1290     return CJS_Result::Failure(JSMessage::kBadObjectError);
1291 
1292   auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict);
1293   page->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(page.Get()));
1294   page->ParseContent();
1295 
1296   int nWords = 0;
1297   for (auto& pPageObj : *page) {
1298     if (pPageObj->IsText())
1299       nWords += pPageObj->AsText()->CountWords();
1300   }
1301   return CJS_Result::Success(pRuntime->NewNumber(nWords));
1302 }
1303 
getPrintParams(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1304 CJS_Result CJS_Document::getPrintParams(
1305     CJS_Runtime* pRuntime,
1306     const std::vector<v8::Local<v8::Value>>& params) {
1307   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1308 }
1309 
get_zoom(CJS_Runtime * pRuntime)1310 CJS_Result CJS_Document::get_zoom(CJS_Runtime* pRuntime) {
1311   return CJS_Result::Success();
1312 }
1313 
set_zoom(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1314 CJS_Result CJS_Document::set_zoom(CJS_Runtime* pRuntime,
1315                                   v8::Local<v8::Value> vp) {
1316   return CJS_Result::Success();
1317 }
1318 
get_zoom_type(CJS_Runtime * pRuntime)1319 CJS_Result CJS_Document::get_zoom_type(CJS_Runtime* pRuntime) {
1320   return CJS_Result::Success();
1321 }
1322 
set_zoom_type(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1323 CJS_Result CJS_Document::set_zoom_type(CJS_Runtime* pRuntime,
1324                                        v8::Local<v8::Value> vp) {
1325   return CJS_Result::Success();
1326 }
1327 
deletePages(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1328 CJS_Result CJS_Document::deletePages(
1329     CJS_Runtime* pRuntime,
1330     const std::vector<v8::Local<v8::Value>>& params) {
1331   // Unsafe, not supported.
1332   return CJS_Result::Success();
1333 }
1334 
extractPages(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1335 CJS_Result CJS_Document::extractPages(
1336     CJS_Runtime* pRuntime,
1337     const std::vector<v8::Local<v8::Value>>& params) {
1338   // Unsafe, not supported.
1339   return CJS_Result::Success();
1340 }
1341 
insertPages(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1342 CJS_Result CJS_Document::insertPages(
1343     CJS_Runtime* pRuntime,
1344     const std::vector<v8::Local<v8::Value>>& params) {
1345   // Unsafe, not supported.
1346   return CJS_Result::Success();
1347 }
1348 
replacePages(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1349 CJS_Result CJS_Document::replacePages(
1350     CJS_Runtime* pRuntime,
1351     const std::vector<v8::Local<v8::Value>>& params) {
1352   // Unsafe, not supported.
1353   return CJS_Result::Success();
1354 }
1355 
getURL(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1356 CJS_Result CJS_Document::getURL(
1357     CJS_Runtime* pRuntime,
1358     const std::vector<v8::Local<v8::Value>>& params) {
1359   // Unsafe, not supported.
1360   return CJS_Result::Success();
1361 }
1362 
gotoNamedDest(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)1363 CJS_Result CJS_Document::gotoNamedDest(
1364     CJS_Runtime* pRuntime,
1365     const std::vector<v8::Local<v8::Value>>& params) {
1366   if (params.size() != 1)
1367     return CJS_Result::Failure(JSMessage::kParamError);
1368 
1369   if (!m_pFormFillEnv)
1370     return CJS_Result::Failure(JSMessage::kBadObjectError);
1371 
1372   CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
1373   CPDF_NameTree nameTree(pDocument, "Dests");
1374   CPDF_Array* destArray =
1375       nameTree.LookupNamedDest(pDocument, pRuntime->ToWideString(params[0]));
1376   if (!destArray)
1377     return CJS_Result::Failure(JSMessage::kBadObjectError);
1378 
1379   CPDF_Dest dest(destArray);
1380   const CPDF_Array* arrayObject = dest.GetArray();
1381   std::vector<float> scrollPositionArray;
1382   if (arrayObject) {
1383     for (size_t i = 2; i < arrayObject->size(); i++)
1384       scrollPositionArray.push_back(arrayObject->GetNumberAt(i));
1385   }
1386   pRuntime->BeginBlock();
1387   m_pFormFillEnv->DoGoToAction(dest.GetDestPageIndex(pDocument),
1388                                dest.GetZoomMode(), scrollPositionArray.data(),
1389                                scrollPositionArray.size());
1390   pRuntime->EndBlock();
1391   return CJS_Result::Success();
1392 }
1393 
AddDelayData(std::unique_ptr<CJS_DelayData> pData)1394 void CJS_Document::AddDelayData(std::unique_ptr<CJS_DelayData> pData) {
1395   m_DelayData.push_back(std::move(pData));
1396 }
1397 
DoFieldDelay(const WideString & sFieldName,int nControlIndex)1398 void CJS_Document::DoFieldDelay(const WideString& sFieldName,
1399                                 int nControlIndex) {
1400   std::vector<std::unique_ptr<CJS_DelayData>> delayed_data;
1401   auto iter = m_DelayData.begin();
1402   while (iter != m_DelayData.end()) {
1403     auto old = iter++;
1404     if ((*old)->sFieldName == sFieldName &&
1405         (*old)->nControlIndex == nControlIndex) {
1406       delayed_data.push_back(std::move(*old));
1407       m_DelayData.erase(old);
1408     }
1409   }
1410 
1411   for (const auto& pData : delayed_data)
1412     CJS_Field::DoDelay(m_pFormFillEnv.Get(), pData.get());
1413 }
1414 
GetCoreInteractiveForm()1415 CPDF_InteractiveForm* CJS_Document::GetCoreInteractiveForm() {
1416   return GetSDKInteractiveForm()->GetInteractiveForm();
1417 }
1418 
GetSDKInteractiveForm()1419 CPDFSDK_InteractiveForm* CJS_Document::GetSDKInteractiveForm() {
1420   return m_pFormFillEnv->GetInteractiveForm();
1421 }
1422