Refactor fxjs_v8 and add embeddertests for it.
[pdfium.git] / fpdfsdk / src / javascript / Document.cpp
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 "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/Document.h"
13 #include "../../include/javascript/JS_EventHandler.h"
14 #include "../../include/javascript/JS_Context.h"
15 #include "../../include/javascript/JS_Runtime.h"
16 #include "../../include/javascript/app.h"
17 #include "../../include/javascript/Field.h"
18 #include "../../include/javascript/Icon.h"
19 #include "../../include/javascript/resource.h"
20
21 #include "../../../third_party/base/numerics/safe_math.h"
22
23 static v8::Isolate* GetIsolate(IFXJS_Context* cc) {
24   CJS_Context* pContext = (CJS_Context*)cc;
25   ASSERT(pContext != NULL);
26
27   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
28   ASSERT(pRuntime != NULL);
29
30   return pRuntime->GetIsolate();
31 }
32
33 BEGIN_JS_STATIC_CONST(CJS_PrintParamsObj)
34 END_JS_STATIC_CONST()
35
36 BEGIN_JS_STATIC_PROP(CJS_PrintParamsObj)
37 END_JS_STATIC_PROP()
38
39 BEGIN_JS_STATIC_METHOD(CJS_PrintParamsObj)
40 END_JS_STATIC_METHOD()
41
42 IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj)
43
44 PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject)
45     : CJS_EmbedObj(pJSObject) {
46   bUI = TRUE;
47   nStart = 0;
48   nEnd = 0;
49   bSilent = FALSE;
50   bShrinkToFit = FALSE;
51   bPrintAsImage = FALSE;
52   bReverse = FALSE;
53   bAnnotations = TRUE;
54 }
55
56 /* ---------------------- Document ---------------------- */
57
58 #define MINWIDTH 5.0f
59 #define MINHEIGHT 5.0f
60
61 BEGIN_JS_STATIC_CONST(CJS_Document)
62 END_JS_STATIC_CONST()
63
64 BEGIN_JS_STATIC_PROP(CJS_Document)
65 JS_STATIC_PROP_ENTRY(ADBE)
66 JS_STATIC_PROP_ENTRY(author)
67 JS_STATIC_PROP_ENTRY(baseURL)
68 JS_STATIC_PROP_ENTRY(bookmarkRoot)
69 JS_STATIC_PROP_ENTRY(calculate)
70 JS_STATIC_PROP_ENTRY(Collab)
71 JS_STATIC_PROP_ENTRY(creationDate)
72 JS_STATIC_PROP_ENTRY(creator)
73 JS_STATIC_PROP_ENTRY(delay)
74 JS_STATIC_PROP_ENTRY(dirty)
75 JS_STATIC_PROP_ENTRY(documentFileName)
76 JS_STATIC_PROP_ENTRY(external)
77 JS_STATIC_PROP_ENTRY(filesize)
78 JS_STATIC_PROP_ENTRY(icons)
79 JS_STATIC_PROP_ENTRY(info)
80 JS_STATIC_PROP_ENTRY(keywords)
81 JS_STATIC_PROP_ENTRY(layout)
82 JS_STATIC_PROP_ENTRY(media)
83 JS_STATIC_PROP_ENTRY(modDate)
84 JS_STATIC_PROP_ENTRY(mouseX)
85 JS_STATIC_PROP_ENTRY(mouseY)
86 JS_STATIC_PROP_ENTRY(numFields)
87 JS_STATIC_PROP_ENTRY(numPages)
88 JS_STATIC_PROP_ENTRY(pageNum)
89 JS_STATIC_PROP_ENTRY(pageWindowRect)
90 JS_STATIC_PROP_ENTRY(path)
91 JS_STATIC_PROP_ENTRY(producer)
92 JS_STATIC_PROP_ENTRY(subject)
93 JS_STATIC_PROP_ENTRY(title)
94 JS_STATIC_PROP_ENTRY(zoom)
95 JS_STATIC_PROP_ENTRY(zoomType)
96 END_JS_STATIC_PROP()
97
98 BEGIN_JS_STATIC_METHOD(CJS_Document)
99 JS_STATIC_METHOD_ENTRY(addAnnot)
100 JS_STATIC_METHOD_ENTRY(addField)
101 JS_STATIC_METHOD_ENTRY(addLink)
102 JS_STATIC_METHOD_ENTRY(addIcon)
103 JS_STATIC_METHOD_ENTRY(calculateNow)
104 JS_STATIC_METHOD_ENTRY(closeDoc)
105 JS_STATIC_METHOD_ENTRY(createDataObject)
106 JS_STATIC_METHOD_ENTRY(deletePages)
107 JS_STATIC_METHOD_ENTRY(exportAsText)
108 JS_STATIC_METHOD_ENTRY(exportAsFDF)
109 JS_STATIC_METHOD_ENTRY(exportAsXFDF)
110 JS_STATIC_METHOD_ENTRY(extractPages)
111 JS_STATIC_METHOD_ENTRY(getAnnot)
112 JS_STATIC_METHOD_ENTRY(getAnnots)
113 JS_STATIC_METHOD_ENTRY(getAnnot3D)
114 JS_STATIC_METHOD_ENTRY(getAnnots3D)
115 JS_STATIC_METHOD_ENTRY(getField)
116 JS_STATIC_METHOD_ENTRY(getIcon)
117 JS_STATIC_METHOD_ENTRY(getLinks)
118 JS_STATIC_METHOD_ENTRY(getNthFieldName)
119 JS_STATIC_METHOD_ENTRY(getOCGs)
120 JS_STATIC_METHOD_ENTRY(getPageBox)
121 JS_STATIC_METHOD_ENTRY(getPageNthWord)
122 JS_STATIC_METHOD_ENTRY(getPageNthWordQuads)
123 JS_STATIC_METHOD_ENTRY(getPageNumWords)
124 JS_STATIC_METHOD_ENTRY(getPrintParams)
125 JS_STATIC_METHOD_ENTRY(getURL)
126 JS_STATIC_METHOD_ENTRY(importAnFDF)
127 JS_STATIC_METHOD_ENTRY(importAnXFDF)
128 JS_STATIC_METHOD_ENTRY(importTextData)
129 JS_STATIC_METHOD_ENTRY(insertPages)
130 JS_STATIC_METHOD_ENTRY(mailForm)
131 JS_STATIC_METHOD_ENTRY(print)
132 JS_STATIC_METHOD_ENTRY(removeField)
133 JS_STATIC_METHOD_ENTRY(replacePages)
134 JS_STATIC_METHOD_ENTRY(resetForm)
135 JS_STATIC_METHOD_ENTRY(removeIcon)
136 JS_STATIC_METHOD_ENTRY(saveAs)
137 JS_STATIC_METHOD_ENTRY(submitForm)
138 JS_STATIC_METHOD_ENTRY(mailDoc)
139 END_JS_STATIC_METHOD()
140
141 IMPLEMENT_JS_CLASS(CJS_Document, Document)
142
143 FX_BOOL CJS_Document::InitInstance(IFXJS_Context* cc) {
144   CJS_Context* pContext = (CJS_Context*)cc;
145   ASSERT(pContext != NULL);
146
147   Document* pDoc = (Document*)GetEmbedObject();
148   ASSERT(pDoc != NULL);
149
150   pDoc->AttachDoc(pContext->GetReaderDocument());
151   pDoc->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
152   return TRUE;
153 };
154
155 /* --------------------------------- Document ---------------------------------
156  */
157
158 Document::Document(CJS_Object* pJSObject)
159     : CJS_EmbedObj(pJSObject),
160       m_isolate(NULL),
161       m_pIconTree(NULL),
162       m_pDocument(NULL),
163       m_cwBaseURL(L""),
164       m_bDelay(FALSE) {}
165
166 Document::~Document() {
167   if (m_pIconTree) {
168     m_pIconTree->DeleteIconTree();
169     delete m_pIconTree;
170     m_pIconTree = NULL;
171   }
172   for (int i = 0; i < m_DelayData.GetSize(); i++) {
173     if (CJS_DelayData* pData = m_DelayData.GetAt(i)) {
174       delete pData;
175       pData = NULL;
176       m_DelayData.SetAt(i, NULL);
177     }
178   }
179
180   m_DelayData.RemoveAll();
181   m_DelayAnnotData.RemoveAll();
182 }
183
184 // the total number of fileds in document.
185 FX_BOOL Document::numFields(IFXJS_Context* cc,
186                             CJS_PropValue& vp,
187                             CFX_WideString& sError) {
188   if (vp.IsSetting()) {
189     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
190     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
191     return FALSE;
192   }
193   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
194   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
195   vp << (int)pPDFForm->CountFields();
196   return TRUE;
197 }
198
199 FX_BOOL Document::dirty(IFXJS_Context* cc,
200                         CJS_PropValue& vp,
201                         CFX_WideString& sError) {
202   ASSERT(m_pDocument != NULL);
203
204   if (vp.IsGetting()) {
205     if (m_pDocument->GetChangeMark())
206       vp << true;
207     else
208       vp << false;
209   } else {
210     bool bChanged = false;
211
212     vp >> bChanged;
213
214     if (bChanged)
215       m_pDocument->SetChangeMark();
216     else
217       m_pDocument->ClearChangeMark();
218   }
219
220   return TRUE;
221 }
222
223 FX_BOOL Document::ADBE(IFXJS_Context* cc,
224                        CJS_PropValue& vp,
225                        CFX_WideString& sError) {
226   ASSERT(m_pDocument != NULL);
227
228   if (vp.IsGetting()) {
229     vp.SetNull();
230   } else {
231   }
232
233   return TRUE;
234 }
235
236 FX_BOOL Document::pageNum(IFXJS_Context* cc,
237                           CJS_PropValue& vp,
238                           CFX_WideString& sError) {
239   ASSERT(m_pDocument != NULL);
240
241   if (vp.IsGetting()) {
242     if (CPDFSDK_PageView* pPageView = m_pDocument->GetCurrentView()) {
243       vp << pPageView->GetPageIndex();
244     }
245   } else {
246     int iPageCount = m_pDocument->GetPageCount();
247     int iPageNum = 0;
248     vp >> iPageNum;
249
250     CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
251     if (iPageNum >= 0 && iPageNum < iPageCount) {
252       pEnv->JS_docgotoPage(iPageNum);
253     } else if (iPageNum >= iPageCount) {
254       pEnv->JS_docgotoPage(iPageCount - 1);
255     } else if (iPageNum < 0) {
256       pEnv->JS_docgotoPage(0);
257     }
258   }
259
260   return TRUE;
261 }
262
263 FX_BOOL Document::addAnnot(IFXJS_Context* cc,
264                            const CJS_Parameters& params,
265                            CJS_Value& vRet,
266                            CFX_WideString& sError) {
267   // Not supported.
268   return TRUE;
269 }
270
271 FX_BOOL Document::addField(IFXJS_Context* cc,
272                            const CJS_Parameters& params,
273                            CJS_Value& vRet,
274                            CFX_WideString& sError) {
275   // Not supported.
276   return TRUE;
277 }
278
279 FX_BOOL Document::exportAsText(IFXJS_Context* cc,
280                                const CJS_Parameters& params,
281                                CJS_Value& vRet,
282                                CFX_WideString& sError) {
283   // Unsafe, not supported.
284   return TRUE;
285 }
286
287 FX_BOOL Document::exportAsFDF(IFXJS_Context* cc,
288                               const CJS_Parameters& params,
289                               CJS_Value& vRet,
290                               CFX_WideString& sError) {
291   // Unsafe, not supported.
292   return TRUE;
293 }
294
295 FX_BOOL Document::exportAsXFDF(IFXJS_Context* cc,
296                                const CJS_Parameters& params,
297                                CJS_Value& vRet,
298                                CFX_WideString& sError) {
299   // Unsafe, not supported.
300   return TRUE;
301 }
302
303 // Maps a field object in PDF document to a JavaScript variable
304 // comment:
305 // note: the paremter cName, this is clue how to treat if the cName is not a
306 // valiable filed name in this document
307
308 FX_BOOL Document::getField(IFXJS_Context* cc,
309                            const CJS_Parameters& params,
310                            CJS_Value& vRet,
311                            CFX_WideString& sError) {
312   CJS_Context* pContext = (CJS_Context*)cc;
313   if (params.size() < 1) {
314     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
315     return FALSE;
316   }
317
318   CFX_WideString wideName = params[0].ToCFXWideString();
319
320   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
321   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
322   if (pPDFForm->CountFields(wideName) <= 0) {
323     vRet.SetNull();
324     return TRUE;
325   }
326
327   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
328   v8::Local<v8::Object> pFieldObj =
329       JS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext,
330                          JS_GetObjDefnID(pRuntime->GetIsolate(), L"Field"));
331
332   v8::Isolate* isolate = GetIsolate(cc);
333   CJS_Field* pJSField = (CJS_Field*)JS_GetPrivate(isolate, pFieldObj);
334   Field* pField = (Field*)pJSField->GetEmbedObject();
335   pField->AttachField(this, wideName);
336
337   vRet = pJSField;
338   return TRUE;
339 }
340
341 // Gets the name of the nth field in the document
342 FX_BOOL Document::getNthFieldName(IFXJS_Context* cc,
343                                   const CJS_Parameters& params,
344                                   CJS_Value& vRet,
345                                   CFX_WideString& sError) {
346   CJS_Context* pContext = (CJS_Context*)cc;
347   if (params.size() != 1) {
348     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
349     return FALSE;
350   }
351
352   int nIndex = params[0].ToInt();
353   if (nIndex < 0) {
354     sError = JSGetStringFromID(pContext, IDS_STRING_JSVALUEERROR);
355     return FALSE;
356   }
357
358   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
359   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
360   CPDF_FormField* pField = pPDFForm->GetField(nIndex);
361   if (!pField)
362     return FALSE;
363
364   vRet = pField->GetFullName().c_str();
365   return TRUE;
366 }
367
368 FX_BOOL Document::importAnFDF(IFXJS_Context* cc,
369                               const CJS_Parameters& params,
370                               CJS_Value& vRet,
371                               CFX_WideString& sError) {
372   // Unsafe, not supported.
373   return TRUE;
374 }
375
376 FX_BOOL Document::importAnXFDF(IFXJS_Context* cc,
377                                const CJS_Parameters& params,
378                                CJS_Value& vRet,
379                                CFX_WideString& sError) {
380   // Unsafe, not supported.
381   return TRUE;
382 }
383
384 FX_BOOL Document::importTextData(IFXJS_Context* cc,
385                                  const CJS_Parameters& params,
386                                  CJS_Value& vRet,
387                                  CFX_WideString& sError) {
388   // Unsafe, not supported.
389   return TRUE;
390 }
391
392 // exports the form data and mails the resulting fdf file as an attachment to
393 // all recipients.
394 // comment: need reader supports
395 // note:
396 // int CPDFSDK_Document::mailForm(FX_BOOL bUI,String cto,string ccc,string
397 // cbcc,string cSubject,string cms);
398
399 FX_BOOL Document::mailForm(IFXJS_Context* cc,
400                            const CJS_Parameters& params,
401                            CJS_Value& vRet,
402                            CFX_WideString& sError) {
403   ASSERT(m_pDocument != NULL);
404
405   if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
406     return FALSE;
407
408   int iLength = params.size();
409
410   FX_BOOL bUI = iLength > 0 ? params[0].ToBool() : TRUE;
411   CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString() : L"";
412   CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString() : L"";
413   CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString() : L"";
414   CFX_WideString cSubject = iLength > 4 ? params[4].ToCFXWideString() : L"";
415   CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString() : L"";
416
417   CPDFSDK_InterForm* pInterForm =
418       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
419   ASSERT(pInterForm != NULL);
420
421   CFX_ByteTextBuf textBuf;
422   if (!pInterForm->ExportFormToFDFTextBuf(textBuf))
423     return FALSE;
424
425   CJS_Context* pContext = (CJS_Context*)cc;
426   ASSERT(pContext != NULL);
427   CPDFDoc_Environment* pEnv = pContext->GetReaderApp();
428   ASSERT(pEnv != NULL);
429   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
430   ASSERT(pRuntime != NULL);
431
432   pRuntime->BeginBlock();
433   pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI,
434                        cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(),
435                        cMsg.c_str());
436   pRuntime->EndBlock();
437   return TRUE;
438 }
439
440 FX_BOOL Document::print(IFXJS_Context* cc,
441                         const CJS_Parameters& params,
442                         CJS_Value& vRet,
443                         CFX_WideString& sError) {
444   CJS_Context* pContext = (CJS_Context*)cc;
445   ASSERT(pContext != NULL);
446   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
447   ASSERT(pRuntime != NULL);
448
449   FX_BOOL bUI = TRUE;
450   int nStart = 0;
451   int nEnd = 0;
452   FX_BOOL bSilent = FALSE;
453   FX_BOOL bShrinkToFit = FALSE;
454   FX_BOOL bPrintAsImage = FALSE;
455   FX_BOOL bReverse = FALSE;
456   FX_BOOL bAnnotations = FALSE;
457
458   int nlength = params.size();
459   if (nlength == 9) {
460     if (params[8].GetType() == VT_fxobject) {
461       v8::Local<v8::Object> pObj = params[8].ToV8Object();
462       {
463         if (JS_GetObjDefnID(pObj) ==
464             JS_GetObjDefnID(pRuntime->GetIsolate(), L"PrintParamsObj")) {
465           if (CJS_Object* pJSObj = params[8].ToCJSObject()) {
466             if (PrintParamsObj* pprintparamsObj =
467                     (PrintParamsObj*)pJSObj->GetEmbedObject()) {
468               bUI = pprintparamsObj->bUI;
469               nStart = pprintparamsObj->nStart;
470               nEnd = pprintparamsObj->nEnd;
471               bSilent = pprintparamsObj->bSilent;
472               bShrinkToFit = pprintparamsObj->bShrinkToFit;
473               bPrintAsImage = pprintparamsObj->bPrintAsImage;
474               bReverse = pprintparamsObj->bReverse;
475               bAnnotations = pprintparamsObj->bAnnotations;
476             }
477           }
478         }
479       }
480     }
481   } else {
482     if (nlength >= 1)
483       bUI = params[0].ToBool();
484     if (nlength >= 2)
485       nStart = params[1].ToInt();
486     if (nlength >= 3)
487       nEnd = params[2].ToInt();
488     if (nlength >= 4)
489       bSilent = params[3].ToBool();
490     if (nlength >= 5)
491       bShrinkToFit = params[4].ToBool();
492     if (nlength >= 6)
493       bPrintAsImage = params[5].ToBool();
494     if (nlength >= 7)
495       bReverse = params[6].ToBool();
496     if (nlength >= 8)
497       bAnnotations = params[7].ToBool();
498   }
499
500   ASSERT(m_pDocument != NULL);
501
502   if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv()) {
503     pEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage,
504                       bReverse, bAnnotations);
505     return TRUE;
506   }
507   return FALSE;
508 }
509
510 // removes the specified field from the document.
511 // comment:
512 // note: if the filed name is not retional, adobe is dumb for it.
513
514 FX_BOOL Document::removeField(IFXJS_Context* cc,
515                               const CJS_Parameters& params,
516                               CJS_Value& vRet,
517                               CFX_WideString& sError) {
518   ASSERT(m_pDocument != NULL);
519
520   if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
521         m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM)))
522     return FALSE;
523
524   CJS_Context* pContext = (CJS_Context*)cc;
525   if (params.size() != 1) {
526     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
527     return FALSE;
528   }
529
530   CFX_WideString sFieldName = params[0].ToCFXWideString();
531   CPDFSDK_InterForm* pInterForm =
532       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
533   ASSERT(pInterForm != NULL);
534
535   CFX_PtrArray widgets;
536   pInterForm->GetWidgets(sFieldName, widgets);
537
538   int nSize = widgets.GetSize();
539
540   if (nSize > 0) {
541     for (int i = 0; i < nSize; i++) {
542       CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)widgets[i];
543       ASSERT(pWidget != NULL);
544
545       CPDF_Rect rcAnnot = pWidget->GetRect();
546       rcAnnot.left -= 1;
547       rcAnnot.bottom -= 1;
548       rcAnnot.right += 1;
549       rcAnnot.top += 1;
550
551       CFX_RectArray aRefresh;
552       aRefresh.Add(rcAnnot);
553
554       CPDF_Page* pPage = pWidget->GetPDFPage();
555       ASSERT(pPage != NULL);
556
557       CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage);
558       pPageView->DeleteAnnot(pWidget);
559
560       pPageView->UpdateRects(aRefresh);
561     }
562     m_pDocument->SetChangeMark();
563   }
564
565   return TRUE;
566 }
567
568 // reset filed values within a document.
569 // comment:
570 // note: if the fields names r not rational, aodbe is dumb for it.
571
572 FX_BOOL Document::resetForm(IFXJS_Context* cc,
573                             const CJS_Parameters& params,
574                             CJS_Value& vRet,
575                             CFX_WideString& sError) {
576   ASSERT(m_pDocument != NULL);
577
578   if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
579         m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
580         m_pDocument->GetPermissions(FPDFPERM_FILL_FORM)))
581     return FALSE;
582
583   CPDFSDK_InterForm* pInterForm =
584       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
585   ASSERT(pInterForm != NULL);
586
587   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
588   ASSERT(pPDFForm != NULL);
589
590   v8::Isolate* isolate = GetIsolate(cc);
591   CJS_Array aName(isolate);
592
593   if (params.size() > 0) {
594     switch (params[0].GetType()) {
595       default:
596         aName.Attach(params[0].ToV8Array());
597         break;
598       case VT_string:
599         aName.SetElement(0, params[0]);
600         break;
601     }
602
603     CFX_PtrArray aFields;
604
605     for (int i = 0, isz = aName.GetLength(); i < isz; i++) {
606       CJS_Value valElement(isolate);
607       aName.GetElement(i, valElement);
608       CFX_WideString swVal = valElement.ToCFXWideString();
609
610       for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; j++) {
611         aFields.Add((void*)pPDFForm->GetField(j, swVal));
612       }
613     }
614
615     if (aFields.GetSize() > 0) {
616       pPDFForm->ResetForm(aFields, TRUE, TRUE);
617       m_pDocument->SetChangeMark();
618     }
619   } else {
620     pPDFForm->ResetForm(TRUE);
621     m_pDocument->SetChangeMark();
622   }
623
624   return TRUE;
625 }
626
627 FX_BOOL Document::saveAs(IFXJS_Context* cc,
628                          const CJS_Parameters& params,
629                          CJS_Value& vRet,
630                          CFX_WideString& sError) {
631   // Unsafe, not supported.
632   return TRUE;
633 }
634
635 FX_BOOL Document::submitForm(IFXJS_Context* cc,
636                              const CJS_Parameters& params,
637                              CJS_Value& vRet,
638                              CFX_WideString& sError) {
639   ASSERT(m_pDocument != NULL);
640   CJS_Context* pContext = (CJS_Context*)cc;
641   int nSize = params.size();
642   if (nSize < 1) {
643     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
644     return FALSE;
645   }
646
647   CFX_WideString strURL;
648   FX_BOOL bFDF = TRUE;
649   FX_BOOL bEmpty = FALSE;
650   v8::Isolate* isolate = GetIsolate(cc);
651   CJS_Array aFields(isolate);
652
653   CJS_Value v = params[0];
654   if (v.GetType() == VT_string) {
655     strURL = params[0].ToCFXWideString();
656     if (nSize > 1)
657       bFDF = params[1].ToBool();
658     if (nSize > 2)
659       bEmpty = params[2].ToBool();
660     if (nSize > 3)
661       aFields.Attach(params[3].ToV8Array());
662   } else if (v.GetType() == VT_object) {
663     v8::Local<v8::Object> pObj = params[0].ToV8Object();
664     v8::Local<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"cURL");
665     if (!pValue.IsEmpty())
666       strURL =
667           CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
668     pValue = JS_GetObjectElement(isolate, pObj, L"bFDF");
669     bFDF = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
670     pValue = JS_GetObjectElement(isolate, pObj, L"bEmpty");
671     bEmpty = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
672     pValue = JS_GetObjectElement(isolate, pObj, L"aFields");
673     aFields.Attach(
674         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToV8Array());
675   }
676
677   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
678   CPDFSDK_InterForm* pInterForm =
679       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
680   CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
681   FX_BOOL bAll = (aFields.GetLength() == 0);
682   if (bAll && bEmpty) {
683     if (pPDFInterForm->CheckRequiredFields()) {
684       pRuntime->BeginBlock();
685       pInterForm->SubmitForm(strURL, FALSE);
686       pRuntime->EndBlock();
687     }
688     return TRUE;
689   }
690
691   CFX_PtrArray fieldObjects;
692   for (int i = 0, sz = aFields.GetLength(); i < sz; i++) {
693     CJS_Value valName(isolate);
694     aFields.GetElement(i, valName);
695
696     CFX_WideString sName = valName.ToCFXWideString();
697     CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
698     for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) {
699       CPDF_FormField* pField = pPDFForm->GetField(j, sName);
700       if (!bEmpty && pField->GetValue().IsEmpty())
701         continue;
702
703       fieldObjects.Add(pField);
704     }
705   }
706
707   if (pPDFInterForm->CheckRequiredFields(&fieldObjects, TRUE)) {
708     pRuntime->BeginBlock();
709     pInterForm->SubmitFields(strURL, fieldObjects, TRUE, !bFDF);
710     pRuntime->EndBlock();
711   }
712   return TRUE;
713 }
714
715 //////////////////////////////////////////////////////////////////////////////////////////////
716
717 void Document::AttachDoc(CPDFSDK_Document* pDoc) {
718   m_pDocument = pDoc;
719 }
720
721 CPDFSDK_Document* Document::GetReaderDoc() {
722   return m_pDocument;
723 }
724
725 FX_BOOL Document::ExtractFileName(CPDFSDK_Document* pDoc,
726                                   CFX_ByteString& strFileName) {
727   return FALSE;
728 }
729
730 FX_BOOL Document::ExtractFolderName(CPDFSDK_Document* pDoc,
731                                     CFX_ByteString& strFolderName) {
732   return FALSE;
733 }
734
735 FX_BOOL Document::bookmarkRoot(IFXJS_Context* cc,
736                                CJS_PropValue& vp,
737                                CFX_WideString& sError) {
738   return TRUE;
739 }
740
741 FX_BOOL Document::mailDoc(IFXJS_Context* cc,
742                           const CJS_Parameters& params,
743                           CJS_Value& vRet,
744                           CFX_WideString& sError) {
745   ASSERT(m_pDocument != NULL);
746
747   FX_BOOL bUI = TRUE;
748   CFX_WideString cTo = L"";
749   CFX_WideString cCc = L"";
750   CFX_WideString cBcc = L"";
751   CFX_WideString cSubject = L"";
752   CFX_WideString cMsg = L"";
753
754   if (params.size() >= 1)
755     bUI = params[0].ToBool();
756   if (params.size() >= 2)
757     cTo = params[1].ToCFXWideString();
758   if (params.size() >= 3)
759     cCc = params[2].ToCFXWideString();
760   if (params.size() >= 4)
761     cBcc = params[3].ToCFXWideString();
762   if (params.size() >= 5)
763     cSubject = params[4].ToCFXWideString();
764   if (params.size() >= 6)
765     cMsg = params[5].ToCFXWideString();
766
767   v8::Isolate* isolate = GetIsolate(cc);
768
769   if (params.size() >= 1 && params[0].GetType() == VT_object) {
770     v8::Local<v8::Object> pObj = params[0].ToV8Object();
771
772     v8::Local<v8::Value> pValue = JS_GetObjectElement(isolate, pObj, L"bUI");
773     bUI = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToInt();
774
775     pValue = JS_GetObjectElement(isolate, pObj, L"cTo");
776     cTo = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
777
778     pValue = JS_GetObjectElement(isolate, pObj, L"cCc");
779     cCc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
780
781     pValue = JS_GetObjectElement(isolate, pObj, L"cBcc");
782     cBcc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
783
784     pValue = JS_GetObjectElement(isolate, pObj, L"cSubject");
785     cSubject =
786         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
787
788     pValue = JS_GetObjectElement(isolate, pObj, L"cMsg");
789     cMsg = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
790   }
791
792   CJS_Context* pContext = (CJS_Context*)cc;
793   ASSERT(pContext != NULL);
794   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
795   ASSERT(pRuntime != NULL);
796
797   pRuntime->BeginBlock();
798   CPDFDoc_Environment* pEnv = pRuntime->GetReaderApp();
799   pEnv->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(),
800                        cBcc.c_str(), cMsg.c_str());
801   pRuntime->EndBlock();
802
803   return TRUE;
804 }
805
806 FX_BOOL Document::author(IFXJS_Context* cc,
807                          CJS_PropValue& vp,
808                          CFX_WideString& sError) {
809   ASSERT(m_pDocument != NULL);
810
811   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
812   if (!pDictionary)
813     return FALSE;
814
815   if (vp.IsGetting()) {
816     vp << pDictionary->GetUnicodeText("Author");
817     return TRUE;
818   } else {
819     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
820       return FALSE;
821
822     CFX_WideString csAuthor;
823     vp >> csAuthor;
824     pDictionary->SetAtString("Author", PDF_EncodeText(csAuthor));
825     m_pDocument->SetChangeMark();
826     return TRUE;
827   }
828 }
829
830 FX_BOOL Document::info(IFXJS_Context* cc,
831                        CJS_PropValue& vp,
832                        CFX_WideString& sError) {
833   ASSERT(m_pDocument != NULL);
834
835   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
836   if (!pDictionary)
837     return FALSE;
838
839   CFX_WideString cwAuthor = pDictionary->GetUnicodeText("Author");
840   CFX_WideString cwTitle = pDictionary->GetUnicodeText("Title");
841   CFX_WideString cwSubject = pDictionary->GetUnicodeText("Subject");
842   CFX_WideString cwKeywords = pDictionary->GetUnicodeText("Keywords");
843   CFX_WideString cwCreator = pDictionary->GetUnicodeText("Creator");
844   CFX_WideString cwProducer = pDictionary->GetUnicodeText("Producer");
845   CFX_WideString cwCreationDate = pDictionary->GetUnicodeText("CreationDate");
846   CFX_WideString cwModDate = pDictionary->GetUnicodeText("ModDate");
847   CFX_WideString cwTrapped = pDictionary->GetUnicodeText("Trapped");
848
849   v8::Isolate* isolate = GetIsolate(cc);
850   if (vp.IsGetting()) {
851     CJS_Context* pContext = (CJS_Context*)cc;
852     CJS_Runtime* pRuntime = pContext->GetJSRuntime();
853     v8::Local<v8::Object> pObj =
854         JS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext, -1);
855     JS_PutObjectString(isolate, pObj, L"Author", cwAuthor.c_str());
856     JS_PutObjectString(isolate, pObj, L"Title", cwTitle.c_str());
857     JS_PutObjectString(isolate, pObj, L"Subject", cwSubject.c_str());
858     JS_PutObjectString(isolate, pObj, L"Keywords", cwKeywords.c_str());
859     JS_PutObjectString(isolate, pObj, L"Creator", cwCreator.c_str());
860     JS_PutObjectString(isolate, pObj, L"Producer", cwProducer.c_str());
861     JS_PutObjectString(isolate, pObj, L"CreationDate", cwCreationDate.c_str());
862     JS_PutObjectString(isolate, pObj, L"ModDate", cwModDate.c_str());
863     JS_PutObjectString(isolate, pObj, L"Trapped", cwTrapped.c_str());
864
865     // It's to be compatible to non-standard info dictionary.
866     FX_POSITION pos = pDictionary->GetStartPos();
867     while (pos) {
868       CFX_ByteString bsKey;
869       CPDF_Object* pValueObj = pDictionary->GetNextElement(pos, bsKey);
870       CFX_WideString wsKey = CFX_WideString::FromUTF8(bsKey, bsKey.GetLength());
871       if ((pValueObj->GetType() == PDFOBJ_STRING) ||
872           (pValueObj->GetType() == PDFOBJ_NAME))
873         JS_PutObjectString(isolate, pObj, wsKey.c_str(),
874                            pValueObj->GetUnicodeText().c_str());
875       if (pValueObj->GetType() == PDFOBJ_NUMBER)
876         JS_PutObjectNumber(isolate, pObj, wsKey.c_str(),
877                            (float)pValueObj->GetNumber());
878       if (pValueObj->GetType() == PDFOBJ_BOOLEAN)
879         JS_PutObjectBoolean(isolate, pObj, wsKey.c_str(),
880                             (bool)pValueObj->GetInteger());
881     }
882     vp << pObj;
883   }
884   return TRUE;
885 }
886
887 FX_BOOL Document::creationDate(IFXJS_Context* cc,
888                                CJS_PropValue& vp,
889                                CFX_WideString& sError) {
890   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
891   if (!pDictionary)
892     return FALSE;
893
894   if (vp.IsGetting()) {
895     vp << pDictionary->GetUnicodeText("CreationDate");
896   } else {
897     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
898       return FALSE;
899
900     CFX_WideString csCreationDate;
901     vp >> csCreationDate;
902     pDictionary->SetAtString("CreationDate", PDF_EncodeText(csCreationDate));
903     m_pDocument->SetChangeMark();
904   }
905   return TRUE;
906 }
907
908 FX_BOOL Document::creator(IFXJS_Context* cc,
909                           CJS_PropValue& vp,
910                           CFX_WideString& sError) {
911   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
912   if (!pDictionary)
913     return FALSE;
914
915   if (vp.IsGetting()) {
916     vp << pDictionary->GetUnicodeText("Creator");
917   } else {
918     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
919       return FALSE;
920
921     CFX_WideString csCreator;
922     vp >> csCreator;
923     pDictionary->SetAtString("Creator", PDF_EncodeText(csCreator));
924     m_pDocument->SetChangeMark();
925   }
926   return TRUE;
927 }
928
929 FX_BOOL Document::delay(IFXJS_Context* cc,
930                         CJS_PropValue& vp,
931                         CFX_WideString& sError) {
932   if (vp.IsGetting()) {
933     vp << m_bDelay;
934   } else {
935     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
936       return FALSE;
937
938     vp >> m_bDelay;
939     if (m_bDelay) {
940       for (int i = 0, sz = m_DelayData.GetSize(); i < sz; i++)
941         delete m_DelayData.GetAt(i);
942
943       m_DelayData.RemoveAll();
944     } else {
945       CFX_ArrayTemplate<CJS_DelayData*> DelayDataToProcess;
946       for (int i = 0, sz = m_DelayData.GetSize(); i < sz; i++) {
947         if (CJS_DelayData* pData = m_DelayData.GetAt(i)) {
948           DelayDataToProcess.Add(pData);
949           m_DelayData.SetAt(i, NULL);
950         }
951       }
952       m_DelayData.RemoveAll();
953       for (int i = 0, sz = DelayDataToProcess.GetSize(); i < sz; i++) {
954         CJS_DelayData* pData = DelayDataToProcess.GetAt(i);
955         Field::DoDelay(m_pDocument, pData);
956         DelayDataToProcess.SetAt(i, NULL);
957         delete pData;
958       }
959     }
960   }
961   return TRUE;
962 }
963
964 FX_BOOL Document::keywords(IFXJS_Context* cc,
965                            CJS_PropValue& vp,
966                            CFX_WideString& sError) {
967   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
968   if (!pDictionary)
969     return FALSE;
970
971   if (vp.IsGetting()) {
972     vp << pDictionary->GetUnicodeText("Keywords");
973   } else {
974     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
975       return FALSE;
976
977     CFX_WideString csKeywords;
978     vp >> csKeywords;
979     pDictionary->SetAtString("Keywords", PDF_EncodeText(csKeywords));
980     m_pDocument->SetChangeMark();
981   }
982   return TRUE;
983 }
984
985 FX_BOOL Document::modDate(IFXJS_Context* cc,
986                           CJS_PropValue& vp,
987                           CFX_WideString& sError) {
988   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
989   if (!pDictionary)
990     return FALSE;
991
992   if (vp.IsGetting()) {
993     vp << pDictionary->GetUnicodeText("ModDate");
994   } else {
995     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
996       return FALSE;
997
998     CFX_WideString csmodDate;
999     vp >> csmodDate;
1000     pDictionary->SetAtString("ModDate", PDF_EncodeText(csmodDate));
1001     m_pDocument->SetChangeMark();
1002   }
1003   return TRUE;
1004 }
1005
1006 FX_BOOL Document::producer(IFXJS_Context* cc,
1007                            CJS_PropValue& vp,
1008                            CFX_WideString& sError) {
1009   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1010   if (!pDictionary)
1011     return FALSE;
1012
1013   if (vp.IsGetting()) {
1014     vp << pDictionary->GetUnicodeText("Producer");
1015   } else {
1016     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
1017       return FALSE;
1018
1019     CFX_WideString csproducer;
1020     vp >> csproducer;
1021     pDictionary->SetAtString("Producer", PDF_EncodeText(csproducer));
1022     m_pDocument->SetChangeMark();
1023   }
1024   return TRUE;
1025 }
1026
1027 FX_BOOL Document::subject(IFXJS_Context* cc,
1028                           CJS_PropValue& vp,
1029                           CFX_WideString& sError) {
1030   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1031   if (!pDictionary)
1032     return FALSE;
1033
1034   if (vp.IsGetting()) {
1035     vp << pDictionary->GetUnicodeText("Subject");
1036   } else {
1037     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
1038       return FALSE;
1039
1040     CFX_WideString cssubject;
1041     vp >> cssubject;
1042     pDictionary->SetAtString("Subject", PDF_EncodeText(cssubject));
1043     m_pDocument->SetChangeMark();
1044   }
1045   return TRUE;
1046 }
1047
1048 FX_BOOL Document::title(IFXJS_Context* cc,
1049                         CJS_PropValue& vp,
1050                         CFX_WideString& sError) {
1051   if (m_pDocument == NULL || m_pDocument->GetDocument() == NULL)
1052     return FALSE;
1053
1054   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1055   if (!pDictionary)
1056     return FALSE;
1057
1058   if (vp.IsGetting()) {
1059     vp << pDictionary->GetUnicodeText("Title");
1060   } else {
1061     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
1062       return FALSE;
1063
1064     CFX_WideString cstitle;
1065     vp >> cstitle;
1066     pDictionary->SetAtString("Title", PDF_EncodeText(cstitle));
1067     m_pDocument->SetChangeMark();
1068   }
1069   return TRUE;
1070 }
1071
1072 FX_BOOL Document::numPages(IFXJS_Context* cc,
1073                            CJS_PropValue& vp,
1074                            CFX_WideString& sError) {
1075   if (vp.IsSetting()) {
1076     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1077     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1078     return FALSE;
1079   }
1080   vp << m_pDocument->GetPageCount();
1081   return TRUE;
1082 }
1083
1084 FX_BOOL Document::external(IFXJS_Context* cc,
1085                            CJS_PropValue& vp,
1086                            CFX_WideString& sError) {
1087   // In Chrome case,should always return true.
1088   if (vp.IsGetting()) {
1089     vp << true;
1090   }
1091   return TRUE;
1092 }
1093
1094 FX_BOOL Document::filesize(IFXJS_Context* cc,
1095                            CJS_PropValue& vp,
1096                            CFX_WideString& sError) {
1097   if (vp.IsSetting()) {
1098     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1099     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1100     return FALSE;
1101   }
1102   vp << 0;
1103   return TRUE;
1104 }
1105
1106 FX_BOOL Document::mouseX(IFXJS_Context* cc,
1107                          CJS_PropValue& vp,
1108                          CFX_WideString& sError) {
1109   return TRUE;
1110 }
1111
1112 FX_BOOL Document::mouseY(IFXJS_Context* cc,
1113                          CJS_PropValue& vp,
1114                          CFX_WideString& sError) {
1115   return TRUE;
1116 }
1117
1118 FX_BOOL Document::baseURL(IFXJS_Context* cc,
1119                           CJS_PropValue& vp,
1120                           CFX_WideString& sError) {
1121   if (vp.IsGetting()) {
1122     vp << m_cwBaseURL;
1123   } else {
1124     vp >> m_cwBaseURL;
1125   }
1126   return TRUE;
1127 }
1128
1129 FX_BOOL Document::calculate(IFXJS_Context* cc,
1130                             CJS_PropValue& vp,
1131                             CFX_WideString& sError) {
1132   ASSERT(m_pDocument != NULL);
1133
1134   CPDFSDK_InterForm* pInterForm =
1135       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1136   ASSERT(pInterForm != NULL);
1137
1138   if (vp.IsGetting()) {
1139     if (pInterForm->IsCalculateEnabled())
1140       vp << true;
1141     else
1142       vp << false;
1143   } else {
1144     bool bCalculate;
1145     vp >> bCalculate;
1146
1147     pInterForm->EnableCalculate(bCalculate);
1148   }
1149
1150   return TRUE;
1151 }
1152
1153 FX_BOOL Document::documentFileName(IFXJS_Context* cc,
1154                                    CJS_PropValue& vp,
1155                                    CFX_WideString& sError) {
1156   if (vp.IsSetting()) {
1157     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1158     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1159     return FALSE;
1160   }
1161   CFX_WideString wsFilePath = m_pDocument->GetPath();
1162   int32_t i = wsFilePath.GetLength() - 1;
1163   for (; i >= 0; i--) {
1164     if (wsFilePath.GetAt(i) == L'\\' || wsFilePath.GetAt(i) == L'/')
1165       break;
1166   }
1167   if (i >= 0 && i < wsFilePath.GetLength() - 1) {
1168     vp << (wsFilePath.GetBuffer(wsFilePath.GetLength()) + i + 1);
1169   } else {
1170     vp << L"";
1171   }
1172   return TRUE;
1173 }
1174
1175 CFX_WideString Document::ReversalStr(CFX_WideString cbFrom) {
1176   size_t iLength = cbFrom.GetLength();
1177   pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1178   iSize *= (iLength + 1);
1179   wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1180   wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1181
1182   for (size_t i = 0; i < iLength; i++) {
1183     pResult[i] = *(pFrom + iLength - i - 1);
1184   }
1185   pResult[iLength] = L'\0';
1186
1187   cbFrom.ReleaseBuffer();
1188   CFX_WideString cbRet = CFX_WideString(pResult);
1189   free(pResult);
1190   pResult = NULL;
1191   return cbRet;
1192 }
1193
1194 CFX_WideString Document::CutString(CFX_WideString cbFrom) {
1195   size_t iLength = cbFrom.GetLength();
1196   pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1197   iSize *= (iLength + 1);
1198   wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1199   wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1200
1201   for (size_t i = 0; i < iLength; i++) {
1202     if (pFrom[i] == L'\\' || pFrom[i] == L'/') {
1203       pResult[i] = L'\0';
1204       break;
1205     }
1206     pResult[i] = pFrom[i];
1207   }
1208   pResult[iLength] = L'\0';
1209
1210   cbFrom.ReleaseBuffer();
1211   CFX_WideString cbRet = CFX_WideString(pResult);
1212   free(pResult);
1213   pResult = NULL;
1214   return cbRet;
1215 }
1216
1217 FX_BOOL Document::path(IFXJS_Context* cc,
1218                        CJS_PropValue& vp,
1219                        CFX_WideString& sError) {
1220   if (vp.IsSetting()) {
1221     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1222     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1223     return FALSE;
1224   }
1225   vp << app::SysPathToPDFPath(m_pDocument->GetPath());
1226   return TRUE;
1227 }
1228
1229 FX_BOOL Document::pageWindowRect(IFXJS_Context* cc,
1230                                  CJS_PropValue& vp,
1231                                  CFX_WideString& sError) {
1232   return TRUE;
1233 }
1234
1235 FX_BOOL Document::layout(IFXJS_Context* cc,
1236                          CJS_PropValue& vp,
1237                          CFX_WideString& sError) {
1238   return TRUE;
1239 }
1240
1241 FX_BOOL Document::addLink(IFXJS_Context* cc,
1242                           const CJS_Parameters& params,
1243                           CJS_Value& vRet,
1244                           CFX_WideString& sError) {
1245   return TRUE;
1246 }
1247
1248 FX_BOOL Document::closeDoc(IFXJS_Context* cc,
1249                            const CJS_Parameters& params,
1250                            CJS_Value& vRet,
1251                            CFX_WideString& sError) {
1252   ASSERT(m_pDocument != NULL);
1253   return TRUE;
1254 }
1255
1256 FX_BOOL Document::getPageBox(IFXJS_Context* cc,
1257                              const CJS_Parameters& params,
1258                              CJS_Value& vRet,
1259                              CFX_WideString& sError) {
1260   return TRUE;
1261 }
1262
1263 FX_BOOL Document::getAnnot(IFXJS_Context* cc,
1264                            const CJS_Parameters& params,
1265                            CJS_Value& vRet,
1266                            CFX_WideString& sError) {
1267   return TRUE;
1268 }
1269
1270 FX_BOOL Document::getAnnots(IFXJS_Context* cc,
1271                             const CJS_Parameters& params,
1272                             CJS_Value& vRet,
1273                             CFX_WideString& sError) {
1274   vRet.SetNull();
1275   return TRUE;
1276 }
1277
1278 FX_BOOL Document::getAnnot3D(IFXJS_Context* cc,
1279                              const CJS_Parameters& params,
1280                              CJS_Value& vRet,
1281                              CFX_WideString& sError) {
1282   vRet.SetNull();
1283   return TRUE;
1284 }
1285
1286 FX_BOOL Document::getAnnots3D(IFXJS_Context* cc,
1287                               const CJS_Parameters& params,
1288                               CJS_Value& vRet,
1289                               CFX_WideString& sError) {
1290   vRet = VT_undefined;
1291   return TRUE;
1292 }
1293
1294 FX_BOOL Document::getOCGs(IFXJS_Context* cc,
1295                           const CJS_Parameters& params,
1296                           CJS_Value& vRet,
1297                           CFX_WideString& sError) {
1298   return TRUE;
1299 }
1300
1301 FX_BOOL Document::getLinks(IFXJS_Context* cc,
1302                            const CJS_Parameters& params,
1303                            CJS_Value& vRet,
1304                            CFX_WideString& sError) {
1305   return TRUE;
1306 }
1307
1308 bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect) {
1309   return (rect.left <= LinkRect.left && rect.top <= LinkRect.top &&
1310           rect.right >= LinkRect.right && rect.bottom >= LinkRect.bottom);
1311 }
1312
1313 void IconTree::InsertIconElement(IconElement* pNewIcon) {
1314   if (!pNewIcon)
1315     return;
1316
1317   if (m_pHead == NULL && m_pEnd == NULL) {
1318     m_pHead = m_pEnd = pNewIcon;
1319     m_iLength++;
1320   } else {
1321     m_pEnd->NextIcon = pNewIcon;
1322     m_pEnd = pNewIcon;
1323     m_iLength++;
1324   }
1325 }
1326
1327 void IconTree::DeleteIconTree() {
1328   if (!m_pHead || !m_pEnd)
1329     return;
1330
1331   IconElement* pTemp = NULL;
1332   while (m_pEnd != m_pHead) {
1333     pTemp = m_pHead;
1334     m_pHead = m_pHead->NextIcon;
1335     delete pTemp;
1336   }
1337
1338   delete m_pEnd;
1339   m_pHead = NULL;
1340   m_pEnd = NULL;
1341 }
1342
1343 int IconTree::GetLength() {
1344   return m_iLength;
1345 }
1346
1347 IconElement* IconTree::operator[](int iIndex) {
1348   if (iIndex >= 0 && iIndex <= m_iLength) {
1349     IconElement* pTemp = m_pHead;
1350     for (int i = 0; i < iIndex; i++) {
1351       pTemp = pTemp->NextIcon;
1352     }
1353     return pTemp;
1354   }
1355   return NULL;
1356 }
1357
1358 FX_BOOL Document::addIcon(IFXJS_Context* cc,
1359                           const CJS_Parameters& params,
1360                           CJS_Value& vRet,
1361                           CFX_WideString& sError) {
1362   CJS_Context* pContext = (CJS_Context*)cc;
1363   if (params.size() != 2) {
1364     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1365     return FALSE;
1366   }
1367   CFX_WideString swIconName = params[0].ToCFXWideString();
1368
1369   if (params[1].GetType() != VT_object) {
1370     sError = JSGetStringFromID(pContext, IDS_STRING_JSTYPEERROR);
1371     return FALSE;
1372   }
1373   v8::Local<v8::Object> pJSIcon = params[1].ToV8Object();
1374
1375   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1376   if (JS_GetObjDefnID(pJSIcon) !=
1377       JS_GetObjDefnID(pRuntime->GetIsolate(), L"Icon")) {
1378     sError = JSGetStringFromID(pContext, IDS_STRING_JSTYPEERROR);
1379     return FALSE;
1380   }
1381
1382   CJS_EmbedObj* pEmbedObj = params[1].ToCJSObject()->GetEmbedObject();
1383   if (!pEmbedObj) {
1384     sError = JSGetStringFromID(pContext, IDS_STRING_JSTYPEERROR);
1385     return FALSE;
1386   }
1387
1388   Icon* pIcon = (Icon*)pEmbedObj;
1389   if (!m_pIconTree)
1390     m_pIconTree = new IconTree();
1391
1392   IconElement* pNewIcon = new IconElement();
1393   pNewIcon->IconName = swIconName;
1394   pNewIcon->NextIcon = NULL;
1395   pNewIcon->IconStream = pIcon;
1396   m_pIconTree->InsertIconElement(pNewIcon);
1397   return TRUE;
1398 }
1399
1400 FX_BOOL Document::icons(IFXJS_Context* cc,
1401                         CJS_PropValue& vp,
1402                         CFX_WideString& sError) {
1403   if (vp.IsSetting()) {
1404     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1405     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
1406     return FALSE;
1407   }
1408
1409   if (!m_pIconTree) {
1410     vp.SetNull();
1411     return TRUE;
1412   }
1413
1414   CJS_Array Icons(m_isolate);
1415   IconElement* pIconElement = NULL;
1416   int iIconTreeLength = m_pIconTree->GetLength();
1417
1418   CJS_Context* pContext = (CJS_Context*)cc;
1419   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1420
1421   for (int i = 0; i < iIconTreeLength; i++) {
1422     pIconElement = (*m_pIconTree)[i];
1423
1424     v8::Local<v8::Object> pObj =
1425         JS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext,
1426                            JS_GetObjDefnID(pRuntime->GetIsolate(), L"Icon"));
1427     if (pObj.IsEmpty())
1428       return FALSE;
1429
1430     CJS_Icon* pJS_Icon = (CJS_Icon*)JS_GetPrivate(pObj);
1431     if (!pJS_Icon)
1432       return FALSE;
1433
1434     Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1435     if (!pIcon)
1436       return FALSE;
1437
1438     pIcon->SetStream(pIconElement->IconStream->GetStream());
1439     pIcon->SetIconName(pIconElement->IconName);
1440     Icons.SetElement(i, CJS_Value(m_isolate, pJS_Icon));
1441   }
1442
1443   vp << Icons;
1444   return TRUE;
1445 }
1446
1447 FX_BOOL Document::getIcon(IFXJS_Context* cc,
1448                           const CJS_Parameters& params,
1449                           CJS_Value& vRet,
1450                           CFX_WideString& sError) {
1451   CJS_Context* pContext = (CJS_Context*)cc;
1452   if (params.size() != 1) {
1453     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1454     return FALSE;
1455   }
1456
1457   if (!m_pIconTree)
1458     return FALSE;
1459   CFX_WideString swIconName = params[0].ToCFXWideString();
1460   int iIconCounts = m_pIconTree->GetLength();
1461
1462   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1463
1464   for (int i = 0; i < iIconCounts; i++) {
1465     if ((*m_pIconTree)[i]->IconName == swIconName) {
1466       Icon* pRetIcon = (*m_pIconTree)[i]->IconStream;
1467
1468       v8::Local<v8::Object> pObj =
1469           JS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext,
1470                              JS_GetObjDefnID(pRuntime->GetIsolate(), L"Icon"));
1471       if (pObj.IsEmpty())
1472         return FALSE;
1473
1474       CJS_Icon* pJS_Icon = (CJS_Icon*)JS_GetPrivate(pObj);
1475       if (!pJS_Icon)
1476         return FALSE;
1477
1478       Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1479       if (!pIcon)
1480         return FALSE;
1481
1482       pIcon->SetIconName(swIconName);
1483       pIcon->SetStream(pRetIcon->GetStream());
1484       vRet = pJS_Icon;
1485       return TRUE;
1486     }
1487   }
1488
1489   return FALSE;
1490 }
1491
1492 FX_BOOL Document::removeIcon(IFXJS_Context* cc,
1493                              const CJS_Parameters& params,
1494                              CJS_Value& vRet,
1495                              CFX_WideString& sError) {
1496   // Unsafe, no supported.
1497   return TRUE;
1498 }
1499
1500 FX_BOOL Document::createDataObject(IFXJS_Context* cc,
1501                                    const CJS_Parameters& params,
1502                                    CJS_Value& vRet,
1503                                    CFX_WideString& sError) {
1504   // Unsafe, not implemented.
1505   return TRUE;
1506 }
1507
1508 FX_BOOL Document::media(IFXJS_Context* cc,
1509                         CJS_PropValue& vp,
1510                         CFX_WideString& sError) {
1511   return TRUE;
1512 }
1513
1514 FX_BOOL Document::calculateNow(IFXJS_Context* cc,
1515                                const CJS_Parameters& params,
1516                                CJS_Value& vRet,
1517                                CFX_WideString& sError) {
1518   ASSERT(m_pDocument != NULL);
1519
1520   if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
1521         m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
1522         m_pDocument->GetPermissions(FPDFPERM_FILL_FORM)))
1523     return FALSE;
1524
1525   CPDFSDK_InterForm* pInterForm =
1526       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1527   ASSERT(pInterForm != NULL);
1528   pInterForm->OnCalculate();
1529   return TRUE;
1530 }
1531
1532 FX_BOOL Document::Collab(IFXJS_Context* cc,
1533                          CJS_PropValue& vp,
1534                          CFX_WideString& sError) {
1535   return TRUE;
1536 }
1537
1538 FX_BOOL Document::getPageNthWord(IFXJS_Context* cc,
1539                                  const CJS_Parameters& params,
1540                                  CJS_Value& vRet,
1541                                  CFX_WideString& sError) {
1542   ASSERT(m_pDocument != NULL);
1543
1544   if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1545     return FALSE;
1546
1547   int nPageNo = params.GetSize() > 0 ? params[0].ToInt() : 0;
1548   int nWordNo = params.GetSize() > 1 ? params[1].ToInt() : 0;
1549   bool bStrip = params.GetSize() > 2 ? params[2].ToBool() : true;
1550
1551   CPDF_Document* pDocument = m_pDocument->GetDocument();
1552   if (!pDocument)
1553     return FALSE;
1554
1555   CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1556   if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) {
1557     sError = JSGetStringFromID(pContext, IDS_STRING_JSVALUEERROR);
1558     return FALSE;
1559   }
1560
1561   CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1562   if (!pPageDict)
1563     return FALSE;
1564
1565   CPDF_Page page;
1566   page.Load(pDocument, pPageDict);
1567   page.StartParse();
1568   page.ParseContent();
1569
1570   FX_POSITION pos = page.GetFirstObjectPosition();
1571
1572   int nWords = 0;
1573
1574   CFX_WideString swRet;
1575
1576   while (pos) {
1577     if (CPDF_PageObject* pPageObj = page.GetNextObject(pos)) {
1578       if (pPageObj->m_Type == PDFPAGE_TEXT) {
1579         int nObjWords = CountWords((CPDF_TextObject*)pPageObj);
1580
1581         if (nWords + nObjWords >= nWordNo) {
1582           swRet = GetObjWordStr((CPDF_TextObject*)pPageObj, nWordNo - nWords);
1583           break;
1584         }
1585
1586         nWords += nObjWords;
1587       }
1588     }
1589   }
1590
1591   if (bStrip) {
1592     swRet.TrimLeft();
1593     swRet.TrimRight();
1594   }
1595
1596   vRet = swRet.c_str();
1597   return TRUE;
1598 }
1599
1600 FX_BOOL Document::getPageNthWordQuads(IFXJS_Context* cc,
1601                                       const CJS_Parameters& params,
1602                                       CJS_Value& vRet,
1603                                       CFX_WideString& sError) {
1604   ASSERT(m_pDocument != NULL);
1605
1606   if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1607     return FALSE;
1608
1609   return FALSE;
1610 }
1611
1612 FX_BOOL Document::getPageNumWords(IFXJS_Context* cc,
1613                                   const CJS_Parameters& params,
1614                                   CJS_Value& vRet,
1615                                   CFX_WideString& sError) {
1616   ASSERT(m_pDocument != NULL);
1617
1618   if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
1619     return FALSE;
1620
1621   int nPageNo = params.GetSize() > 0 ? params[0].ToInt() : 0;
1622
1623   CPDF_Document* pDocument = m_pDocument->GetDocument();
1624   ASSERT(pDocument != NULL);
1625
1626   CJS_Context* pContext = static_cast<CJS_Context*>(cc);
1627   if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) {
1628     sError = JSGetStringFromID(pContext, IDS_STRING_JSVALUEERROR);
1629     return FALSE;
1630   }
1631
1632   CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1633   if (!pPageDict)
1634     return FALSE;
1635
1636   CPDF_Page page;
1637   page.Load(pDocument, pPageDict);
1638   page.StartParse();
1639   page.ParseContent();
1640
1641   FX_POSITION pos = page.GetFirstObjectPosition();
1642
1643   int nWords = 0;
1644
1645   while (pos) {
1646     if (CPDF_PageObject* pPageObj = page.GetNextObject(pos)) {
1647       if (pPageObj->m_Type == PDFPAGE_TEXT) {
1648         CPDF_TextObject* pTextObj = (CPDF_TextObject*)pPageObj;
1649         nWords += CountWords(pTextObj);
1650       }
1651     }
1652   }
1653
1654   vRet = nWords;
1655
1656   return TRUE;
1657 }
1658
1659 FX_BOOL Document::getPrintParams(IFXJS_Context* cc,
1660                                  const CJS_Parameters& params,
1661                                  CJS_Value& vRet,
1662                                  CFX_WideString& sError) {
1663   CJS_Context* pContext = (CJS_Context*)cc;
1664   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1665   v8::Local<v8::Object> pRetObj = JS_NewFxDynamicObj(
1666       pRuntime->GetIsolate(), pContext,
1667       JS_GetObjDefnID(pRuntime->GetIsolate(), L"PrintParamsObj"));
1668
1669   // Not implemented yet.
1670
1671   vRet = pRetObj;
1672   return TRUE;
1673 }
1674
1675 #define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF)
1676
1677 int Document::CountWords(CPDF_TextObject* pTextObj) {
1678   if (!pTextObj)
1679     return 0;
1680
1681   int nWords = 0;
1682
1683   CPDF_Font* pFont = pTextObj->GetFont();
1684   if (!pFont)
1685     return 0;
1686
1687   FX_BOOL bIsLatin = FALSE;
1688
1689   for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) {
1690     FX_DWORD charcode = -1;
1691     FX_FLOAT kerning;
1692
1693     pTextObj->GetCharInfo(i, charcode, kerning);
1694     CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1695
1696     FX_WORD unicode = 0;
1697     if (swUnicode.GetLength() > 0)
1698       unicode = swUnicode[0];
1699
1700     if (ISLATINWORD(unicode) && bIsLatin)
1701       continue;
1702
1703     bIsLatin = ISLATINWORD(unicode);
1704     if (unicode != 0x20)
1705       nWords++;
1706   }
1707
1708   return nWords;
1709 }
1710
1711 CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj,
1712                                        int nWordIndex) {
1713   ASSERT(pTextObj != NULL);
1714
1715   CFX_WideString swRet;
1716
1717   CPDF_Font* pFont = pTextObj->GetFont();
1718   if (!pFont)
1719     return L"";
1720
1721   int nWords = 0;
1722   FX_BOOL bIsLatin = FALSE;
1723
1724   for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) {
1725     FX_DWORD charcode = -1;
1726     FX_FLOAT kerning;
1727
1728     pTextObj->GetCharInfo(i, charcode, kerning);
1729     CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1730
1731     FX_WORD unicode = 0;
1732     if (swUnicode.GetLength() > 0)
1733       unicode = swUnicode[0];
1734
1735     if (ISLATINWORD(unicode) && bIsLatin) {
1736     } else {
1737       bIsLatin = ISLATINWORD(unicode);
1738       if (unicode != 0x20)
1739         nWords++;
1740     }
1741
1742     if (nWords - 1 == nWordIndex)
1743       swRet += unicode;
1744   }
1745
1746   return swRet;
1747 }
1748
1749 FX_BOOL Document::zoom(IFXJS_Context* cc,
1750                        CJS_PropValue& vp,
1751                        CFX_WideString& sError) {
1752   return TRUE;
1753 }
1754
1755 /**
1756 (none,  NoVary)
1757 (fitP,  FitPage)
1758 (fitW,  FitWidth)
1759 (fitH,  FitHeight)
1760 (fitV,  FitVisibleWidth)
1761 (pref,  Preferred)
1762 (refW,  ReflowWidth)
1763 */
1764
1765 FX_BOOL Document::zoomType(IFXJS_Context* cc,
1766                            CJS_PropValue& vp,
1767                            CFX_WideString& sError) {
1768   return TRUE;
1769 }
1770
1771 FX_BOOL Document::deletePages(IFXJS_Context* cc,
1772                               const CJS_Parameters& params,
1773                               CJS_Value& vRet,
1774                               CFX_WideString& sError) {
1775   // Unsafe, no supported.
1776   return TRUE;
1777 }
1778
1779 FX_BOOL Document::extractPages(IFXJS_Context* cc,
1780                                const CJS_Parameters& params,
1781                                CJS_Value& vRet,
1782                                CFX_WideString& sError) {
1783   // Unsafe, not supported.
1784   return TRUE;
1785 }
1786
1787 FX_BOOL Document::insertPages(IFXJS_Context* cc,
1788                               const CJS_Parameters& params,
1789                               CJS_Value& vRet,
1790                               CFX_WideString& sError) {
1791   // Unsafe, not supported.
1792   return TRUE;
1793 }
1794
1795 FX_BOOL Document::replacePages(IFXJS_Context* cc,
1796                                const CJS_Parameters& params,
1797                                CJS_Value& vRet,
1798                                CFX_WideString& sError) {
1799   // Unsafe, not supported.
1800   return TRUE;
1801 }
1802
1803 FX_BOOL Document::getURL(IFXJS_Context* cc,
1804                          const CJS_Parameters& params,
1805                          CJS_Value& vRet,
1806                          CFX_WideString& sError) {
1807   // Unsafe, not supported.
1808   return TRUE;
1809 }
1810
1811 void Document::AddDelayData(CJS_DelayData* pData) {
1812   m_DelayData.Add(pData);
1813 }
1814
1815 void Document::DoFieldDelay(const CFX_WideString& sFieldName,
1816                             int nControlIndex) {
1817   CFX_DWordArray DelArray;
1818   CFX_ArrayTemplate<CJS_DelayData*> DelayDataForFieldAndControlIndex;
1819
1820   for (int i = 0, sz = m_DelayData.GetSize(); i < sz; i++) {
1821     if (CJS_DelayData* pData = m_DelayData.GetAt(i)) {
1822       if (pData->sFieldName == sFieldName &&
1823           pData->nControlIndex == nControlIndex) {
1824         DelayDataForFieldAndControlIndex.Add(pData);
1825         m_DelayData.SetAt(i, NULL);
1826         DelArray.Add(i);
1827       }
1828     }
1829   }
1830
1831   for (int j = DelArray.GetSize() - 1; j >= 0; j--) {
1832     m_DelayData.RemoveAt(DelArray[j]);
1833   }
1834
1835   for (int i = 0, sz = DelayDataForFieldAndControlIndex.GetSize(); i < sz;
1836        i++) {
1837     CJS_DelayData* pData = DelayDataForFieldAndControlIndex.GetAt(i);
1838     Field::DoDelay(m_pDocument, pData);
1839     DelayDataForFieldAndControlIndex.SetAt(i, NULL);
1840     delete pData;
1841   }
1842 }
1843
1844 void Document::AddDelayAnnotData(CJS_AnnotObj* pData) {
1845   m_DelayAnnotData.Add(pData);
1846 }
1847
1848 void Document::DoAnnotDelay() {
1849   CFX_DWordArray DelArray;
1850
1851   for (int j = DelArray.GetSize() - 1; j >= 0; j--) {
1852     m_DelayData.RemoveAt(DelArray[j]);
1853   }
1854 }
1855
1856 CJS_Document* Document::GetCJSDoc() const {
1857   return static_cast<CJS_Document*>(m_pJSObject);
1858 }