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