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