• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fxjs/cjs_field.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <optional>
12 #include <utility>
13 
14 #include "constants/access_permissions.h"
15 #include "constants/annotation_flags.h"
16 #include "constants/form_flags.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fpdfdoc/cpdf_formcontrol.h"
19 #include "core/fpdfdoc/cpdf_formfield.h"
20 #include "core/fpdfdoc/cpdf_interactiveform.h"
21 #include "core/fxcrt/check.h"
22 #include "core/fxcrt/notreached.h"
23 #include "core/fxcrt/span.h"
24 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
25 #include "fpdfsdk/cpdfsdk_interactiveform.h"
26 #include "fpdfsdk/cpdfsdk_pageview.h"
27 #include "fpdfsdk/cpdfsdk_widget.h"
28 #include "fxjs/cjs_color.h"
29 #include "fxjs/cjs_delaydata.h"
30 #include "fxjs/cjs_document.h"
31 #include "fxjs/cjs_icon.h"
32 #include "fxjs/fxv8.h"
33 #include "fxjs/js_resources.h"
34 #include "v8/include/v8-container.h"
35 
36 namespace {
37 
38 constexpr wchar_t kCheckSelector = L'4';
39 constexpr wchar_t kCircleSelector = L'l';
40 constexpr wchar_t kCrossSelector = L'8';
41 constexpr wchar_t kDiamondSelector = L'u';
42 constexpr wchar_t kSquareSelector = L'n';
43 constexpr wchar_t kStarSelector = L'H';
44 
IsCheckBoxOrRadioButton(const CPDF_FormField * pFormField)45 bool IsCheckBoxOrRadioButton(const CPDF_FormField* pFormField) {
46   return pFormField->GetFieldType() == FormFieldType::kCheckBox ||
47          pFormField->GetFieldType() == FormFieldType::kRadioButton;
48 }
49 
IsComboBoxOrListBox(const CPDF_FormField * pFormField)50 bool IsComboBoxOrListBox(const CPDF_FormField* pFormField) {
51   return pFormField->GetFieldType() == FormFieldType::kComboBox ||
52          pFormField->GetFieldType() == FormFieldType::kListBox;
53 }
54 
IsComboBoxOrTextField(const CPDF_FormField * pFormField)55 bool IsComboBoxOrTextField(const CPDF_FormField* pFormField) {
56   return pFormField->GetFieldType() == FormFieldType::kComboBox ||
57          pFormField->GetFieldType() == FormFieldType::kTextField;
58 }
59 
UpdateFormField(CPDFSDK_FormFillEnvironment * pFormFillEnv,CPDF_FormField * pFormField,bool bResetAP)60 void UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
61                      CPDF_FormField* pFormField,
62                      bool bResetAP) {
63   CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
64   if (bResetAP) {
65     std::vector<ObservedPtr<CPDFSDK_Widget>> widgets;
66     pForm->GetWidgets(pFormField, &widgets);
67 
68     if (IsComboBoxOrTextField(pFormField)) {
69       for (auto& pWidget : widgets) {
70         if (pWidget) {
71           std::optional<WideString> sValue = pWidget->OnFormat();
72           if (pWidget) {  // Not redundant, may be clobbered by OnFormat.
73             pWidget->ResetAppearance(sValue, CPDFSDK_Widget::kValueUnchanged);
74           }
75         }
76       }
77     } else {
78       for (auto& pWidget : widgets) {
79         if (pWidget) {
80           pWidget->ResetAppearance(std::nullopt,
81                                    CPDFSDK_Widget::kValueUnchanged);
82         }
83       }
84     }
85   }
86 
87   // Refresh the widget list. The calls in |bResetAP| may have caused widgets
88   // to be removed from the list. We need to call |GetWidgets| again to be
89   // sure none of the widgets have been deleted.
90   std::vector<ObservedPtr<CPDFSDK_Widget>> widgets;
91   pForm->GetWidgets(pFormField, &widgets);
92   for (auto& pWidget : widgets) {
93     if (pWidget)
94       pFormFillEnv->UpdateAllViews(pWidget.Get());
95   }
96   pFormFillEnv->SetChangeMark();
97 }
98 
UpdateFormControl(CPDFSDK_FormFillEnvironment * pFormFillEnv,CPDF_FormControl * pFormControl,bool bResetAP)99 void UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv,
100                        CPDF_FormControl* pFormControl,
101                        bool bResetAP) {
102   DCHECK(pFormControl);
103   CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
104   ObservedPtr<CPDFSDK_Widget> observed_widget(pForm->GetWidget(pFormControl));
105   if (observed_widget) {
106     if (bResetAP) {
107       FormFieldType fieldType = observed_widget->GetFieldType();
108       if (fieldType == FormFieldType::kComboBox ||
109           fieldType == FormFieldType::kTextField) {
110         std::optional<WideString> sValue = observed_widget->OnFormat();
111         if (!observed_widget)
112           return;
113         observed_widget->ResetAppearance(sValue,
114                                          CPDFSDK_Widget::kValueUnchanged);
115       } else {
116         observed_widget->ResetAppearance(std::nullopt,
117                                          CPDFSDK_Widget::kValueUnchanged);
118       }
119       if (!observed_widget)
120         return;
121     }
122     pFormFillEnv->UpdateAllViews(observed_widget.Get());
123   }
124   pFormFillEnv->SetChangeMark();
125 }
126 
127 struct FieldNameData {
FieldNameData__anona902e4b90111::FieldNameData128   FieldNameData(WideString field_name_in, int control_index_in)
129       : field_name(field_name_in), control_index(control_index_in) {}
130 
131   WideString field_name;
132   int control_index;
133 };
134 
ParseFieldName(const WideString & field_name)135 std::optional<FieldNameData> ParseFieldName(const WideString& field_name) {
136   auto reverse_it = field_name.rbegin();
137   while (reverse_it != field_name.rend()) {
138     if (*reverse_it == L'.')
139       break;
140     ++reverse_it;
141   }
142   if (reverse_it == field_name.rend()) {
143     return std::nullopt;
144   }
145   WideString suffixal = field_name.Last(reverse_it - field_name.rbegin());
146   int control_index = FXSYS_wtoi(suffixal.c_str());
147   if (control_index == 0) {
148     suffixal.TrimBack(L' ');
149     if (suffixal != L"0") {
150       return std::nullopt;
151     }
152   }
153   return FieldNameData(field_name.First(field_name.rend() - reverse_it - 1),
154                        control_index);
155 }
156 
GetFormFieldsForName(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & csFieldName)157 std::vector<CPDF_FormField*> GetFormFieldsForName(
158     CPDFSDK_FormFillEnvironment* pFormFillEnv,
159     const WideString& csFieldName) {
160   std::vector<CPDF_FormField*> fields;
161   CPDFSDK_InteractiveForm* pReaderForm = pFormFillEnv->GetInteractiveForm();
162   CPDF_InteractiveForm* pForm = pReaderForm->GetInteractiveForm();
163   const size_t sz = pForm->CountFields(csFieldName);
164   for (size_t i = 0; i < sz; ++i) {
165     CPDF_FormField* pFormField = pForm->GetField(i, csFieldName);
166     if (pFormField)
167       fields.push_back(pFormField);
168   }
169   return fields;
170 }
171 
GetFormControlColor(CPDF_FormControl * pFormControl,const ByteString & entry)172 CFX_Color GetFormControlColor(CPDF_FormControl* pFormControl,
173                               const ByteString& entry) {
174   switch (pFormControl->GetColorARGB(entry).color_type) {
175     case CFX_Color::Type::kTransparent:
176       return CFX_Color(CFX_Color::Type::kTransparent);
177     case CFX_Color::Type::kGray:
178       return CFX_Color(CFX_Color::Type::kGray,
179                        pFormControl->GetOriginalColorComponent(0, entry));
180     case CFX_Color::Type::kRGB:
181       return CFX_Color(CFX_Color::Type::kRGB,
182                        pFormControl->GetOriginalColorComponent(0, entry),
183                        pFormControl->GetOriginalColorComponent(1, entry),
184                        pFormControl->GetOriginalColorComponent(2, entry));
185     case CFX_Color::Type::kCMYK:
186       return CFX_Color(CFX_Color::Type::kCMYK,
187                        pFormControl->GetOriginalColorComponent(0, entry),
188                        pFormControl->GetOriginalColorComponent(1, entry),
189                        pFormControl->GetOriginalColorComponent(2, entry),
190                        pFormControl->GetOriginalColorComponent(3, entry));
191   }
192 }
193 
SetWidgetDisplayStatus(CPDFSDK_Widget * pWidget,int value)194 bool SetWidgetDisplayStatus(CPDFSDK_Widget* pWidget, int value) {
195   if (!pWidget)
196     return false;
197 
198   uint32_t dwFlag = pWidget->GetFlags();
199   switch (value) {
200     case 0:
201       dwFlag &= ~pdfium::annotation_flags::kInvisible;
202       dwFlag &= ~pdfium::annotation_flags::kHidden;
203       dwFlag &= ~pdfium::annotation_flags::kNoView;
204       dwFlag |= pdfium::annotation_flags::kPrint;
205       break;
206     case 1:
207       dwFlag &= ~pdfium::annotation_flags::kInvisible;
208       dwFlag &= ~pdfium::annotation_flags::kNoView;
209       dwFlag |= (pdfium::annotation_flags::kHidden |
210                  pdfium::annotation_flags::kPrint);
211       break;
212     case 2:
213       dwFlag &= ~pdfium::annotation_flags::kInvisible;
214       dwFlag &= ~pdfium::annotation_flags::kPrint;
215       dwFlag &= ~pdfium::annotation_flags::kHidden;
216       dwFlag &= ~pdfium::annotation_flags::kNoView;
217       break;
218     case 3:
219       dwFlag |= pdfium::annotation_flags::kNoView;
220       dwFlag |= pdfium::annotation_flags::kPrint;
221       dwFlag &= ~pdfium::annotation_flags::kHidden;
222       break;
223   }
224 
225   if (dwFlag != pWidget->GetFlags()) {
226     pWidget->SetFlags(dwFlag);
227     return true;
228   }
229 
230   return false;
231 }
232 
SetBorderStyle(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,const ByteString & bsString)233 void SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
234                     const WideString& swFieldName,
235                     int nControlIndex,
236                     const ByteString& bsString) {
237   DCHECK(pFormFillEnv);
238 
239   BorderStyle nBorderStyle;
240   if (bsString == "solid")
241     nBorderStyle = BorderStyle::kSolid;
242   else if (bsString == "beveled")
243     nBorderStyle = BorderStyle::kBeveled;
244   else if (bsString == "dashed")
245     nBorderStyle = BorderStyle::kDash;
246   else if (bsString == "inset")
247     nBorderStyle = BorderStyle::kInset;
248   else if (bsString == "underline")
249     nBorderStyle = BorderStyle::kUnderline;
250   else
251     return;
252 
253   std::vector<CPDF_FormField*> FieldArray =
254       GetFormFieldsForName(pFormFillEnv, swFieldName);
255   auto* pForm = pFormFillEnv->GetInteractiveForm();
256   for (CPDF_FormField* pFormField : FieldArray) {
257     if (nControlIndex < 0) {
258       bool bSet = false;
259       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
260         CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormField->GetControl(i));
261         if (pWidget) {
262           if (pWidget->GetBorderStyle() != nBorderStyle) {
263             pWidget->SetBorderStyle(nBorderStyle);
264             bSet = true;
265           }
266         }
267       }
268       if (bSet)
269         UpdateFormField(pFormFillEnv, pFormField, true);
270     } else {
271       if (nControlIndex >= pFormField->CountControls())
272         return;
273       if (CPDF_FormControl* pFormControl =
274               pFormField->GetControl(nControlIndex)) {
275         CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
276         if (pWidget) {
277           if (pWidget->GetBorderStyle() != nBorderStyle) {
278             pWidget->SetBorderStyle(nBorderStyle);
279             UpdateFormControl(pFormFillEnv, pFormControl, true);
280           }
281         }
282       }
283     }
284   }
285 }
286 
SetCurrentValueIndices(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,const std::vector<uint32_t> & array)287 void SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv,
288                             const WideString& swFieldName,
289                             int nControlIndex,
290                             const std::vector<uint32_t>& array) {
291   DCHECK(pFormFillEnv);
292   std::vector<CPDF_FormField*> FieldArray =
293       GetFormFieldsForName(pFormFillEnv, swFieldName);
294 
295   for (CPDF_FormField* pFormField : FieldArray) {
296     if (!IsComboBoxOrListBox(pFormField))
297       continue;
298 
299     uint32_t dwFieldFlags = pFormField->GetFieldFlags();
300     pFormField->ClearSelection(NotificationOption::kNotify);
301     for (size_t i = 0; i < array.size(); ++i) {
302       if (i != 0 && !(dwFieldFlags & pdfium::form_flags::kChoiceMultiSelect))
303         break;
304       if (array[i] < static_cast<uint32_t>(pFormField->CountOptions()) &&
305           !pFormField->IsItemSelected(array[i])) {
306         pFormField->SetItemSelection(array[i],
307                                      NotificationOption::kDoNotNotify);
308       }
309     }
310     UpdateFormField(pFormFillEnv, pFormField, true);
311   }
312 }
313 
SetDisplay(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,int number)314 void SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
315                 const WideString& swFieldName,
316                 int nControlIndex,
317                 int number) {
318   CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
319   std::vector<CPDF_FormField*> FieldArray =
320       GetFormFieldsForName(pFormFillEnv, swFieldName);
321   for (CPDF_FormField* pFormField : FieldArray) {
322     if (nControlIndex < 0) {
323       bool bAnySet = false;
324       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
325         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
326         DCHECK(pFormControl);
327 
328         CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
329         if (SetWidgetDisplayStatus(pWidget, number))
330           bAnySet = true;
331       }
332 
333       if (bAnySet)
334         UpdateFormField(pFormFillEnv, pFormField, false);
335     } else {
336       if (nControlIndex >= pFormField->CountControls())
337         return;
338 
339       CPDF_FormControl* pFormControl = pFormField->GetControl(nControlIndex);
340       if (!pFormControl)
341         return;
342 
343       CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
344       if (SetWidgetDisplayStatus(pWidget, number))
345         UpdateFormControl(pFormFillEnv, pFormControl, false);
346     }
347   }
348 }
349 
SetHidden(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,bool b)350 void SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv,
351                const WideString& swFieldName,
352                int nControlIndex,
353                bool b) {
354   int display = b ? 1 /*Hidden*/ : 0 /*Visible*/;
355   SetDisplay(pFormFillEnv, swFieldName, nControlIndex, display);
356 }
357 
SetLineWidth(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,int number)358 void SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv,
359                   const WideString& swFieldName,
360                   int nControlIndex,
361                   int number) {
362   CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
363   std::vector<CPDF_FormField*> FieldArray =
364       GetFormFieldsForName(pFormFillEnv, swFieldName);
365   for (CPDF_FormField* pFormField : FieldArray) {
366     if (nControlIndex < 0) {
367       bool bSet = false;
368       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
369         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
370         DCHECK(pFormControl);
371 
372         if (CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl)) {
373           if (number != pWidget->GetBorderWidth()) {
374             pWidget->SetBorderWidth(number);
375             bSet = true;
376           }
377         }
378       }
379       if (bSet)
380         UpdateFormField(pFormFillEnv, pFormField, true);
381     } else {
382       if (nControlIndex >= pFormField->CountControls())
383         return;
384       if (CPDF_FormControl* pFormControl =
385               pFormField->GetControl(nControlIndex)) {
386         if (CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl)) {
387           if (number != pWidget->GetBorderWidth()) {
388             pWidget->SetBorderWidth(number);
389             UpdateFormControl(pFormFillEnv, pFormControl, true);
390           }
391         }
392       }
393     }
394   }
395 }
396 
SetRect(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,const CFX_FloatRect & rect)397 void SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv,
398              const WideString& swFieldName,
399              int nControlIndex,
400              const CFX_FloatRect& rect) {
401   CPDFSDK_InteractiveForm* pForm = pFormFillEnv->GetInteractiveForm();
402   std::vector<CPDF_FormField*> FieldArray =
403       GetFormFieldsForName(pFormFillEnv, swFieldName);
404   for (CPDF_FormField* pFormField : FieldArray) {
405     if (nControlIndex < 0) {
406       bool bSet = false;
407       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
408         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
409         DCHECK(pFormControl);
410 
411         if (CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl)) {
412           CFX_FloatRect crRect = rect;
413 
414           CPDF_Page* pPDFPage = pWidget->GetPDFPage();
415           crRect.Intersect(pPDFPage->GetBBox());
416 
417           if (!crRect.IsEmpty()) {
418             CFX_FloatRect rcOld = pWidget->GetRect();
419             if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
420                 crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
421               pWidget->SetRect(crRect);
422               bSet = true;
423             }
424           }
425         }
426       }
427 
428       if (bSet)
429         UpdateFormField(pFormFillEnv, pFormField, true);
430 
431       continue;
432     }
433 
434     if (nControlIndex >= pFormField->CountControls())
435       return;
436     if (CPDF_FormControl* pFormControl =
437             pFormField->GetControl(nControlIndex)) {
438       if (CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl)) {
439         CFX_FloatRect crRect = rect;
440         CPDF_Page* pPDFPage = pWidget->GetPDFPage();
441         crRect.Intersect(pPDFPage->GetBBox());
442         if (!crRect.IsEmpty()) {
443           CFX_FloatRect rcOld = pWidget->GetRect();
444           if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
445               crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
446             pWidget->SetRect(crRect);
447             UpdateFormControl(pFormFillEnv, pFormControl, true);
448           }
449         }
450       }
451     }
452   }
453 }
454 
SetFieldValue(CPDFSDK_FormFillEnvironment * pFormFillEnv,const WideString & swFieldName,int nControlIndex,const std::vector<WideString> & strArray)455 void SetFieldValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
456                    const WideString& swFieldName,
457                    int nControlIndex,
458                    const std::vector<WideString>& strArray) {
459   DCHECK(pFormFillEnv);
460   if (strArray.empty())
461     return;
462 
463   std::vector<CPDF_FormField*> FieldArray =
464       GetFormFieldsForName(pFormFillEnv, swFieldName);
465 
466   for (CPDF_FormField* pFormField : FieldArray) {
467     if (pFormField->GetFullName() != swFieldName)
468       continue;
469 
470     switch (pFormField->GetFieldType()) {
471       case FormFieldType::kTextField:
472       case FormFieldType::kComboBox:
473         if (pFormField->GetValue() != strArray[0]) {
474           pFormField->SetValue(strArray[0], NotificationOption::kNotify);
475           UpdateFormField(pFormFillEnv, pFormField, false);
476         }
477         break;
478       case FormFieldType::kCheckBox:
479       case FormFieldType::kRadioButton:
480         if (pFormField->GetValue() != strArray[0]) {
481           pFormField->SetValue(strArray[0], NotificationOption::kNotify);
482           UpdateFormField(pFormFillEnv, pFormField, false);
483         }
484         break;
485       case FormFieldType::kListBox: {
486         bool bModified = false;
487         for (const auto& str : strArray) {
488           if (!pFormField->IsItemSelected(pFormField->FindOption(str))) {
489             bModified = true;
490             break;
491           }
492         }
493         if (bModified) {
494           pFormField->ClearSelection(NotificationOption::kNotify);
495           for (const auto& str : strArray) {
496             int index = pFormField->FindOption(str);
497             if (!pFormField->IsItemSelected(index))
498               pFormField->SetItemSelection(index, NotificationOption::kNotify);
499           }
500           UpdateFormField(pFormFillEnv, pFormField, false);
501         }
502         break;
503       }
504       default:
505         break;
506     }
507   }
508 }
509 
GetSelectorFromCaptionForFieldType(const WideString & caption,CPDF_FormField::Type type)510 wchar_t GetSelectorFromCaptionForFieldType(const WideString& caption,
511                                            CPDF_FormField::Type type) {
512   if (!caption.IsEmpty())
513     return caption[0];
514 
515   switch (type) {
516     case CPDF_FormField::kRadioButton:
517       return kCircleSelector;
518     default:
519       return kCheckSelector;
520   }
521 }
522 
523 }  // namespace
524 
525 const JSPropertySpec CJS_Field::PropertySpecs[] = {
526     {"alignment", get_alignment_static, set_alignment_static},
527     {"borderStyle", get_border_style_static, set_border_style_static},
528     {"buttonAlignX", get_button_align_x_static, set_button_align_x_static},
529     {"buttonAlignY", get_button_align_y_static, set_button_align_y_static},
530     {"buttonFitBounds", get_button_fit_bounds_static,
531      set_button_fit_bounds_static},
532     {"buttonPosition", get_button_position_static, set_button_position_static},
533     {"buttonScaleHow", get_button_scale_how_static,
534      set_button_scale_how_static},
535     {"buttonScaleWhen", get_button_scale_when_static,
536      set_button_scale_when_static},
537     {"calcOrderIndex", get_calc_order_index_static,
538      set_calc_order_index_static},
539     {"charLimit", get_char_limit_static, set_char_limit_static},
540     {"comb", get_comb_static, set_comb_static},
541     {"commitOnSelChange", get_commit_on_sel_change_static,
542      set_commit_on_sel_change_static},
543     {"currentValueIndices", get_current_value_indices_static,
544      set_current_value_indices_static},
545     {"defaultStyle", get_default_style_static, set_default_style_static},
546     {"defaultValue", get_default_value_static, set_default_value_static},
547     {"doNotScroll", get_do_not_scroll_static, set_do_not_scroll_static},
548     {"doNotSpellCheck", get_do_not_spell_check_static,
549      set_do_not_spell_check_static},
550     {"delay", get_delay_static, set_delay_static},
551     {"display", get_display_static, set_display_static},
552     {"doc", get_doc_static, set_doc_static},
553     {"editable", get_editable_static, set_editable_static},
554     {"exportValues", get_export_values_static, set_export_values_static},
555     {"hidden", get_hidden_static, set_hidden_static},
556     {"fileSelect", get_file_select_static, set_file_select_static},
557     {"fillColor", get_fill_color_static, set_fill_color_static},
558     {"lineWidth", get_line_width_static, set_line_width_static},
559     {"highlight", get_highlight_static, set_highlight_static},
560     {"multiline", get_multiline_static, set_multiline_static},
561     {"multipleSelection", get_multiple_selection_static,
562      set_multiple_selection_static},
563     {"name", get_name_static, set_name_static},
564     {"numItems", get_num_items_static, set_num_items_static},
565     {"page", get_page_static, set_page_static},
566     {"password", get_password_static, set_password_static},
567     {"print", get_print_static, set_print_static},
568     {"radiosInUnison", get_radios_in_unison_static,
569      set_radios_in_unison_static},
570     {"readonly", get_readonly_static, set_readonly_static},
571     {"rect", get_rect_static, set_rect_static},
572     {"required", get_required_static, set_required_static},
573     {"richText", get_rich_text_static, set_rich_text_static},
574     {"richValue", get_rich_value_static, set_rich_value_static},
575     {"rotation", get_rotation_static, set_rotation_static},
576     {"source", get_source_static, set_source_static},
577     {"strokeColor", get_stroke_color_static, set_stroke_color_static},
578     {"style", get_style_static, set_style_static},
579     {"submitName", get_submit_name_static, set_submit_name_static},
580     {"textColor", get_text_color_static, set_text_color_static},
581     {"textFont", get_text_font_static, set_text_font_static},
582     {"textSize", get_text_size_static, set_text_size_static},
583     {"type", get_type_static, set_type_static},
584     {"userName", get_user_name_static, set_user_name_static},
585     {"value", get_value_static, set_value_static},
586     {"valueAsString", get_value_as_string_static, set_value_as_string_static}};
587 
588 const JSMethodSpec CJS_Field::MethodSpecs[] = {
589     {"browseForFileToSubmit", browseForFileToSubmit_static},
590     {"buttonGetCaption", buttonGetCaption_static},
591     {"buttonGetIcon", buttonGetIcon_static},
592     {"buttonImportIcon", buttonImportIcon_static},
593     {"buttonSetCaption", buttonSetCaption_static},
594     {"buttonSetIcon", buttonSetIcon_static},
595     {"checkThisBox", checkThisBox_static},
596     {"clearItems", clearItems_static},
597     {"defaultIsChecked", defaultIsChecked_static},
598     {"deleteItemAt", deleteItemAt_static},
599     {"getArray", getArray_static},
600     {"getItemAt", getItemAt_static},
601     {"getLock", getLock_static},
602     {"insertItemAt", insertItemAt_static},
603     {"isBoxChecked", isBoxChecked_static},
604     {"isDefaultChecked", isDefaultChecked_static},
605     {"setAction", setAction_static},
606     {"setFocus", setFocus_static},
607     {"setItems", setItems_static},
608     {"setLock", setLock_static},
609     {"signatureGetModifications", signatureGetModifications_static},
610     {"signatureGetSeedValue", signatureGetSeedValue_static},
611     {"signatureInfo", signatureInfo_static},
612     {"signatureSetSeedValue", signatureSetSeedValue_static},
613     {"signatureSign", signatureSign_static},
614     {"signatureValidate", signatureValidate_static}};
615 
616 uint32_t CJS_Field::ObjDefnID = 0;
617 const char CJS_Field::kName[] = "Field";
618 
619 // static
GetObjDefnID()620 uint32_t CJS_Field::GetObjDefnID() {
621   return ObjDefnID;
622 }
623 
624 // static
DefineJSObjects(CFXJS_Engine * pEngine)625 void CJS_Field::DefineJSObjects(CFXJS_Engine* pEngine) {
626   ObjDefnID = pEngine->DefineObj(CJS_Field::kName, FXJSOBJTYPE_DYNAMIC,
627                                  JSConstructor<CJS_Field>, JSDestructor);
628   DefineProps(pEngine, ObjDefnID, PropertySpecs);
629   DefineMethods(pEngine, ObjDefnID, MethodSpecs);
630 }
631 
CJS_Field(v8::Local<v8::Object> pObject,CJS_Runtime * pRuntime)632 CJS_Field::CJS_Field(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
633     : CJS_Object(pObject, pRuntime) {}
634 
635 CJS_Field::~CJS_Field() = default;
636 
AttachField(CJS_Document * pDocument,const WideString & csFieldName)637 bool CJS_Field::AttachField(CJS_Document* pDocument,
638                             const WideString& csFieldName) {
639   m_pJSDoc.Reset(pDocument);
640   m_pFormFillEnv.Reset(pDocument->GetFormFillEnv());
641   m_bCanSet = m_pFormFillEnv->HasPermissions(
642       pdfium::access_permissions::kFillForm |
643       pdfium::access_permissions::kModifyAnnotation |
644       pdfium::access_permissions::kModifyContent);
645 
646   CPDFSDK_InteractiveForm* pRDForm = m_pFormFillEnv->GetInteractiveForm();
647   CPDF_InteractiveForm* pForm = pRDForm->GetInteractiveForm();
648   WideString swFieldNameTemp = csFieldName;
649   swFieldNameTemp.Replace(L"..", L".");
650 
651   if (pForm->CountFields(swFieldNameTemp) <= 0) {
652     std::optional<FieldNameData> parsed_data = ParseFieldName(swFieldNameTemp);
653     if (!parsed_data.has_value())
654       return false;
655 
656     m_FieldName = parsed_data.value().field_name;
657     m_nFormControlIndex = parsed_data.value().control_index;
658     return true;
659   }
660 
661   m_FieldName = swFieldNameTemp;
662   m_nFormControlIndex = -1;
663 
664   return true;
665 }
666 
GetFormFields() const667 std::vector<CPDF_FormField*> CJS_Field::GetFormFields() const {
668   return GetFormFieldsForName(m_pFormFillEnv.Get(), m_FieldName);
669 }
670 
GetFirstFormField() const671 CPDF_FormField* CJS_Field::GetFirstFormField() const {
672   std::vector<CPDF_FormField*> fields = GetFormFields();
673   return fields.empty() ? nullptr : fields[0];
674 }
675 
GetSmartFieldControl(CPDF_FormField * pFormField)676 CPDF_FormControl* CJS_Field::GetSmartFieldControl(CPDF_FormField* pFormField) {
677   if (!pFormField->CountControls() ||
678       m_nFormControlIndex >= pFormField->CountControls())
679     return nullptr;
680   if (m_nFormControlIndex < 0)
681     return pFormField->GetControl(0);
682   return pFormField->GetControl(m_nFormControlIndex);
683 }
684 
get_alignment(CJS_Runtime * pRuntime)685 CJS_Result CJS_Field::get_alignment(CJS_Runtime* pRuntime) {
686   DCHECK(m_pFormFillEnv);
687 
688   CPDF_FormField* pFormField = GetFirstFormField();
689   if (!pFormField)
690     return CJS_Result::Failure(JSMessage::kBadObjectError);
691 
692   if (pFormField->GetFieldType() != FormFieldType::kTextField)
693     return CJS_Result::Failure(JSMessage::kObjectTypeError);
694 
695   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
696   if (!pFormControl)
697     return CJS_Result::Failure(JSMessage::kBadObjectError);
698 
699   switch (pFormControl->GetControlAlignment()) {
700     case 0:
701       return CJS_Result::Success(pRuntime->NewString("left"));
702     case 1:
703       return CJS_Result::Success(pRuntime->NewString("center"));
704     case 2:
705       return CJS_Result::Success(pRuntime->NewString("right"));
706   }
707   return CJS_Result::Success(pRuntime->NewString(""));
708 }
709 
set_alignment(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)710 CJS_Result CJS_Field::set_alignment(CJS_Runtime* pRuntime,
711                                     v8::Local<v8::Value> vp) {
712   DCHECK(m_pFormFillEnv);
713   if (!m_bCanSet)
714     return CJS_Result::Failure(JSMessage::kReadOnlyError);
715 
716   return CJS_Result::Success();
717 }
718 
get_border_style(CJS_Runtime * pRuntime)719 CJS_Result CJS_Field::get_border_style(CJS_Runtime* pRuntime) {
720   DCHECK(m_pFormFillEnv);
721 
722   CPDF_FormField* pFormField = GetFirstFormField();
723   if (!pFormField)
724     return CJS_Result::Failure(JSMessage::kBadObjectError);
725 
726   CPDFSDK_Widget* pWidget = m_pFormFillEnv->GetInteractiveForm()->GetWidget(
727       GetSmartFieldControl(pFormField));
728   if (!pWidget)
729     return CJS_Result::Failure(JSMessage::kBadObjectError);
730 
731   switch (pWidget->GetBorderStyle()) {
732     case BorderStyle::kSolid:
733       return CJS_Result::Success(pRuntime->NewString("solid"));
734     case BorderStyle::kDash:
735       return CJS_Result::Success(pRuntime->NewString("dashed"));
736     case BorderStyle::kBeveled:
737       return CJS_Result::Success(pRuntime->NewString("beveled"));
738     case BorderStyle::kInset:
739       return CJS_Result::Success(pRuntime->NewString("inset"));
740     case BorderStyle::kUnderline:
741       return CJS_Result::Success(pRuntime->NewString("underline"));
742   }
743   return CJS_Result::Success(pRuntime->NewString(""));
744 }
745 
set_border_style(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)746 CJS_Result CJS_Field::set_border_style(CJS_Runtime* pRuntime,
747                                        v8::Local<v8::Value> vp) {
748   DCHECK(m_pFormFillEnv);
749   if (!m_bCanSet)
750     return CJS_Result::Failure(JSMessage::kReadOnlyError);
751 
752   ByteString byte_str = pRuntime->ToByteString(vp);
753   if (m_bDelay) {
754     AddDelay_String(FP_BORDERSTYLE, byte_str);
755   } else {
756     SetBorderStyle(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
757                    byte_str);
758   }
759   return CJS_Result::Success();
760 }
761 
get_button_align_x(CJS_Runtime * pRuntime)762 CJS_Result CJS_Field::get_button_align_x(CJS_Runtime* pRuntime) {
763   DCHECK(m_pFormFillEnv);
764 
765   CPDF_FormField* pFormField = GetFirstFormField();
766   if (!pFormField)
767     return CJS_Result::Failure(JSMessage::kBadObjectError);
768 
769   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
770     return CJS_Result::Failure(JSMessage::kObjectTypeError);
771 
772   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
773   if (!pFormControl)
774     return CJS_Result::Failure(JSMessage::kBadObjectError);
775 
776   CPDF_IconFit IconFit = pFormControl->GetIconFit();
777   CFX_PointF pos = IconFit.GetIconBottomLeftPosition();
778   return CJS_Result::Success(pRuntime->NewNumber(static_cast<int32_t>(pos.x)));
779 }
780 
set_button_align_x(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)781 CJS_Result CJS_Field::set_button_align_x(CJS_Runtime* pRuntime,
782                                          v8::Local<v8::Value> vp) {
783   DCHECK(m_pFormFillEnv);
784   if (!m_bCanSet)
785     return CJS_Result::Failure(JSMessage::kReadOnlyError);
786   return CJS_Result::Success();
787 }
788 
get_button_align_y(CJS_Runtime * pRuntime)789 CJS_Result CJS_Field::get_button_align_y(CJS_Runtime* pRuntime) {
790   DCHECK(m_pFormFillEnv);
791 
792   CPDF_FormField* pFormField = GetFirstFormField();
793   if (!pFormField)
794     return CJS_Result::Failure(JSMessage::kBadObjectError);
795 
796   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
797     return CJS_Result::Failure(JSMessage::kObjectTypeError);
798 
799   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
800   if (!pFormControl)
801     return CJS_Result::Failure(JSMessage::kBadObjectError);
802 
803   CPDF_IconFit IconFit = pFormControl->GetIconFit();
804   CFX_PointF pos = IconFit.GetIconBottomLeftPosition();
805   return CJS_Result::Success(pRuntime->NewNumber(static_cast<int32_t>(pos.y)));
806 }
807 
set_button_align_y(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)808 CJS_Result CJS_Field::set_button_align_y(CJS_Runtime* pRuntime,
809                                          v8::Local<v8::Value> vp) {
810   DCHECK(m_pFormFillEnv);
811   if (!m_bCanSet)
812     return CJS_Result::Failure(JSMessage::kReadOnlyError);
813   return CJS_Result::Success();
814 }
815 
get_button_fit_bounds(CJS_Runtime * pRuntime)816 CJS_Result CJS_Field::get_button_fit_bounds(CJS_Runtime* pRuntime) {
817   DCHECK(m_pFormFillEnv);
818 
819   CPDF_FormField* pFormField = GetFirstFormField();
820   if (!pFormField)
821     return CJS_Result::Failure(JSMessage::kBadObjectError);
822 
823   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
824     return CJS_Result::Failure(JSMessage::kObjectTypeError);
825 
826   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
827   if (!pFormControl)
828     return CJS_Result::Failure(JSMessage::kBadObjectError);
829 
830   return CJS_Result::Success(
831       pRuntime->NewBoolean(pFormControl->GetIconFit().GetFittingBounds()));
832 }
833 
set_button_fit_bounds(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)834 CJS_Result CJS_Field::set_button_fit_bounds(CJS_Runtime* pRuntime,
835                                             v8::Local<v8::Value> vp) {
836   DCHECK(m_pFormFillEnv);
837   if (!m_bCanSet)
838     return CJS_Result::Failure(JSMessage::kReadOnlyError);
839   return CJS_Result::Success();
840 }
841 
get_button_position(CJS_Runtime * pRuntime)842 CJS_Result CJS_Field::get_button_position(CJS_Runtime* pRuntime) {
843   DCHECK(m_pFormFillEnv);
844 
845   CPDF_FormField* pFormField = GetFirstFormField();
846   if (!pFormField)
847     return CJS_Result::Failure(JSMessage::kBadObjectError);
848 
849   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
850     return CJS_Result::Failure(JSMessage::kObjectTypeError);
851 
852   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
853   if (!pFormControl)
854     return CJS_Result::Failure(JSMessage::kBadObjectError);
855 
856   return CJS_Result::Success(
857       pRuntime->NewNumber(pFormControl->GetTextPosition()));
858 }
859 
set_button_position(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)860 CJS_Result CJS_Field::set_button_position(CJS_Runtime* pRuntime,
861                                           v8::Local<v8::Value> vp) {
862   DCHECK(m_pFormFillEnv);
863   if (!m_bCanSet)
864     return CJS_Result::Failure(JSMessage::kBadObjectError);
865   return CJS_Result::Success();
866 }
867 
get_button_scale_how(CJS_Runtime * pRuntime)868 CJS_Result CJS_Field::get_button_scale_how(CJS_Runtime* pRuntime) {
869   DCHECK(m_pFormFillEnv);
870 
871   CPDF_FormField* pFormField = GetFirstFormField();
872   if (!pFormField)
873     return CJS_Result::Failure(JSMessage::kBadObjectError);
874 
875   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
876     return CJS_Result::Failure(JSMessage::kObjectTypeError);
877 
878   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
879   if (!pFormControl)
880     return CJS_Result::Failure(JSMessage::kBadObjectError);
881 
882   return CJS_Result::Success(
883       pRuntime->NewBoolean(!pFormControl->GetIconFit().IsProportionalScale()));
884 }
885 
set_button_scale_how(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)886 CJS_Result CJS_Field::set_button_scale_how(CJS_Runtime* pRuntime,
887                                            v8::Local<v8::Value> vp) {
888   DCHECK(m_pFormFillEnv);
889   if (!m_bCanSet)
890     return CJS_Result::Failure(JSMessage::kReadOnlyError);
891   return CJS_Result::Success();
892 }
893 
get_button_scale_when(CJS_Runtime * pRuntime)894 CJS_Result CJS_Field::get_button_scale_when(CJS_Runtime* pRuntime) {
895   DCHECK(m_pFormFillEnv);
896 
897   CPDF_FormField* pFormField = GetFirstFormField();
898   if (!pFormField)
899     return CJS_Result::Failure(JSMessage::kBadObjectError);
900 
901   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
902     return CJS_Result::Failure(JSMessage::kObjectTypeError);
903 
904   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
905   if (!pFormControl)
906     return CJS_Result::Failure(JSMessage::kBadObjectError);
907 
908   CPDF_IconFit IconFit = pFormControl->GetIconFit();
909   CPDF_IconFit::ScaleMethod scale_method = IconFit.GetScaleMethod();
910   switch (scale_method) {
911     case CPDF_IconFit::ScaleMethod::kAlways:
912     case CPDF_IconFit::ScaleMethod::kBigger:
913     case CPDF_IconFit::ScaleMethod::kNever:
914     case CPDF_IconFit::ScaleMethod::kSmaller:
915       return CJS_Result::Success(
916           pRuntime->NewNumber(static_cast<int>(scale_method)));
917   }
918 }
919 
set_button_scale_when(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)920 CJS_Result CJS_Field::set_button_scale_when(CJS_Runtime* pRuntime,
921                                             v8::Local<v8::Value> vp) {
922   DCHECK(m_pFormFillEnv);
923   if (!m_bCanSet)
924     return CJS_Result::Failure(JSMessage::kReadOnlyError);
925   return CJS_Result::Success();
926 }
927 
get_calc_order_index(CJS_Runtime * pRuntime)928 CJS_Result CJS_Field::get_calc_order_index(CJS_Runtime* pRuntime) {
929   DCHECK(m_pFormFillEnv);
930 
931   CPDF_FormField* pFormField = GetFirstFormField();
932   if (!pFormField)
933     return CJS_Result::Failure(JSMessage::kBadObjectError);
934 
935   if (!IsComboBoxOrTextField(pFormField))
936     return CJS_Result::Failure(JSMessage::kObjectTypeError);
937 
938   CPDFSDK_InteractiveForm* pRDForm = m_pFormFillEnv->GetInteractiveForm();
939   CPDF_InteractiveForm* pForm = pRDForm->GetInteractiveForm();
940   return CJS_Result::Success(
941       pRuntime->NewNumber(pForm->FindFieldInCalculationOrder(pFormField)));
942 }
943 
set_calc_order_index(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)944 CJS_Result CJS_Field::set_calc_order_index(CJS_Runtime* pRuntime,
945                                            v8::Local<v8::Value> vp) {
946   DCHECK(m_pFormFillEnv);
947   if (!m_bCanSet)
948     return CJS_Result::Failure(JSMessage::kReadOnlyError);
949   return CJS_Result::Success();
950 }
951 
get_char_limit(CJS_Runtime * pRuntime)952 CJS_Result CJS_Field::get_char_limit(CJS_Runtime* pRuntime) {
953   DCHECK(m_pFormFillEnv);
954 
955   CPDF_FormField* pFormField = GetFirstFormField();
956   if (!pFormField)
957     return CJS_Result::Failure(JSMessage::kBadObjectError);
958 
959   if (pFormField->GetFieldType() != FormFieldType::kTextField)
960     return CJS_Result::Failure(JSMessage::kObjectTypeError);
961   return CJS_Result::Success(
962       pRuntime->NewNumber(static_cast<int32_t>(pFormField->GetMaxLen())));
963 }
964 
set_char_limit(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)965 CJS_Result CJS_Field::set_char_limit(CJS_Runtime* pRuntime,
966                                      v8::Local<v8::Value> vp) {
967   DCHECK(m_pFormFillEnv);
968   if (!m_bCanSet)
969     return CJS_Result::Failure(JSMessage::kReadOnlyError);
970   return CJS_Result::Success();
971 }
972 
get_comb(CJS_Runtime * pRuntime)973 CJS_Result CJS_Field::get_comb(CJS_Runtime* pRuntime) {
974   DCHECK(m_pFormFillEnv);
975 
976   CPDF_FormField* pFormField = GetFirstFormField();
977   if (!pFormField)
978     return CJS_Result::Failure(JSMessage::kBadObjectError);
979 
980   if (pFormField->GetFieldType() != FormFieldType::kTextField)
981     return CJS_Result::Failure(JSMessage::kObjectTypeError);
982 
983   return CJS_Result::Success(pRuntime->NewBoolean(
984       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextComb)));
985 }
986 
set_comb(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)987 CJS_Result CJS_Field::set_comb(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
988   DCHECK(m_pFormFillEnv);
989   if (!m_bCanSet)
990     return CJS_Result::Failure(JSMessage::kReadOnlyError);
991   return CJS_Result::Success();
992 }
993 
get_commit_on_sel_change(CJS_Runtime * pRuntime)994 CJS_Result CJS_Field::get_commit_on_sel_change(CJS_Runtime* pRuntime) {
995   DCHECK(m_pFormFillEnv);
996 
997   CPDF_FormField* pFormField = GetFirstFormField();
998   if (!pFormField)
999     return CJS_Result::Failure(JSMessage::kBadObjectError);
1000 
1001   if (!IsComboBoxOrListBox(pFormField))
1002     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1003 
1004   uint32_t dwFieldFlags = pFormField->GetFieldFlags();
1005   return CJS_Result::Success(pRuntime->NewBoolean(
1006       !!(dwFieldFlags & pdfium::form_flags::kChoiceCommitOnSelChange)));
1007 }
1008 
set_commit_on_sel_change(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1009 CJS_Result CJS_Field::set_commit_on_sel_change(CJS_Runtime* pRuntime,
1010                                                v8::Local<v8::Value> vp) {
1011   DCHECK(m_pFormFillEnv);
1012   if (!m_bCanSet)
1013     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1014   return CJS_Result::Success();
1015 }
1016 
get_current_value_indices(CJS_Runtime * pRuntime)1017 CJS_Result CJS_Field::get_current_value_indices(CJS_Runtime* pRuntime) {
1018   CPDF_FormField* pFormField = GetFirstFormField();
1019   if (!pFormField)
1020     return CJS_Result::Failure(JSMessage::kBadObjectError);
1021 
1022   if (!IsComboBoxOrListBox(pFormField))
1023     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1024 
1025   int count = pFormField->CountSelectedItems();
1026   if (count <= 0)
1027     return CJS_Result::Success(pRuntime->NewNumber(-1));
1028   if (count == 1)
1029     return CJS_Result::Success(
1030         pRuntime->NewNumber(pFormField->GetSelectedIndex(0)));
1031 
1032   v8::Local<v8::Array> SelArray = pRuntime->NewArray();
1033   for (int i = 0; i < count; i++) {
1034     pRuntime->PutArrayElement(
1035         SelArray, i, pRuntime->NewNumber(pFormField->GetSelectedIndex(i)));
1036   }
1037   if (SelArray.IsEmpty())
1038     return CJS_Result::Success(pRuntime->NewArray());
1039   return CJS_Result::Success(SelArray);
1040 }
1041 
set_current_value_indices(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1042 CJS_Result CJS_Field::set_current_value_indices(CJS_Runtime* pRuntime,
1043                                                 v8::Local<v8::Value> vp) {
1044   if (!m_bCanSet)
1045     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1046 
1047   std::vector<uint32_t> array;
1048   if (vp->IsNumber()) {
1049     array.push_back(pRuntime->ToInt32(vp));
1050   } else if (fxv8::IsArray(vp)) {
1051     v8::Local<v8::Array> SelArray = pRuntime->ToArray(vp);
1052     for (size_t i = 0; i < pRuntime->GetArrayLength(SelArray); i++) {
1053       array.push_back(
1054           pRuntime->ToInt32(pRuntime->GetArrayElement(SelArray, i)));
1055     }
1056   }
1057 
1058   if (m_bDelay) {
1059     AddDelay_WordArray(FP_CURRENTVALUEINDICES, array);
1060   } else {
1061     SetCurrentValueIndices(m_pFormFillEnv.Get(), m_FieldName,
1062                            m_nFormControlIndex, array);
1063   }
1064   return CJS_Result::Success();
1065 }
1066 
get_default_style(CJS_Runtime * pRuntime)1067 CJS_Result CJS_Field::get_default_style(CJS_Runtime* pRuntime) {
1068   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1069 }
1070 
set_default_style(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1071 CJS_Result CJS_Field::set_default_style(CJS_Runtime* pRuntime,
1072                                         v8::Local<v8::Value> vp) {
1073   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1074 }
1075 
get_default_value(CJS_Runtime * pRuntime)1076 CJS_Result CJS_Field::get_default_value(CJS_Runtime* pRuntime) {
1077   DCHECK(m_pFormFillEnv);
1078 
1079   CPDF_FormField* pFormField = GetFirstFormField();
1080   if (!pFormField)
1081     return CJS_Result::Failure(JSMessage::kBadObjectError);
1082 
1083   if (pFormField->GetFieldType() == FormFieldType::kPushButton ||
1084       pFormField->GetFieldType() == FormFieldType::kSignature) {
1085     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1086   }
1087 
1088   return CJS_Result::Success(
1089       pRuntime->NewString(pFormField->GetDefaultValue().AsStringView()));
1090 }
1091 
set_default_value(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1092 CJS_Result CJS_Field::set_default_value(CJS_Runtime* pRuntime,
1093                                         v8::Local<v8::Value> vp) {
1094   DCHECK(m_pFormFillEnv);
1095   if (!m_bCanSet)
1096     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1097   return CJS_Result::Success();
1098 }
1099 
get_do_not_scroll(CJS_Runtime * pRuntime)1100 CJS_Result CJS_Field::get_do_not_scroll(CJS_Runtime* pRuntime) {
1101   DCHECK(m_pFormFillEnv);
1102 
1103   CPDF_FormField* pFormField = GetFirstFormField();
1104   if (!pFormField)
1105     return CJS_Result::Failure(JSMessage::kBadObjectError);
1106 
1107   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1108     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1109 
1110   return CJS_Result::Success(pRuntime->NewBoolean(
1111       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextDoNotScroll)));
1112 }
1113 
set_do_not_scroll(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1114 CJS_Result CJS_Field::set_do_not_scroll(CJS_Runtime* pRuntime,
1115                                         v8::Local<v8::Value> vp) {
1116   DCHECK(m_pFormFillEnv);
1117   if (!m_bCanSet)
1118     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1119   return CJS_Result::Success();
1120 }
1121 
get_do_not_spell_check(CJS_Runtime * pRuntime)1122 CJS_Result CJS_Field::get_do_not_spell_check(CJS_Runtime* pRuntime) {
1123   DCHECK(m_pFormFillEnv);
1124 
1125   CPDF_FormField* pFormField = GetFirstFormField();
1126   if (!pFormField)
1127     return CJS_Result::Failure(JSMessage::kBadObjectError);
1128 
1129   if (!IsComboBoxOrTextField(pFormField))
1130     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1131 
1132   uint32_t dwFieldFlags = pFormField->GetFieldFlags();
1133   return CJS_Result::Success(pRuntime->NewBoolean(
1134       !!(dwFieldFlags & pdfium::form_flags::kTextDoNotSpellCheck)));
1135 }
1136 
set_do_not_spell_check(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1137 CJS_Result CJS_Field::set_do_not_spell_check(CJS_Runtime* pRuntime,
1138                                              v8::Local<v8::Value> vp) {
1139   DCHECK(m_pFormFillEnv);
1140   if (!m_bCanSet)
1141     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1142   return CJS_Result::Success();
1143 }
1144 
get_delay(CJS_Runtime * pRuntime)1145 CJS_Result CJS_Field::get_delay(CJS_Runtime* pRuntime) {
1146   return CJS_Result::Success(pRuntime->NewBoolean(m_bDelay));
1147 }
1148 
set_delay(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1149 CJS_Result CJS_Field::set_delay(CJS_Runtime* pRuntime,
1150                                 v8::Local<v8::Value> vp) {
1151   if (!m_bCanSet)
1152     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1153 
1154   SetDelay(pRuntime->ToBoolean(vp));
1155   return CJS_Result::Success();
1156 }
1157 
get_display(CJS_Runtime * pRuntime)1158 CJS_Result CJS_Field::get_display(CJS_Runtime* pRuntime) {
1159   CPDF_FormField* pFormField = GetFirstFormField();
1160   if (!pFormField)
1161     return CJS_Result::Failure(JSMessage::kBadObjectError);
1162 
1163   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1164   CPDFSDK_Widget* pWidget = pForm->GetWidget(GetSmartFieldControl(pFormField));
1165   if (!pWidget)
1166     return CJS_Result::Failure(JSMessage::kBadObjectError);
1167 
1168   uint32_t dwFlag = pWidget->GetFlags();
1169   if (pdfium::annotation_flags::kInvisible & dwFlag ||
1170       pdfium::annotation_flags::kHidden & dwFlag) {
1171     return CJS_Result::Success(pRuntime->NewNumber(1));
1172   }
1173 
1174   if (pdfium::annotation_flags::kPrint & dwFlag) {
1175     if (pdfium::annotation_flags::kNoView & dwFlag)
1176       return CJS_Result::Success(pRuntime->NewNumber(3));
1177     return CJS_Result::Success(pRuntime->NewNumber(0));
1178   }
1179   return CJS_Result::Success(pRuntime->NewNumber(2));
1180 }
1181 
set_display(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1182 CJS_Result CJS_Field::set_display(CJS_Runtime* pRuntime,
1183                                   v8::Local<v8::Value> vp) {
1184   if (!m_bCanSet)
1185     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1186 
1187   if (m_bDelay) {
1188     AddDelay_Int(FP_DISPLAY, pRuntime->ToInt32(vp));
1189   } else {
1190     SetDisplay(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
1191                pRuntime->ToInt32(vp));
1192   }
1193   return CJS_Result::Success();
1194 }
1195 
get_doc(CJS_Runtime * pRuntime)1196 CJS_Result CJS_Field::get_doc(CJS_Runtime* pRuntime) {
1197   return CJS_Result::Success(m_pJSDoc->ToV8Object());
1198 }
1199 
set_doc(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1200 CJS_Result CJS_Field::set_doc(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
1201   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1202 }
1203 
get_editable(CJS_Runtime * pRuntime)1204 CJS_Result CJS_Field::get_editable(CJS_Runtime* pRuntime) {
1205   CPDF_FormField* pFormField = GetFirstFormField();
1206   if (!pFormField)
1207     return CJS_Result::Failure(JSMessage::kBadObjectError);
1208 
1209   if (pFormField->GetFieldType() != FormFieldType::kComboBox)
1210     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1211 
1212   return CJS_Result::Success(pRuntime->NewBoolean(
1213       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kChoiceEdit)));
1214 }
1215 
set_editable(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1216 CJS_Result CJS_Field::set_editable(CJS_Runtime* pRuntime,
1217                                    v8::Local<v8::Value> vp) {
1218   if (!m_bCanSet)
1219     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1220   return CJS_Result::Success();
1221 }
1222 
get_export_values(CJS_Runtime * pRuntime)1223 CJS_Result CJS_Field::get_export_values(CJS_Runtime* pRuntime) {
1224   CPDF_FormField* pFormField = GetFirstFormField();
1225   if (!pFormField)
1226     return CJS_Result::Failure(JSMessage::kBadObjectError);
1227 
1228   if (!IsCheckBoxOrRadioButton(pFormField))
1229     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1230 
1231   v8::Local<v8::Array> ExportValuesArray = pRuntime->NewArray();
1232   if (m_nFormControlIndex < 0) {
1233     for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
1234       CPDF_FormControl* pFormControl = pFormField->GetControl(i);
1235       pRuntime->PutArrayElement(
1236           ExportValuesArray, i,
1237           pRuntime->NewString(pFormControl->GetExportValue().AsStringView()));
1238     }
1239   } else {
1240     if (m_nFormControlIndex >= pFormField->CountControls())
1241       return CJS_Result::Failure(JSMessage::kValueError);
1242 
1243     CPDF_FormControl* pFormControl =
1244         pFormField->GetControl(m_nFormControlIndex);
1245     if (!pFormControl)
1246       return CJS_Result::Failure(JSMessage::kBadObjectError);
1247 
1248     pRuntime->PutArrayElement(
1249         ExportValuesArray, 0,
1250         pRuntime->NewString(pFormControl->GetExportValue().AsStringView()));
1251   }
1252   return CJS_Result::Success(ExportValuesArray);
1253 }
1254 
set_export_values(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1255 CJS_Result CJS_Field::set_export_values(CJS_Runtime* pRuntime,
1256                                         v8::Local<v8::Value> vp) {
1257   CPDF_FormField* pFormField = GetFirstFormField();
1258   if (!pFormField)
1259     return CJS_Result::Failure(JSMessage::kBadObjectError);
1260 
1261   if (!IsCheckBoxOrRadioButton(pFormField))
1262     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1263 
1264   if (!m_bCanSet)
1265     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1266 
1267   if (!fxv8::IsArray(vp))
1268     return CJS_Result::Failure(JSMessage::kBadObjectError);
1269 
1270   return CJS_Result::Success();
1271 }
1272 
get_file_select(CJS_Runtime * pRuntime)1273 CJS_Result CJS_Field::get_file_select(CJS_Runtime* pRuntime) {
1274   CPDF_FormField* pFormField = GetFirstFormField();
1275   if (!pFormField)
1276     return CJS_Result::Failure(JSMessage::kBadObjectError);
1277 
1278   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1279     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1280 
1281   return CJS_Result::Success(pRuntime->NewBoolean(
1282       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextFileSelect)));
1283 }
1284 
set_file_select(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1285 CJS_Result CJS_Field::set_file_select(CJS_Runtime* pRuntime,
1286                                       v8::Local<v8::Value> vp) {
1287   CPDF_FormField* pFormField = GetFirstFormField();
1288   if (!pFormField)
1289     return CJS_Result::Failure(JSMessage::kBadObjectError);
1290 
1291   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1292     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1293 
1294   if (!m_bCanSet)
1295     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1296 
1297   return CJS_Result::Success();
1298 }
1299 
get_fill_color(CJS_Runtime * pRuntime)1300 CJS_Result CJS_Field::get_fill_color(CJS_Runtime* pRuntime) {
1301   CPDF_FormField* pFormField = GetFirstFormField();
1302   if (!pFormField)
1303     return CJS_Result::Failure(JSMessage::kBadObjectError);
1304 
1305   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1306   if (!pFormControl)
1307     return CJS_Result::Failure(JSMessage::kBadObjectError);
1308 
1309   CFX_Color color = GetFormControlColor(pFormControl, pdfium::appearance::kBG);
1310   v8::Local<v8::Value> array =
1311       CJS_Color::ConvertPWLColorToArray(pRuntime, color);
1312   if (array.IsEmpty())
1313     return CJS_Result::Success(pRuntime->NewArray());
1314   return CJS_Result::Success(array);
1315 }
1316 
set_fill_color(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1317 CJS_Result CJS_Field::set_fill_color(CJS_Runtime* pRuntime,
1318                                      v8::Local<v8::Value> vp) {
1319   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
1320   if (FieldArray.empty())
1321     return CJS_Result::Failure(JSMessage::kBadObjectError);
1322   if (!m_bCanSet)
1323     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1324   if (!fxv8::IsArray(vp))
1325     return CJS_Result::Failure(JSMessage::kBadObjectError);
1326   return CJS_Result::Success();
1327 }
1328 
get_hidden(CJS_Runtime * pRuntime)1329 CJS_Result CJS_Field::get_hidden(CJS_Runtime* pRuntime) {
1330   CPDF_FormField* pFormField = GetFirstFormField();
1331   if (!pFormField)
1332     return CJS_Result::Failure(JSMessage::kBadObjectError);
1333 
1334   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1335   CPDFSDK_Widget* pWidget = pForm->GetWidget(GetSmartFieldControl(pFormField));
1336   if (!pWidget)
1337     return CJS_Result::Failure(JSMessage::kBadObjectError);
1338 
1339   uint32_t dwFlags = pWidget->GetFlags();
1340   return CJS_Result::Success(
1341       pRuntime->NewBoolean(pdfium::annotation_flags::kInvisible & dwFlags ||
1342                            pdfium::annotation_flags::kHidden & dwFlags));
1343 }
1344 
set_hidden(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1345 CJS_Result CJS_Field::set_hidden(CJS_Runtime* pRuntime,
1346                                  v8::Local<v8::Value> vp) {
1347   if (!m_bCanSet)
1348     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1349 
1350   if (m_bDelay) {
1351     AddDelay_Bool(FP_HIDDEN, pRuntime->ToBoolean(vp));
1352   } else {
1353     SetHidden(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
1354               pRuntime->ToBoolean(vp));
1355   }
1356   return CJS_Result::Success();
1357 }
1358 
get_highlight(CJS_Runtime * pRuntime)1359 CJS_Result CJS_Field::get_highlight(CJS_Runtime* pRuntime) {
1360   DCHECK(m_pFormFillEnv);
1361 
1362   CPDF_FormField* pFormField = GetFirstFormField();
1363   if (!pFormField)
1364     return CJS_Result::Failure(JSMessage::kBadObjectError);
1365 
1366   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
1367     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1368 
1369   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1370   if (!pFormControl)
1371     return CJS_Result::Failure(JSMessage::kBadObjectError);
1372 
1373   int eHM = pFormControl->GetHighlightingMode();
1374   switch (eHM) {
1375     case CPDF_FormControl::kNone:
1376       return CJS_Result::Success(pRuntime->NewString("none"));
1377     case CPDF_FormControl::kPush:
1378       return CJS_Result::Success(pRuntime->NewString("push"));
1379     case CPDF_FormControl::kInvert:
1380       return CJS_Result::Success(pRuntime->NewString("invert"));
1381     case CPDF_FormControl::kOutline:
1382       return CJS_Result::Success(pRuntime->NewString("outline"));
1383     case CPDF_FormControl::kToggle:
1384       return CJS_Result::Success(pRuntime->NewString("toggle"));
1385   }
1386   return CJS_Result::Success();
1387 }
1388 
set_highlight(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1389 CJS_Result CJS_Field::set_highlight(CJS_Runtime* pRuntime,
1390                                     v8::Local<v8::Value> vp) {
1391   DCHECK(m_pFormFillEnv);
1392   if (!m_bCanSet)
1393     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1394   return CJS_Result::Success();
1395 }
1396 
get_line_width(CJS_Runtime * pRuntime)1397 CJS_Result CJS_Field::get_line_width(CJS_Runtime* pRuntime) {
1398   CPDF_FormField* pFormField = GetFirstFormField();
1399   if (!pFormField)
1400     return CJS_Result::Failure(JSMessage::kBadObjectError);
1401 
1402   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1403   if (!pFormControl)
1404     return CJS_Result::Failure(JSMessage::kBadObjectError);
1405 
1406   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1407   if (!pFormField->CountControls())
1408     return CJS_Result::Failure(JSMessage::kBadObjectError);
1409 
1410   CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormField->GetControl(0));
1411   if (!pWidget)
1412     return CJS_Result::Failure(JSMessage::kBadObjectError);
1413 
1414   return CJS_Result::Success(pRuntime->NewNumber(pWidget->GetBorderWidth()));
1415 }
1416 
set_line_width(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1417 CJS_Result CJS_Field::set_line_width(CJS_Runtime* pRuntime,
1418                                      v8::Local<v8::Value> vp) {
1419   if (!m_bCanSet)
1420     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1421 
1422   if (m_bDelay) {
1423     AddDelay_Int(FP_LINEWIDTH, pRuntime->ToInt32(vp));
1424   } else {
1425     SetLineWidth(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
1426                  pRuntime->ToInt32(vp));
1427   }
1428   return CJS_Result::Success();
1429 }
1430 
get_multiline(CJS_Runtime * pRuntime)1431 CJS_Result CJS_Field::get_multiline(CJS_Runtime* pRuntime) {
1432   DCHECK(m_pFormFillEnv);
1433 
1434   CPDF_FormField* pFormField = GetFirstFormField();
1435   if (!pFormField)
1436     return CJS_Result::Failure(JSMessage::kBadObjectError);
1437 
1438   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1439     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1440 
1441   return CJS_Result::Success(pRuntime->NewBoolean(
1442       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextMultiline)));
1443 }
1444 
set_multiline(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1445 CJS_Result CJS_Field::set_multiline(CJS_Runtime* pRuntime,
1446                                     v8::Local<v8::Value> vp) {
1447   DCHECK(m_pFormFillEnv);
1448   if (!m_bCanSet)
1449     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1450   return CJS_Result::Success();
1451 }
1452 
get_multiple_selection(CJS_Runtime * pRuntime)1453 CJS_Result CJS_Field::get_multiple_selection(CJS_Runtime* pRuntime) {
1454   DCHECK(m_pFormFillEnv);
1455   CPDF_FormField* pFormField = GetFirstFormField();
1456   if (!pFormField)
1457     return CJS_Result::Failure(JSMessage::kBadObjectError);
1458 
1459   if (pFormField->GetFieldType() != FormFieldType::kListBox)
1460     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1461 
1462   uint32_t dwFieldFlags = pFormField->GetFieldFlags();
1463   return CJS_Result::Success(pRuntime->NewBoolean(
1464       !!(dwFieldFlags & pdfium::form_flags::kChoiceMultiSelect)));
1465 }
1466 
set_multiple_selection(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1467 CJS_Result CJS_Field::set_multiple_selection(CJS_Runtime* pRuntime,
1468                                              v8::Local<v8::Value> vp) {
1469   DCHECK(m_pFormFillEnv);
1470   if (!m_bCanSet)
1471     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1472   return CJS_Result::Success();
1473 }
1474 
get_name(CJS_Runtime * pRuntime)1475 CJS_Result CJS_Field::get_name(CJS_Runtime* pRuntime) {
1476   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
1477   if (FieldArray.empty())
1478     return CJS_Result::Failure(JSMessage::kBadObjectError);
1479 
1480   return CJS_Result::Success(pRuntime->NewString(m_FieldName.AsStringView()));
1481 }
1482 
set_name(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1483 CJS_Result CJS_Field::set_name(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
1484   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1485 }
1486 
get_num_items(CJS_Runtime * pRuntime)1487 CJS_Result CJS_Field::get_num_items(CJS_Runtime* pRuntime) {
1488   CPDF_FormField* pFormField = GetFirstFormField();
1489   if (!pFormField)
1490     return CJS_Result::Failure(JSMessage::kBadObjectError);
1491 
1492   if (!IsComboBoxOrListBox(pFormField))
1493     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1494 
1495   return CJS_Result::Success(pRuntime->NewNumber(pFormField->CountOptions()));
1496 }
1497 
set_num_items(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1498 CJS_Result CJS_Field::set_num_items(CJS_Runtime* pRuntime,
1499                                     v8::Local<v8::Value> vp) {
1500   return CJS_Result::Failure(JSMessage::kNotSupportedError);
1501 }
1502 
get_page(CJS_Runtime * pRuntime)1503 CJS_Result CJS_Field::get_page(CJS_Runtime* pRuntime) {
1504   CPDF_FormField* pFormField = GetFirstFormField();
1505   if (!pFormField)
1506     return CJS_Result::Failure(JSMessage::kBadObjectError);
1507 
1508   std::vector<ObservedPtr<CPDFSDK_Widget>> widgets;
1509   m_pFormFillEnv->GetInteractiveForm()->GetWidgets(pFormField, &widgets);
1510   if (widgets.empty())
1511     return CJS_Result::Success(pRuntime->NewNumber(-1));
1512 
1513   v8::Local<v8::Array> PageArray = pRuntime->NewArray();
1514   int i = 0;
1515   for (const auto& pWidget : widgets) {
1516     if (!pWidget)
1517       return CJS_Result::Failure(JSMessage::kBadObjectError);
1518 
1519     pRuntime->PutArrayElement(
1520         PageArray, i,
1521         pRuntime->NewNumber(pWidget->GetPageView()->GetPageIndex()));
1522     ++i;
1523   }
1524   return CJS_Result::Success(PageArray);
1525 }
1526 
set_page(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1527 CJS_Result CJS_Field::set_page(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
1528   return CJS_Result::Failure(JSMessage::kReadOnlyError);
1529 }
1530 
get_password(CJS_Runtime * pRuntime)1531 CJS_Result CJS_Field::get_password(CJS_Runtime* pRuntime) {
1532   DCHECK(m_pFormFillEnv);
1533 
1534   CPDF_FormField* pFormField = GetFirstFormField();
1535   if (!pFormField)
1536     return CJS_Result::Failure(JSMessage::kBadObjectError);
1537 
1538   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1539     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1540 
1541   return CJS_Result::Success(pRuntime->NewBoolean(
1542       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextPassword)));
1543 }
1544 
set_password(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1545 CJS_Result CJS_Field::set_password(CJS_Runtime* pRuntime,
1546                                    v8::Local<v8::Value> vp) {
1547   DCHECK(m_pFormFillEnv);
1548   if (!m_bCanSet)
1549     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1550   return CJS_Result::Success();
1551 }
1552 
get_print(CJS_Runtime * pRuntime)1553 CJS_Result CJS_Field::get_print(CJS_Runtime* pRuntime) {
1554   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1555   CPDF_FormField* pFormField = GetFirstFormField();
1556   if (!pFormField)
1557     return CJS_Result::Failure(JSMessage::kBadObjectError);
1558 
1559   CPDFSDK_Widget* pWidget = pForm->GetWidget(GetSmartFieldControl(pFormField));
1560   if (!pWidget)
1561     return CJS_Result::Failure(JSMessage::kBadObjectError);
1562 
1563   return CJS_Result::Success(pRuntime->NewBoolean(
1564       !!(pWidget->GetFlags() & pdfium::annotation_flags::kPrint)));
1565 }
1566 
set_print(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1567 CJS_Result CJS_Field::set_print(CJS_Runtime* pRuntime,
1568                                 v8::Local<v8::Value> vp) {
1569   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1570   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
1571   if (FieldArray.empty())
1572     return CJS_Result::Failure(JSMessage::kBadObjectError);
1573 
1574   if (!m_bCanSet)
1575     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1576 
1577   for (CPDF_FormField* pFormField : FieldArray) {
1578     if (m_nFormControlIndex < 0) {
1579       bool bSet = false;
1580       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
1581         if (CPDFSDK_Widget* pWidget =
1582                 pForm->GetWidget(pFormField->GetControl(i))) {
1583           uint32_t dwFlags = pWidget->GetFlags();
1584           if (pRuntime->ToBoolean(vp))
1585             dwFlags |= pdfium::annotation_flags::kPrint;
1586           else
1587             dwFlags &= ~pdfium::annotation_flags::kPrint;
1588 
1589           if (dwFlags != pWidget->GetFlags()) {
1590             pWidget->SetFlags(dwFlags);
1591             bSet = true;
1592           }
1593         }
1594       }
1595 
1596       if (bSet)
1597         UpdateFormField(m_pFormFillEnv.Get(), pFormField, false);
1598 
1599       continue;
1600     }
1601 
1602     if (m_nFormControlIndex >= pFormField->CountControls())
1603       return CJS_Result::Failure(JSMessage::kValueError);
1604 
1605     if (CPDF_FormControl* pFormControl =
1606             pFormField->GetControl(m_nFormControlIndex)) {
1607       if (CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl)) {
1608         uint32_t dwFlags = pWidget->GetFlags();
1609         if (pRuntime->ToBoolean(vp))
1610           dwFlags |= pdfium::annotation_flags::kPrint;
1611         else
1612           dwFlags &= ~pdfium::annotation_flags::kPrint;
1613 
1614         if (dwFlags != pWidget->GetFlags()) {
1615           pWidget->SetFlags(dwFlags);
1616           UpdateFormControl(m_pFormFillEnv.Get(),
1617                             pFormField->GetControl(m_nFormControlIndex), false);
1618         }
1619       }
1620     }
1621   }
1622   return CJS_Result::Success();
1623 }
1624 
get_radios_in_unison(CJS_Runtime * pRuntime)1625 CJS_Result CJS_Field::get_radios_in_unison(CJS_Runtime* pRuntime) {
1626   CPDF_FormField* pFormField = GetFirstFormField();
1627   if (!pFormField)
1628     return CJS_Result::Failure(JSMessage::kBadObjectError);
1629 
1630   if (pFormField->GetFieldType() != FormFieldType::kRadioButton)
1631     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1632 
1633   uint32_t dwFieldFlags = pFormField->GetFieldFlags();
1634   return CJS_Result::Success(pRuntime->NewBoolean(
1635       !!(dwFieldFlags & pdfium::form_flags::kButtonRadiosInUnison)));
1636 }
1637 
set_radios_in_unison(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1638 CJS_Result CJS_Field::set_radios_in_unison(CJS_Runtime* pRuntime,
1639                                            v8::Local<v8::Value> vp) {
1640   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
1641   if (FieldArray.empty())
1642     return CJS_Result::Failure(JSMessage::kBadObjectError);
1643   if (!m_bCanSet)
1644     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1645   return CJS_Result::Success();
1646 }
1647 
get_readonly(CJS_Runtime * pRuntime)1648 CJS_Result CJS_Field::get_readonly(CJS_Runtime* pRuntime) {
1649   CPDF_FormField* pFormField = GetFirstFormField();
1650   if (!pFormField)
1651     return CJS_Result::Failure(JSMessage::kBadObjectError);
1652 
1653   return CJS_Result::Success(pRuntime->NewBoolean(
1654       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kReadOnly)));
1655 }
1656 
set_readonly(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1657 CJS_Result CJS_Field::set_readonly(CJS_Runtime* pRuntime,
1658                                    v8::Local<v8::Value> vp) {
1659   CPDF_FormField* pFormField = GetFirstFormField();
1660   if (!pFormField)
1661     return CJS_Result::Failure(JSMessage::kBadObjectError);
1662 
1663   if (!m_bCanSet)
1664     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1665 
1666   const bool bReadOnly = pRuntime->ToBoolean(vp);
1667   const uint32_t dwFlags = pFormField->GetFieldFlags();
1668   const uint32_t dwNewFlags = bReadOnly
1669                                   ? (dwFlags | pdfium::form_flags::kReadOnly)
1670                                   : (dwFlags & ~pdfium::form_flags::kReadOnly);
1671   if (dwNewFlags != dwFlags)
1672     pFormField->SetFieldFlags(dwNewFlags);
1673 
1674   return CJS_Result::Success();
1675 }
1676 
get_rect(CJS_Runtime * pRuntime)1677 CJS_Result CJS_Field::get_rect(CJS_Runtime* pRuntime) {
1678   CPDF_FormField* pFormField = GetFirstFormField();
1679   if (!pFormField)
1680     return CJS_Result::Failure(JSMessage::kBadObjectError);
1681 
1682   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
1683   CPDFSDK_Widget* pWidget = pForm->GetWidget(GetSmartFieldControl(pFormField));
1684   if (!pWidget)
1685     return CJS_Result::Failure(JSMessage::kBadObjectError);
1686 
1687   CFX_FloatRect crRect = pWidget->GetRect();
1688   v8::Local<v8::Array> rcArray = pRuntime->NewArray();
1689   pRuntime->PutArrayElement(
1690       rcArray, 0, pRuntime->NewNumber(static_cast<int32_t>(crRect.left)));
1691   pRuntime->PutArrayElement(
1692       rcArray, 1, pRuntime->NewNumber(static_cast<int32_t>(crRect.top)));
1693   pRuntime->PutArrayElement(
1694       rcArray, 2, pRuntime->NewNumber(static_cast<int32_t>(crRect.right)));
1695   pRuntime->PutArrayElement(
1696       rcArray, 3, pRuntime->NewNumber(static_cast<int32_t>(crRect.bottom)));
1697 
1698   return CJS_Result::Success(rcArray);
1699 }
1700 
set_rect(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1701 CJS_Result CJS_Field::set_rect(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
1702   if (!m_bCanSet)
1703     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1704   if (!fxv8::IsArray(vp))
1705     return CJS_Result::Failure(JSMessage::kValueError);
1706 
1707   v8::Local<v8::Array> rcArray = pRuntime->ToArray(vp);
1708   if (pRuntime->GetArrayLength(rcArray) < 4)
1709     return CJS_Result::Failure(JSMessage::kValueError);
1710 
1711   float f0 = static_cast<float>(
1712       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 0)));
1713   float f1 = static_cast<float>(
1714       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 1)));
1715   float f2 = static_cast<float>(
1716       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 2)));
1717   float f3 = static_cast<float>(
1718       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 3)));
1719 
1720   CFX_FloatRect crRect(f0, f1, f2, f3);
1721   if (m_bDelay) {
1722     AddDelay_Rect(FP_RECT, crRect);
1723   } else {
1724     SetRect(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, crRect);
1725   }
1726   return CJS_Result::Success();
1727 }
1728 
get_required(CJS_Runtime * pRuntime)1729 CJS_Result CJS_Field::get_required(CJS_Runtime* pRuntime) {
1730   CPDF_FormField* pFormField = GetFirstFormField();
1731   if (!pFormField)
1732     return CJS_Result::Failure(JSMessage::kBadObjectError);
1733 
1734   if (pFormField->GetFieldType() == FormFieldType::kPushButton)
1735     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1736 
1737   return CJS_Result::Success(pRuntime->NewBoolean(
1738       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kRequired)));
1739 }
1740 
set_required(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1741 CJS_Result CJS_Field::set_required(CJS_Runtime* pRuntime,
1742                                    v8::Local<v8::Value> vp) {
1743   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
1744   if (FieldArray.empty())
1745     return CJS_Result::Failure(JSMessage::kBadObjectError);
1746   if (!m_bCanSet)
1747     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1748   return CJS_Result::Success();
1749 }
1750 
get_rich_text(CJS_Runtime * pRuntime)1751 CJS_Result CJS_Field::get_rich_text(CJS_Runtime* pRuntime) {
1752   DCHECK(m_pFormFillEnv);
1753 
1754   CPDF_FormField* pFormField = GetFirstFormField();
1755   if (!pFormField)
1756     return CJS_Result::Failure(JSMessage::kBadObjectError);
1757 
1758   if (pFormField->GetFieldType() != FormFieldType::kTextField)
1759     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1760 
1761   return CJS_Result::Success(pRuntime->NewBoolean(
1762       !!(pFormField->GetFieldFlags() & pdfium::form_flags::kTextRichText)));
1763 }
1764 
set_rich_text(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1765 CJS_Result CJS_Field::set_rich_text(CJS_Runtime* pRuntime,
1766                                     v8::Local<v8::Value> vp) {
1767   DCHECK(m_pFormFillEnv);
1768   if (!m_bCanSet)
1769     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1770   return CJS_Result::Success();
1771 }
1772 
get_rich_value(CJS_Runtime * pRuntime)1773 CJS_Result CJS_Field::get_rich_value(CJS_Runtime* pRuntime) {
1774   return CJS_Result::Success();
1775 }
1776 
set_rich_value(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1777 CJS_Result CJS_Field::set_rich_value(CJS_Runtime* pRuntime,
1778                                      v8::Local<v8::Value> vp) {
1779   return CJS_Result::Success();
1780 }
1781 
get_rotation(CJS_Runtime * pRuntime)1782 CJS_Result CJS_Field::get_rotation(CJS_Runtime* pRuntime) {
1783   DCHECK(m_pFormFillEnv);
1784 
1785   CPDF_FormField* pFormField = GetFirstFormField();
1786   if (!pFormField)
1787     return CJS_Result::Failure(JSMessage::kBadObjectError);
1788 
1789   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1790   if (!pFormControl)
1791     return CJS_Result::Failure(JSMessage::kBadObjectError);
1792 
1793   return CJS_Result::Success(pRuntime->NewNumber(pFormControl->GetRotation()));
1794 }
1795 
set_rotation(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1796 CJS_Result CJS_Field::set_rotation(CJS_Runtime* pRuntime,
1797                                    v8::Local<v8::Value> vp) {
1798   DCHECK(m_pFormFillEnv);
1799   if (!m_bCanSet)
1800     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1801   return CJS_Result::Success();
1802 }
1803 
get_source(CJS_Runtime * pRuntime)1804 CJS_Result CJS_Field::get_source(CJS_Runtime* pRuntime) {
1805   return CJS_Result::Success();
1806 }
1807 
set_source(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1808 CJS_Result CJS_Field::set_source(CJS_Runtime* pRuntime,
1809                                  v8::Local<v8::Value> vp) {
1810   return CJS_Result::Success();
1811 }
1812 
get_stroke_color(CJS_Runtime * pRuntime)1813 CJS_Result CJS_Field::get_stroke_color(CJS_Runtime* pRuntime) {
1814   CPDF_FormField* pFormField = GetFirstFormField();
1815   if (!pFormField)
1816     return CJS_Result::Failure(JSMessage::kBadObjectError);
1817 
1818   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1819   if (!pFormControl)
1820     return CJS_Result::Failure(JSMessage::kBadObjectError);
1821 
1822   CFX_Color color = GetFormControlColor(pFormControl, pdfium::appearance::kBC);
1823   v8::Local<v8::Value> array =
1824       CJS_Color::ConvertPWLColorToArray(pRuntime, color);
1825   if (array.IsEmpty())
1826     return CJS_Result::Success(pRuntime->NewArray());
1827   return CJS_Result::Success(array);
1828 }
1829 
set_stroke_color(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1830 CJS_Result CJS_Field::set_stroke_color(CJS_Runtime* pRuntime,
1831                                        v8::Local<v8::Value> vp) {
1832   if (!m_bCanSet)
1833     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1834   if (!fxv8::IsArray(vp))
1835     return CJS_Result::Failure(JSMessage::kBadObjectError);
1836   return CJS_Result::Success();
1837 }
1838 
get_style(CJS_Runtime * pRuntime)1839 CJS_Result CJS_Field::get_style(CJS_Runtime* pRuntime) {
1840   DCHECK(m_pFormFillEnv);
1841 
1842   CPDF_FormField* pFormField = GetFirstFormField();
1843   if (!pFormField)
1844     return CJS_Result::Failure(JSMessage::kBadObjectError);
1845 
1846   if (!IsCheckBoxOrRadioButton(pFormField))
1847     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1848 
1849   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1850   if (!pFormControl)
1851     return CJS_Result::Failure(JSMessage::kBadObjectError);
1852 
1853   wchar_t selector = GetSelectorFromCaptionForFieldType(
1854       pFormControl->GetNormalCaption(), pFormControl->GetType());
1855 
1856   ByteString csBCaption;
1857   switch (selector) {
1858     case kCircleSelector:
1859       csBCaption = "circle";
1860       break;
1861     case kCrossSelector:
1862       csBCaption = "cross";
1863       break;
1864     case kDiamondSelector:
1865       csBCaption = "diamond";
1866       break;
1867     case kSquareSelector:
1868       csBCaption = "square";
1869       break;
1870     case kStarSelector:
1871       csBCaption = "star";
1872       break;
1873     case kCheckSelector:
1874     default:
1875       csBCaption = "check";
1876       break;
1877   }
1878   return CJS_Result::Success(pRuntime->NewString(csBCaption.AsStringView()));
1879 }
1880 
set_style(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1881 CJS_Result CJS_Field::set_style(CJS_Runtime* pRuntime,
1882                                 v8::Local<v8::Value> vp) {
1883   DCHECK(m_pFormFillEnv);
1884   if (!m_bCanSet)
1885     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1886   return CJS_Result::Success();
1887 }
1888 
get_submit_name(CJS_Runtime * pRuntime)1889 CJS_Result CJS_Field::get_submit_name(CJS_Runtime* pRuntime) {
1890   return CJS_Result::Success();
1891 }
1892 
set_submit_name(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1893 CJS_Result CJS_Field::set_submit_name(CJS_Runtime* pRuntime,
1894                                       v8::Local<v8::Value> vp) {
1895   return CJS_Result::Success();
1896 }
1897 
get_text_color(CJS_Runtime * pRuntime)1898 CJS_Result CJS_Field::get_text_color(CJS_Runtime* pRuntime) {
1899   CPDF_FormField* pFormField = GetFirstFormField();
1900   if (!pFormField)
1901     return CJS_Result::Failure(JSMessage::kBadObjectError);
1902 
1903   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1904   if (!pFormControl)
1905     return CJS_Result::Failure(JSMessage::kBadObjectError);
1906 
1907   CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
1908   std::optional<CFX_Color::TypeAndARGB> maybe_type_argb_pair =
1909       FieldAppearance.GetColorARGB();
1910 
1911   CFX_Color crRet;
1912   if (maybe_type_argb_pair.has_value() &&
1913       maybe_type_argb_pair.value().color_type !=
1914           CFX_Color::Type::kTransparent) {
1915     FX_BGR_STRUCT<uint8_t> bgr =
1916         ArgbToBGRStruct(maybe_type_argb_pair.value().argb);
1917     crRet = CFX_Color(CFX_Color::Type::kRGB, bgr.red / 255.0f,
1918                       bgr.green / 255.0f, bgr.blue / 255.0f);
1919   }
1920 
1921   v8::Local<v8::Value> array =
1922       CJS_Color::ConvertPWLColorToArray(pRuntime, crRet);
1923   if (array.IsEmpty())
1924     return CJS_Result::Success(pRuntime->NewArray());
1925   return CJS_Result::Success(array);
1926 }
1927 
set_text_color(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1928 CJS_Result CJS_Field::set_text_color(CJS_Runtime* pRuntime,
1929                                      v8::Local<v8::Value> vp) {
1930   if (!m_bCanSet)
1931     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1932   if (!fxv8::IsArray(vp))
1933     return CJS_Result::Failure(JSMessage::kBadObjectError);
1934   return CJS_Result::Success();
1935 }
1936 
get_text_font(CJS_Runtime * pRuntime)1937 CJS_Result CJS_Field::get_text_font(CJS_Runtime* pRuntime) {
1938   DCHECK(m_pFormFillEnv);
1939 
1940   CPDF_FormField* pFormField = GetFirstFormField();
1941   if (!pFormField)
1942     return CJS_Result::Failure(JSMessage::kBadObjectError);
1943 
1944   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1945   if (!pFormControl)
1946     return CJS_Result::Failure(JSMessage::kBadObjectError);
1947 
1948   FormFieldType fieldType = pFormField->GetFieldType();
1949   if (fieldType != FormFieldType::kPushButton &&
1950       fieldType != FormFieldType::kComboBox &&
1951       fieldType != FormFieldType::kListBox &&
1952       fieldType != FormFieldType::kTextField) {
1953     return CJS_Result::Failure(JSMessage::kObjectTypeError);
1954   }
1955 
1956   std::optional<WideString> wsFontName =
1957       pFormControl->GetDefaultControlFontName();
1958   if (!wsFontName.has_value())
1959     return CJS_Result::Failure(JSMessage::kBadObjectError);
1960 
1961   return CJS_Result::Success(
1962       pRuntime->NewString(wsFontName.value().AsStringView()));
1963 }
1964 
set_text_font(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1965 CJS_Result CJS_Field::set_text_font(CJS_Runtime* pRuntime,
1966                                     v8::Local<v8::Value> vp) {
1967   DCHECK(m_pFormFillEnv);
1968 
1969   if (!m_bCanSet)
1970     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1971   if (pRuntime->ToByteString(vp).IsEmpty())
1972     return CJS_Result::Failure(JSMessage::kValueError);
1973   return CJS_Result::Success();
1974 }
1975 
get_text_size(CJS_Runtime * pRuntime)1976 CJS_Result CJS_Field::get_text_size(CJS_Runtime* pRuntime) {
1977   DCHECK(m_pFormFillEnv);
1978 
1979   CPDF_FormField* pFormField = GetFirstFormField();
1980   if (!pFormField)
1981     return CJS_Result::Failure(JSMessage::kBadObjectError);
1982 
1983   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
1984   if (!pFormControl)
1985     return CJS_Result::Failure(JSMessage::kBadObjectError);
1986 
1987   float fFontSize;
1988   CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
1989   FieldAppearance.GetFont(&fFontSize);
1990   return CJS_Result::Success(pRuntime->NewNumber(static_cast<int>(fFontSize)));
1991 }
1992 
set_text_size(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)1993 CJS_Result CJS_Field::set_text_size(CJS_Runtime* pRuntime,
1994                                     v8::Local<v8::Value> vp) {
1995   DCHECK(m_pFormFillEnv);
1996   if (!m_bCanSet)
1997     return CJS_Result::Failure(JSMessage::kReadOnlyError);
1998   return CJS_Result::Success();
1999 }
2000 
get_type(CJS_Runtime * pRuntime)2001 CJS_Result CJS_Field::get_type(CJS_Runtime* pRuntime) {
2002   CPDF_FormField* pFormField = GetFirstFormField();
2003   if (!pFormField)
2004     return CJS_Result::Failure(JSMessage::kBadObjectError);
2005 
2006   switch (pFormField->GetFieldType()) {
2007     case FormFieldType::kUnknown:
2008       return CJS_Result::Success(pRuntime->NewString("unknown"));
2009     case FormFieldType::kPushButton:
2010       return CJS_Result::Success(pRuntime->NewString("button"));
2011     case FormFieldType::kCheckBox:
2012       return CJS_Result::Success(pRuntime->NewString("checkbox"));
2013     case FormFieldType::kRadioButton:
2014       return CJS_Result::Success(pRuntime->NewString("radiobutton"));
2015     case FormFieldType::kComboBox:
2016       return CJS_Result::Success(pRuntime->NewString("combobox"));
2017     case FormFieldType::kListBox:
2018       return CJS_Result::Success(pRuntime->NewString("listbox"));
2019     case FormFieldType::kTextField:
2020       return CJS_Result::Success(pRuntime->NewString("text"));
2021     case FormFieldType::kSignature:
2022       return CJS_Result::Success(pRuntime->NewString("signature"));
2023 #ifdef PDF_ENABLE_XFA
2024     default:
2025       return CJS_Result::Success(pRuntime->NewString("unknown"));
2026 #endif
2027   }
2028 }
2029 
set_type(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)2030 CJS_Result CJS_Field::set_type(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
2031   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2032 }
2033 
get_user_name(CJS_Runtime * pRuntime)2034 CJS_Result CJS_Field::get_user_name(CJS_Runtime* pRuntime) {
2035   DCHECK(m_pFormFillEnv);
2036 
2037   CPDF_FormField* pFormField = GetFirstFormField();
2038   if (!pFormField)
2039     return CJS_Result::Failure(JSMessage::kBadObjectError);
2040 
2041   return CJS_Result::Success(
2042       pRuntime->NewString(pFormField->GetAlternateName().AsStringView()));
2043 }
2044 
set_user_name(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)2045 CJS_Result CJS_Field::set_user_name(CJS_Runtime* pRuntime,
2046                                     v8::Local<v8::Value> vp) {
2047   DCHECK(m_pFormFillEnv);
2048   if (!m_bCanSet)
2049     return CJS_Result::Failure(JSMessage::kReadOnlyError);
2050   return CJS_Result::Success();
2051 }
2052 
get_value(CJS_Runtime * pRuntime)2053 CJS_Result CJS_Field::get_value(CJS_Runtime* pRuntime) {
2054   CPDF_FormField* pFormField = GetFirstFormField();
2055   if (!pFormField)
2056     return CJS_Result::Failure(JSMessage::kBadObjectError);
2057 
2058   v8::Local<v8::Value> ret;
2059   switch (pFormField->GetFieldType()) {
2060     case FormFieldType::kPushButton:
2061       return CJS_Result::Failure(JSMessage::kObjectTypeError);
2062     case FormFieldType::kComboBox:
2063     case FormFieldType::kTextField:
2064       ret = pRuntime->NewString(pFormField->GetValue().AsStringView());
2065       break;
2066     case FormFieldType::kListBox: {
2067       if (pFormField->CountSelectedItems() > 1) {
2068         v8::Local<v8::Array> ValueArray = pRuntime->NewArray();
2069         v8::Local<v8::Value> ElementValue;
2070         int iIndex;
2071         for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
2072           iIndex = pFormField->GetSelectedIndex(i);
2073           ElementValue = pRuntime->NewString(
2074               pFormField->GetOptionValue(iIndex).AsStringView());
2075           if (pRuntime->ToWideString(ElementValue).IsEmpty()) {
2076             ElementValue = pRuntime->NewString(
2077                 pFormField->GetOptionLabel(iIndex).AsStringView());
2078           }
2079           pRuntime->PutArrayElement(ValueArray, i, ElementValue);
2080         }
2081         ret = ValueArray;
2082       } else {
2083         ret = pRuntime->NewString(pFormField->GetValue().AsStringView());
2084       }
2085       break;
2086     }
2087     case FormFieldType::kCheckBox:
2088     case FormFieldType::kRadioButton: {
2089       bool bFind = false;
2090       for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
2091         if (pFormField->GetControl(i)->IsChecked()) {
2092           ret = pRuntime->NewString(
2093               pFormField->GetControl(i)->GetExportValue().AsStringView());
2094           bFind = true;
2095           break;
2096         }
2097       }
2098       if (!bFind)
2099         ret = pRuntime->NewString("Off");
2100 
2101       break;
2102     }
2103     default:
2104       ret = pRuntime->NewString(pFormField->GetValue().AsStringView());
2105       break;
2106   }
2107   return CJS_Result::Success(pRuntime->MaybeCoerceToNumber(ret));
2108 }
2109 
set_value(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)2110 CJS_Result CJS_Field::set_value(CJS_Runtime* pRuntime,
2111                                 v8::Local<v8::Value> vp) {
2112   if (!m_bCanSet)
2113     return CJS_Result::Failure(JSMessage::kReadOnlyError);
2114 
2115   std::vector<WideString> strArray;
2116   if (fxv8::IsArray(vp)) {
2117     v8::Local<v8::Array> ValueArray = pRuntime->ToArray(vp);
2118     for (size_t i = 0; i < pRuntime->GetArrayLength(ValueArray); i++) {
2119       strArray.push_back(
2120           pRuntime->ToWideString(pRuntime->GetArrayElement(ValueArray, i)));
2121     }
2122   } else {
2123     strArray.push_back(pRuntime->ToWideString(vp));
2124   }
2125 
2126   if (m_bDelay) {
2127     AddDelay_WideStringArray(FP_VALUE, strArray);
2128   } else {
2129     SetFieldValue(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
2130                   strArray);
2131   }
2132   return CJS_Result::Success();
2133 }
2134 
get_value_as_string(CJS_Runtime * pRuntime)2135 CJS_Result CJS_Field::get_value_as_string(CJS_Runtime* pRuntime) {
2136   CPDF_FormField* pFormField = GetFirstFormField();
2137   if (!pFormField)
2138     return CJS_Result::Failure(JSMessage::kBadObjectError);
2139 
2140   if (pFormField->GetFieldType() == FormFieldType::kPushButton)
2141     return CJS_Result::Failure(JSMessage::kObjectTypeError);
2142 
2143   if (pFormField->GetFieldType() == FormFieldType::kCheckBox) {
2144     if (!pFormField->CountControls())
2145       return CJS_Result::Failure(JSMessage::kBadObjectError);
2146     return CJS_Result::Success(pRuntime->NewString(
2147         pFormField->GetControl(0)->IsChecked() ? "Yes" : "Off"));
2148   }
2149 
2150   if (pFormField->GetFieldType() == FormFieldType::kRadioButton &&
2151       !(pFormField->GetFieldFlags() &
2152         pdfium::form_flags::kButtonRadiosInUnison)) {
2153     for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
2154       if (pFormField->GetControl(i)->IsChecked()) {
2155         return CJS_Result::Success(pRuntime->NewString(
2156             pFormField->GetControl(i)->GetExportValue().AsStringView()));
2157       }
2158     }
2159     return CJS_Result::Success(pRuntime->NewString("Off"));
2160   }
2161 
2162   if (pFormField->GetFieldType() == FormFieldType::kListBox &&
2163       (pFormField->CountSelectedItems() > 1)) {
2164     return CJS_Result::Success(pRuntime->NewString(""));
2165   }
2166   return CJS_Result::Success(
2167       pRuntime->NewString(pFormField->GetValue().AsStringView()));
2168 }
2169 
set_value_as_string(CJS_Runtime * pRuntime,v8::Local<v8::Value> vp)2170 CJS_Result CJS_Field::set_value_as_string(CJS_Runtime* pRuntime,
2171                                           v8::Local<v8::Value> vp) {
2172   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2173 }
2174 
browseForFileToSubmit(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2175 CJS_Result CJS_Field::browseForFileToSubmit(
2176     CJS_Runtime* pRuntime,
2177     pdfium::span<v8::Local<v8::Value>> params) {
2178   CPDF_FormField* pFormField = GetFirstFormField();
2179   if (!pFormField)
2180     return CJS_Result::Failure(JSMessage::kBadObjectError);
2181 
2182   if ((pFormField->GetFieldFlags() & pdfium::form_flags::kTextFileSelect) &&
2183       (pFormField->GetFieldType() == FormFieldType::kTextField)) {
2184     WideString wsFileName = m_pFormFillEnv->JS_fieldBrowse();
2185     if (!wsFileName.IsEmpty()) {
2186       pFormField->SetValue(wsFileName, NotificationOption::kDoNotNotify);
2187       UpdateFormField(m_pFormFillEnv.Get(), pFormField, true);
2188     }
2189     return CJS_Result::Success();
2190   }
2191   return CJS_Result::Failure(JSMessage::kObjectTypeError);
2192 }
2193 
buttonGetCaption(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2194 CJS_Result CJS_Field::buttonGetCaption(
2195     CJS_Runtime* pRuntime,
2196     pdfium::span<v8::Local<v8::Value>> params) {
2197   int nface = 0;
2198   if (params.size() >= 1)
2199     nface = pRuntime->ToInt32(params[0]);
2200 
2201   CPDF_FormField* pFormField = GetFirstFormField();
2202   if (!pFormField)
2203     return CJS_Result::Failure(JSMessage::kBadObjectError);
2204 
2205   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
2206     return CJS_Result::Failure(JSMessage::kObjectTypeError);
2207 
2208   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
2209   if (!pFormControl)
2210     return CJS_Result::Failure(JSMessage::kBadObjectError);
2211 
2212   if (nface == 0) {
2213     return CJS_Result::Success(
2214         pRuntime->NewString(pFormControl->GetNormalCaption().AsStringView()));
2215   }
2216   if (nface == 1) {
2217     return CJS_Result::Success(
2218         pRuntime->NewString(pFormControl->GetDownCaption().AsStringView()));
2219   }
2220   if (nface == 2) {
2221     return CJS_Result::Success(
2222         pRuntime->NewString(pFormControl->GetRolloverCaption().AsStringView()));
2223   }
2224   return CJS_Result::Failure(JSMessage::kValueError);
2225 }
2226 
buttonGetIcon(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2227 CJS_Result CJS_Field::buttonGetIcon(CJS_Runtime* pRuntime,
2228                                     pdfium::span<v8::Local<v8::Value>> params) {
2229   if (params.size() >= 1) {
2230     int nFace = pRuntime->ToInt32(params[0]);
2231     if (nFace < 0 || nFace > 2)
2232       return CJS_Result::Failure(JSMessage::kValueError);
2233   }
2234 
2235   CPDF_FormField* pFormField = GetFirstFormField();
2236   if (!pFormField)
2237     return CJS_Result::Failure(JSMessage::kBadObjectError);
2238 
2239   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
2240     return CJS_Result::Failure(JSMessage::kObjectTypeError);
2241 
2242   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
2243   if (!pFormControl)
2244     return CJS_Result::Failure(JSMessage::kBadObjectError);
2245 
2246   v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
2247       CJS_Icon::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
2248   if (pObj.IsEmpty())
2249     return CJS_Result::Failure(JSMessage::kBadObjectError);
2250 
2251   auto* pJS_Icon = static_cast<CJS_Icon*>(
2252       CFXJS_Engine::GetBinding(pRuntime->GetIsolate(), pObj));
2253   return pJS_Icon ? CJS_Result::Success(pJS_Icon->ToV8Object())
2254                   : CJS_Result::Failure(JSMessage::kBadObjectError);
2255 }
2256 
buttonImportIcon(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2257 CJS_Result CJS_Field::buttonImportIcon(
2258     CJS_Runtime* pRuntime,
2259     pdfium::span<v8::Local<v8::Value>> params) {
2260   return CJS_Result::Success();
2261 }
2262 
buttonSetCaption(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2263 CJS_Result CJS_Field::buttonSetCaption(
2264     CJS_Runtime* pRuntime,
2265     pdfium::span<v8::Local<v8::Value>> params) {
2266   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2267 }
2268 
buttonSetIcon(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2269 CJS_Result CJS_Field::buttonSetIcon(CJS_Runtime* pRuntime,
2270                                     pdfium::span<v8::Local<v8::Value>> params) {
2271   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2272 }
2273 
checkThisBox(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2274 CJS_Result CJS_Field::checkThisBox(CJS_Runtime* pRuntime,
2275                                    pdfium::span<v8::Local<v8::Value>> params) {
2276   const size_t nSize = params.size();
2277   if (nSize == 0)
2278     return CJS_Result::Failure(JSMessage::kParamError);
2279 
2280   if (!m_bCanSet)
2281     return CJS_Result::Failure(JSMessage::kReadOnlyError);
2282 
2283   int nWidget = pRuntime->ToInt32(params[0]);
2284   bool bCheckit = true;
2285   if (nSize >= 2)
2286     bCheckit = pRuntime->ToBoolean(params[1]);
2287 
2288   CPDF_FormField* pFormField = GetFirstFormField();
2289   if (!pFormField)
2290     return CJS_Result::Failure(JSMessage::kBadObjectError);
2291 
2292   if (!IsCheckBoxOrRadioButton(pFormField))
2293     return CJS_Result::Failure(JSMessage::kObjectTypeError);
2294 
2295   if (nWidget < 0 || nWidget >= pFormField->CountControls())
2296     return CJS_Result::Failure(JSMessage::kValueError);
2297 
2298   // TODO(weili): Check whether anything special needed for radio button.
2299   // (When pFormField->GetFieldType() == FormFieldType::kRadioButton.)
2300   pFormField->CheckControl(nWidget, bCheckit, NotificationOption::kNotify);
2301   UpdateFormField(m_pFormFillEnv.Get(), pFormField, true);
2302   return CJS_Result::Success();
2303 }
2304 
clearItems(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2305 CJS_Result CJS_Field::clearItems(CJS_Runtime* pRuntime,
2306                                  pdfium::span<v8::Local<v8::Value>> params) {
2307   return CJS_Result::Success();
2308 }
2309 
defaultIsChecked(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2310 CJS_Result CJS_Field::defaultIsChecked(
2311     CJS_Runtime* pRuntime,
2312     pdfium::span<v8::Local<v8::Value>> params) {
2313   if (!m_bCanSet)
2314     return CJS_Result::Failure(JSMessage::kReadOnlyError);
2315 
2316   if (params.empty())
2317     return CJS_Result::Failure(JSMessage::kParamError);
2318 
2319   CPDF_FormField* pFormField = GetFirstFormField();
2320   if (!pFormField)
2321     return CJS_Result::Failure(JSMessage::kBadObjectError);
2322 
2323   int nWidget = pRuntime->ToInt32(params[0]);
2324   if (nWidget < 0 || nWidget >= pFormField->CountControls())
2325     return CJS_Result::Failure(JSMessage::kValueError);
2326 
2327   return CJS_Result::Success(
2328       pRuntime->NewBoolean(IsCheckBoxOrRadioButton(pFormField)));
2329 }
2330 
deleteItemAt(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2331 CJS_Result CJS_Field::deleteItemAt(CJS_Runtime* pRuntime,
2332                                    pdfium::span<v8::Local<v8::Value>> params) {
2333   return CJS_Result::Success();
2334 }
2335 
getArray(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2336 CJS_Result CJS_Field::getArray(CJS_Runtime* pRuntime,
2337                                pdfium::span<v8::Local<v8::Value>> params) {
2338   std::vector<CPDF_FormField*> FieldArray = GetFormFields();
2339   if (FieldArray.empty())
2340     return CJS_Result::Failure(JSMessage::kBadObjectError);
2341 
2342   std::vector<std::unique_ptr<WideString>> swSort;
2343   for (CPDF_FormField* pFormField : FieldArray) {
2344     swSort.push_back(std::make_unique<WideString>(pFormField->GetFullName()));
2345   }
2346 
2347   std::sort(swSort.begin(), swSort.end(),
2348             [](const std::unique_ptr<WideString>& p1,
2349                const std::unique_ptr<WideString>& p2) { return *p1 < *p2; });
2350 
2351   v8::Local<v8::Array> FormFieldArray = pRuntime->NewArray();
2352   int j = 0;
2353   for (const auto& pStr : swSort) {
2354     v8::Local<v8::Object> pObj = pRuntime->NewFXJSBoundObject(
2355         CJS_Field::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
2356     if (pObj.IsEmpty())
2357       return CJS_Result::Failure(JSMessage::kBadObjectError);
2358 
2359     auto* pJSField = static_cast<CJS_Field*>(
2360         CFXJS_Engine::GetBinding(pRuntime->GetIsolate(), pObj));
2361     pJSField->AttachField(m_pJSDoc.Get(), *pStr);
2362     pRuntime->PutArrayElement(FormFieldArray, j++,
2363                               pJSField
2364                                   ? v8::Local<v8::Value>(pJSField->ToV8Object())
2365                                   : v8::Local<v8::Value>());
2366   }
2367   return CJS_Result::Success(FormFieldArray);
2368 }
2369 
getItemAt(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2370 CJS_Result CJS_Field::getItemAt(CJS_Runtime* pRuntime,
2371                                 pdfium::span<v8::Local<v8::Value>> params) {
2372   const size_t nSize = params.size();
2373   int nIdx = -1;
2374   if (nSize >= 1)
2375     nIdx = pRuntime->ToInt32(params[0]);
2376 
2377   bool bExport = true;
2378   if (nSize >= 2)
2379     bExport = pRuntime->ToBoolean(params[1]);
2380 
2381   CPDF_FormField* pFormField = GetFirstFormField();
2382   if (!pFormField)
2383     return CJS_Result::Failure(JSMessage::kBadObjectError);
2384 
2385   if (!IsComboBoxOrListBox(pFormField))
2386     return CJS_Result::Failure(JSMessage::kObjectTypeError);
2387 
2388   if (nIdx == -1 || nIdx > pFormField->CountOptions())
2389     nIdx = pFormField->CountOptions() - 1;
2390   if (!bExport) {
2391     return CJS_Result::Success(
2392         pRuntime->NewString(pFormField->GetOptionLabel(nIdx).AsStringView()));
2393   }
2394 
2395   WideString strval = pFormField->GetOptionValue(nIdx);
2396   if (strval.IsEmpty()) {
2397     return CJS_Result::Success(
2398         pRuntime->NewString(pFormField->GetOptionLabel(nIdx).AsStringView()));
2399   }
2400   return CJS_Result::Success(pRuntime->NewString(strval.AsStringView()));
2401 }
2402 
getLock(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2403 CJS_Result CJS_Field::getLock(CJS_Runtime* pRuntime,
2404                               pdfium::span<v8::Local<v8::Value>> params) {
2405   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2406 }
2407 
insertItemAt(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2408 CJS_Result CJS_Field::insertItemAt(CJS_Runtime* pRuntime,
2409                                    pdfium::span<v8::Local<v8::Value>> params) {
2410   return CJS_Result::Success();
2411 }
2412 
isBoxChecked(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2413 CJS_Result CJS_Field::isBoxChecked(CJS_Runtime* pRuntime,
2414                                    pdfium::span<v8::Local<v8::Value>> params) {
2415   int nIndex = -1;
2416   if (params.size() >= 1)
2417     nIndex = pRuntime->ToInt32(params[0]);
2418 
2419   CPDF_FormField* pFormField = GetFirstFormField();
2420   if (!pFormField)
2421     return CJS_Result::Failure(JSMessage::kBadObjectError);
2422 
2423   if (nIndex < 0 || nIndex >= pFormField->CountControls())
2424     return CJS_Result::Failure(JSMessage::kValueError);
2425 
2426   return CJS_Result::Success(
2427       pRuntime->NewBoolean((IsCheckBoxOrRadioButton(pFormField) &&
2428                             pFormField->GetControl(nIndex)->IsChecked() != 0)));
2429 }
2430 
isDefaultChecked(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2431 CJS_Result CJS_Field::isDefaultChecked(
2432     CJS_Runtime* pRuntime,
2433     pdfium::span<v8::Local<v8::Value>> params) {
2434   int nIndex = -1;
2435   if (params.size() >= 1)
2436     nIndex = pRuntime->ToInt32(params[0]);
2437 
2438   CPDF_FormField* pFormField = GetFirstFormField();
2439   if (!pFormField)
2440     return CJS_Result::Failure(JSMessage::kBadObjectError);
2441 
2442   if (nIndex < 0 || nIndex >= pFormField->CountControls())
2443     return CJS_Result::Failure(JSMessage::kValueError);
2444 
2445   return CJS_Result::Success(pRuntime->NewBoolean(
2446       (IsCheckBoxOrRadioButton(pFormField) &&
2447        pFormField->GetControl(nIndex)->IsDefaultChecked() != 0)));
2448 }
2449 
setAction(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2450 CJS_Result CJS_Field::setAction(CJS_Runtime* pRuntime,
2451                                 pdfium::span<v8::Local<v8::Value>> params) {
2452   return CJS_Result::Success();
2453 }
2454 
setFocus(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2455 CJS_Result CJS_Field::setFocus(CJS_Runtime* pRuntime,
2456                                pdfium::span<v8::Local<v8::Value>> params) {
2457   CPDF_FormField* pFormField = GetFirstFormField();
2458   if (!pFormField)
2459     return CJS_Result::Failure(JSMessage::kBadObjectError);
2460 
2461   int32_t nCount = pFormField->CountControls();
2462   if (nCount < 1)
2463     return CJS_Result::Failure(JSMessage::kBadObjectError);
2464 
2465   CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
2466   CPDFSDK_Widget* pWidget = nullptr;
2467   if (nCount == 1) {
2468     pWidget = pForm->GetWidget(pFormField->GetControl(0));
2469   } else {
2470     IPDF_Page* pPage = m_pFormFillEnv->GetCurrentPage();
2471     if (!pPage)
2472       return CJS_Result::Failure(JSMessage::kBadObjectError);
2473     CPDFSDK_PageView* pCurPageView = m_pFormFillEnv->GetOrCreatePageView(pPage);
2474     for (int32_t i = 0; i < nCount; i++) {
2475       if (CPDFSDK_Widget* pTempWidget =
2476               pForm->GetWidget(pFormField->GetControl(i))) {
2477         if (pTempWidget->GetPDFPage() == pCurPageView->GetPDFPage()) {
2478           pWidget = pTempWidget;
2479           break;
2480         }
2481       }
2482     }
2483   }
2484 
2485   if (pWidget) {
2486     ObservedPtr<CPDFSDK_Annot> pObserved(pWidget);
2487     m_pFormFillEnv->SetFocusAnnot(pObserved);
2488   }
2489 
2490   return CJS_Result::Success();
2491 }
2492 
setItems(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2493 CJS_Result CJS_Field::setItems(CJS_Runtime* pRuntime,
2494                                pdfium::span<v8::Local<v8::Value>> params) {
2495   return CJS_Result::Success();
2496 }
2497 
setLock(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2498 CJS_Result CJS_Field::setLock(CJS_Runtime* pRuntime,
2499                               pdfium::span<v8::Local<v8::Value>> params) {
2500   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2501 }
2502 
signatureGetModifications(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2503 CJS_Result CJS_Field::signatureGetModifications(
2504     CJS_Runtime* pRuntime,
2505     pdfium::span<v8::Local<v8::Value>> params) {
2506   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2507 }
2508 
signatureGetSeedValue(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2509 CJS_Result CJS_Field::signatureGetSeedValue(
2510     CJS_Runtime* pRuntime,
2511     pdfium::span<v8::Local<v8::Value>> params) {
2512   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2513 }
2514 
signatureInfo(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2515 CJS_Result CJS_Field::signatureInfo(CJS_Runtime* pRuntime,
2516                                     pdfium::span<v8::Local<v8::Value>> params) {
2517   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2518 }
2519 
signatureSetSeedValue(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2520 CJS_Result CJS_Field::signatureSetSeedValue(
2521     CJS_Runtime* pRuntime,
2522     pdfium::span<v8::Local<v8::Value>> params) {
2523   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2524 }
2525 
signatureSign(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2526 CJS_Result CJS_Field::signatureSign(CJS_Runtime* pRuntime,
2527                                     pdfium::span<v8::Local<v8::Value>> params) {
2528   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2529 }
2530 
signatureValidate(CJS_Runtime * pRuntime,pdfium::span<v8::Local<v8::Value>> params)2531 CJS_Result CJS_Field::signatureValidate(
2532     CJS_Runtime* pRuntime,
2533     pdfium::span<v8::Local<v8::Value>> params) {
2534   return CJS_Result::Failure(JSMessage::kNotSupportedError);
2535 }
2536 
SetDelay(bool bDelay)2537 void CJS_Field::SetDelay(bool bDelay) {
2538   m_bDelay = bDelay;
2539   if (m_bDelay)
2540     return;
2541 
2542   if (m_pJSDoc)
2543     m_pJSDoc->DoFieldDelay(m_FieldName, m_nFormControlIndex);
2544 }
2545 
AddDelay_Int(FIELD_PROP prop,int32_t n)2546 void CJS_Field::AddDelay_Int(FIELD_PROP prop, int32_t n) {
2547   auto pNewData =
2548       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2549   pNewData->num = n;
2550   m_pJSDoc->AddDelayData(std::move(pNewData));
2551 }
2552 
AddDelay_Bool(FIELD_PROP prop,bool b)2553 void CJS_Field::AddDelay_Bool(FIELD_PROP prop, bool b) {
2554   auto pNewData =
2555       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2556   pNewData->b = b;
2557   m_pJSDoc->AddDelayData(std::move(pNewData));
2558 }
2559 
AddDelay_String(FIELD_PROP prop,const ByteString & str)2560 void CJS_Field::AddDelay_String(FIELD_PROP prop, const ByteString& str) {
2561   auto pNewData =
2562       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2563   pNewData->bytestring = str;
2564   m_pJSDoc->AddDelayData(std::move(pNewData));
2565 }
2566 
AddDelay_Rect(FIELD_PROP prop,const CFX_FloatRect & rect)2567 void CJS_Field::AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect) {
2568   auto pNewData =
2569       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2570   pNewData->rect = rect;
2571   m_pJSDoc->AddDelayData(std::move(pNewData));
2572 }
2573 
AddDelay_WordArray(FIELD_PROP prop,const std::vector<uint32_t> & array)2574 void CJS_Field::AddDelay_WordArray(FIELD_PROP prop,
2575                                    const std::vector<uint32_t>& array) {
2576   auto pNewData =
2577       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2578   pNewData->wordarray = array;
2579   m_pJSDoc->AddDelayData(std::move(pNewData));
2580 }
2581 
AddDelay_WideStringArray(FIELD_PROP prop,const std::vector<WideString> & array)2582 void CJS_Field::AddDelay_WideStringArray(FIELD_PROP prop,
2583                                          const std::vector<WideString>& array) {
2584   auto pNewData =
2585       std::make_unique<CJS_DelayData>(prop, m_nFormControlIndex, m_FieldName);
2586   pNewData->widestringarray = array;
2587   m_pJSDoc->AddDelayData(std::move(pNewData));
2588 }
2589 
DoDelay(CPDFSDK_FormFillEnvironment * pFormFillEnv,CJS_DelayData * pData)2590 void CJS_Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
2591                         CJS_DelayData* pData) {
2592   DCHECK(pFormFillEnv);
2593   switch (pData->eProp) {
2594     case FP_BORDERSTYLE:
2595       SetBorderStyle(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2596                      pData->bytestring);
2597       break;
2598     case FP_CURRENTVALUEINDICES:
2599       SetCurrentValueIndices(pFormFillEnv, pData->sFieldName,
2600                              pData->nControlIndex, pData->wordarray);
2601       break;
2602     case FP_DISPLAY:
2603       SetDisplay(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2604                  pData->num);
2605       break;
2606     case FP_HIDDEN:
2607       SetHidden(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2608                 pData->b);
2609       break;
2610     case FP_LINEWIDTH:
2611       SetLineWidth(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2612                    pData->num);
2613       break;
2614     case FP_RECT:
2615       SetRect(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2616               pData->rect);
2617       break;
2618     case FP_VALUE:
2619       SetFieldValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
2620                     pData->widestringarray);
2621       break;
2622   }
2623 }
2624