Remove JavaScript.h
[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/IJavaScript.h"
8 #include "../../include/javascript/JS_Define.h"
9 #include "../../include/javascript/JS_Object.h"
10 #include "../../include/javascript/JS_Value.h"
11 #include "../../include/javascript/Document.h"
12 #include "../../include/javascript/JS_EventHandler.h"
13 #include "../../include/javascript/JS_Context.h"
14 #include "../../include/javascript/JS_Runtime.h"
15 #include "../../include/javascript/app.h"
16 #include "../../include/javascript/Field.h"
17 #include "../../include/javascript/Icon.h"
18 #include "../../include/javascript/resource.h"
19
20 #include "../../../third_party/base/numerics/safe_math.h"
21
22 static v8::Isolate* GetIsolate(IFXJS_Context* cc) {
23   CJS_Context* pContext = (CJS_Context*)cc;
24   ASSERT(pContext != NULL);
25
26   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
27   ASSERT(pRuntime != NULL);
28
29   return pRuntime->GetIsolate();
30 }
31
32 BEGIN_JS_STATIC_CONST(CJS_PrintParamsObj)
33 END_JS_STATIC_CONST()
34
35 BEGIN_JS_STATIC_PROP(CJS_PrintParamsObj)
36 END_JS_STATIC_PROP()
37
38 BEGIN_JS_STATIC_METHOD(CJS_PrintParamsObj)
39 END_JS_STATIC_METHOD()
40
41 IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj)
42
43 PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject)
44     : CJS_EmbedObj(pJSObject) {
45   bUI = TRUE;
46   nStart = 0;
47   nEnd = 0;
48   bSilent = FALSE;
49   bShrinkToFit = FALSE;
50   bPrintAsImage = FALSE;
51   bReverse = FALSE;
52   bAnnotations = TRUE;
53 }
54
55 /* ---------------------- Document ---------------------- */
56
57 #define MINWIDTH 5.0f
58 #define MINHEIGHT 5.0f
59
60 BEGIN_JS_STATIC_CONST(CJS_Document)
61 END_JS_STATIC_CONST()
62
63 BEGIN_JS_STATIC_PROP(CJS_Document)
64 JS_STATIC_PROP_ENTRY(ADBE)
65 JS_STATIC_PROP_ENTRY(author)
66 JS_STATIC_PROP_ENTRY(baseURL)
67 JS_STATIC_PROP_ENTRY(bookmarkRoot)
68 JS_STATIC_PROP_ENTRY(calculate)
69 JS_STATIC_PROP_ENTRY(Collab)
70 JS_STATIC_PROP_ENTRY(creationDate)
71 JS_STATIC_PROP_ENTRY(creator)
72 JS_STATIC_PROP_ENTRY(delay)
73 JS_STATIC_PROP_ENTRY(dirty)
74 JS_STATIC_PROP_ENTRY(documentFileName)
75 JS_STATIC_PROP_ENTRY(external)
76 JS_STATIC_PROP_ENTRY(filesize)
77 JS_STATIC_PROP_ENTRY(icons)
78 JS_STATIC_PROP_ENTRY(info)
79 JS_STATIC_PROP_ENTRY(keywords)
80 JS_STATIC_PROP_ENTRY(layout)
81 JS_STATIC_PROP_ENTRY(media)
82 JS_STATIC_PROP_ENTRY(modDate)
83 JS_STATIC_PROP_ENTRY(mouseX)
84 JS_STATIC_PROP_ENTRY(mouseY)
85 JS_STATIC_PROP_ENTRY(numFields)
86 JS_STATIC_PROP_ENTRY(numPages)
87 JS_STATIC_PROP_ENTRY(pageNum)
88 JS_STATIC_PROP_ENTRY(pageWindowRect)
89 JS_STATIC_PROP_ENTRY(path)
90 JS_STATIC_PROP_ENTRY(producer)
91 JS_STATIC_PROP_ENTRY(subject)
92 JS_STATIC_PROP_ENTRY(title)
93 JS_STATIC_PROP_ENTRY(zoom)
94 JS_STATIC_PROP_ENTRY(zoomType)
95 END_JS_STATIC_PROP()
96
97 BEGIN_JS_STATIC_METHOD(CJS_Document)
98 JS_STATIC_METHOD_ENTRY(addAnnot)
99 JS_STATIC_METHOD_ENTRY(addField)
100 JS_STATIC_METHOD_ENTRY(addLink)
101 JS_STATIC_METHOD_ENTRY(addIcon)
102 JS_STATIC_METHOD_ENTRY(calculateNow)
103 JS_STATIC_METHOD_ENTRY(closeDoc)
104 JS_STATIC_METHOD_ENTRY(createDataObject)
105 JS_STATIC_METHOD_ENTRY(deletePages)
106 JS_STATIC_METHOD_ENTRY(exportAsText)
107 JS_STATIC_METHOD_ENTRY(exportAsFDF)
108 JS_STATIC_METHOD_ENTRY(exportAsXFDF)
109 JS_STATIC_METHOD_ENTRY(extractPages)
110 JS_STATIC_METHOD_ENTRY(getAnnot)
111 JS_STATIC_METHOD_ENTRY(getAnnots)
112 JS_STATIC_METHOD_ENTRY(getAnnot3D)
113 JS_STATIC_METHOD_ENTRY(getAnnots3D)
114 JS_STATIC_METHOD_ENTRY(getField)
115 JS_STATIC_METHOD_ENTRY(getIcon)
116 JS_STATIC_METHOD_ENTRY(getLinks)
117 JS_STATIC_METHOD_ENTRY(getNthFieldName)
118 JS_STATIC_METHOD_ENTRY(getOCGs)
119 JS_STATIC_METHOD_ENTRY(getPageBox)
120 JS_STATIC_METHOD_ENTRY(getPageNthWord)
121 JS_STATIC_METHOD_ENTRY(getPageNthWordQuads)
122 JS_STATIC_METHOD_ENTRY(getPageNumWords)
123 JS_STATIC_METHOD_ENTRY(getPrintParams)
124 JS_STATIC_METHOD_ENTRY(getURL)
125 JS_STATIC_METHOD_ENTRY(importAnFDF)
126 JS_STATIC_METHOD_ENTRY(importAnXFDF)
127 JS_STATIC_METHOD_ENTRY(importTextData)
128 JS_STATIC_METHOD_ENTRY(insertPages)
129 JS_STATIC_METHOD_ENTRY(mailForm)
130 JS_STATIC_METHOD_ENTRY(print)
131 JS_STATIC_METHOD_ENTRY(removeField)
132 JS_STATIC_METHOD_ENTRY(replacePages)
133 JS_STATIC_METHOD_ENTRY(resetForm)
134 JS_STATIC_METHOD_ENTRY(removeIcon)
135 JS_STATIC_METHOD_ENTRY(saveAs)
136 JS_STATIC_METHOD_ENTRY(submitForm)
137 JS_STATIC_METHOD_ENTRY(mailDoc)
138 END_JS_STATIC_METHOD()
139
140 IMPLEMENT_JS_CLASS(CJS_Document, Document)
141
142 FX_BOOL CJS_Document::InitInstance(IFXJS_Context* cc) {
143   CJS_Context* pContext = (CJS_Context*)cc;
144   ASSERT(pContext != NULL);
145
146   Document* pDoc = (Document*)GetEmbedObject();
147   ASSERT(pDoc != NULL);
148
149   pDoc->AttachDoc(pContext->GetReaderDocument());
150   pDoc->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
151   return TRUE;
152 };
153
154 /* --------------------------------- Document ---------------------------------
155  */
156
157 Document::Document(CJS_Object* pJSObject)
158     : CJS_EmbedObj(pJSObject),
159       m_isolate(NULL),
160       m_pIconTree(NULL),
161       m_pDocument(NULL),
162       m_cwBaseURL(L""),
163       m_bDelay(FALSE) {}
164
165 Document::~Document() {
166   if (m_pIconTree) {
167     m_pIconTree->DeleteIconTree();
168     delete m_pIconTree;
169     m_pIconTree = NULL;
170   }
171   for (int i = 0; i < m_DelayData.GetSize(); i++) {
172     if (CJS_DelayData* pData = m_DelayData.GetAt(i)) {
173       delete pData;
174       pData = NULL;
175       m_DelayData.SetAt(i, NULL);
176     }
177   }
178
179   m_DelayData.RemoveAll();
180   m_DelayAnnotData.RemoveAll();
181 }
182
183 // the total number of fileds in document.
184 FX_BOOL Document::numFields(IFXJS_Context* cc,
185                             CJS_PropValue& vp,
186                             CFX_WideString& sError) {
187   if (vp.IsSetting()) {
188     CJS_Context* pContext = static_cast<CJS_Context*>(cc);
189     sError = JSGetStringFromID(pContext, IDS_STRING_JSREADONLY);
190     return FALSE;
191   }
192   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
193   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
194   vp << (int)pPDFForm->CountFields();
195   return TRUE;
196 }
197
198 FX_BOOL Document::dirty(IFXJS_Context* cc,
199                         CJS_PropValue& vp,
200                         CFX_WideString& sError) {
201   ASSERT(m_pDocument != NULL);
202
203   if (vp.IsGetting()) {
204     if (m_pDocument->GetChangeMark())
205       vp << true;
206     else
207       vp << false;
208   } else {
209     bool bChanged = false;
210
211     vp >> bChanged;
212
213     if (bChanged)
214       m_pDocument->SetChangeMark();
215     else
216       m_pDocument->ClearChangeMark();
217   }
218
219   return TRUE;
220 }
221
222 FX_BOOL Document::ADBE(IFXJS_Context* cc,
223                        CJS_PropValue& vp,
224                        CFX_WideString& sError) {
225   ASSERT(m_pDocument != NULL);
226
227   if (vp.IsGetting()) {
228     vp.SetNull();
229   } else {
230   }
231
232   return TRUE;
233 }
234
235 FX_BOOL Document::pageNum(IFXJS_Context* cc,
236                           CJS_PropValue& vp,
237                           CFX_WideString& sError) {
238   ASSERT(m_pDocument != NULL);
239
240   if (vp.IsGetting()) {
241     if (CPDFSDK_PageView* pPageView = m_pDocument->GetCurrentView()) {
242       vp << pPageView->GetPageIndex();
243     }
244   } else {
245     int iPageCount = m_pDocument->GetPageCount();
246     int iPageNum = 0;
247     vp >> iPageNum;
248
249     CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
250     if (iPageNum >= 0 && iPageNum < iPageCount) {
251       pEnv->JS_docgotoPage(iPageNum);
252     } else if (iPageNum >= iPageCount) {
253       pEnv->JS_docgotoPage(iPageCount - 1);
254     } else if (iPageNum < 0) {
255       pEnv->JS_docgotoPage(0);
256     }
257   }
258
259   return TRUE;
260 }
261
262 FX_BOOL Document::addAnnot(IFXJS_Context* cc,
263                            const CJS_Parameters& params,
264                            CJS_Value& vRet,
265                            CFX_WideString& sError) {
266   // Not supported.
267   return TRUE;
268 }
269
270 FX_BOOL Document::addField(IFXJS_Context* cc,
271                            const CJS_Parameters& params,
272                            CJS_Value& vRet,
273                            CFX_WideString& sError) {
274   // Not supported.
275   return TRUE;
276 }
277
278 FX_BOOL Document::exportAsText(IFXJS_Context* cc,
279                                const CJS_Parameters& params,
280                                CJS_Value& vRet,
281                                CFX_WideString& sError) {
282   // Unsafe, not supported.
283   return TRUE;
284 }
285
286 FX_BOOL Document::exportAsFDF(IFXJS_Context* cc,
287                               const CJS_Parameters& params,
288                               CJS_Value& vRet,
289                               CFX_WideString& sError) {
290   // Unsafe, not supported.
291   return TRUE;
292 }
293
294 FX_BOOL Document::exportAsXFDF(IFXJS_Context* cc,
295                                const CJS_Parameters& params,
296                                CJS_Value& vRet,
297                                CFX_WideString& sError) {
298   // Unsafe, not supported.
299   return TRUE;
300 }
301
302 // Maps a field object in PDF document to a JavaScript variable
303 // comment:
304 // note: the paremter cName, this is clue how to treat if the cName is not a
305 // valiable filed name in this document
306
307 FX_BOOL Document::getField(IFXJS_Context* cc,
308                            const CJS_Parameters& params,
309                            CJS_Value& vRet,
310                            CFX_WideString& sError) {
311   CJS_Context* pContext = (CJS_Context*)cc;
312   if (params.size() < 1) {
313     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
314     return FALSE;
315   }
316
317   CFX_WideString wideName = params[0].ToCFXWideString();
318
319   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
320   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
321   if (pPDFForm->CountFields(wideName) <= 0) {
322     vRet.SetNull();
323     return TRUE;
324   }
325
326   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
327   v8::Local<v8::Object> pFieldObj =
328       FXJS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext,
329                            FXJS_GetObjDefnID(pRuntime->GetIsolate(), L"Field"));
330
331   v8::Isolate* isolate = GetIsolate(cc);
332   CJS_Field* pJSField = (CJS_Field*)FXJS_GetPrivate(isolate, pFieldObj);
333   Field* pField = (Field*)pJSField->GetEmbedObject();
334   pField->AttachField(this, wideName);
335
336   vRet = pJSField;
337   return TRUE;
338 }
339
340 // Gets the name of the nth field in the document
341 FX_BOOL Document::getNthFieldName(IFXJS_Context* cc,
342                                   const CJS_Parameters& params,
343                                   CJS_Value& vRet,
344                                   CFX_WideString& sError) {
345   CJS_Context* pContext = (CJS_Context*)cc;
346   if (params.size() != 1) {
347     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
348     return FALSE;
349   }
350
351   int nIndex = params[0].ToInt();
352   if (nIndex < 0) {
353     sError = JSGetStringFromID(pContext, IDS_STRING_JSVALUEERROR);
354     return FALSE;
355   }
356
357   CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
358   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
359   CPDF_FormField* pField = pPDFForm->GetField(nIndex);
360   if (!pField)
361     return FALSE;
362
363   vRet = pField->GetFullName().c_str();
364   return TRUE;
365 }
366
367 FX_BOOL Document::importAnFDF(IFXJS_Context* cc,
368                               const CJS_Parameters& params,
369                               CJS_Value& vRet,
370                               CFX_WideString& sError) {
371   // Unsafe, not supported.
372   return TRUE;
373 }
374
375 FX_BOOL Document::importAnXFDF(IFXJS_Context* cc,
376                                const CJS_Parameters& params,
377                                CJS_Value& vRet,
378                                CFX_WideString& sError) {
379   // Unsafe, not supported.
380   return TRUE;
381 }
382
383 FX_BOOL Document::importTextData(IFXJS_Context* cc,
384                                  const CJS_Parameters& params,
385                                  CJS_Value& vRet,
386                                  CFX_WideString& sError) {
387   // Unsafe, not supported.
388   return TRUE;
389 }
390
391 // exports the form data and mails the resulting fdf file as an attachment to
392 // all recipients.
393 // comment: need reader supports
394 // note:
395 // int CPDFSDK_Document::mailForm(FX_BOOL bUI,String cto,string ccc,string
396 // cbcc,string cSubject,string cms);
397
398 FX_BOOL Document::mailForm(IFXJS_Context* cc,
399                            const CJS_Parameters& params,
400                            CJS_Value& vRet,
401                            CFX_WideString& sError) {
402   ASSERT(m_pDocument != NULL);
403
404   if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS))
405     return FALSE;
406
407   int iLength = params.size();
408
409   FX_BOOL bUI = iLength > 0 ? params[0].ToBool() : TRUE;
410   CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString() : L"";
411   CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString() : L"";
412   CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString() : L"";
413   CFX_WideString cSubject = iLength > 4 ? params[4].ToCFXWideString() : L"";
414   CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString() : L"";
415
416   CPDFSDK_InterForm* pInterForm =
417       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
418   ASSERT(pInterForm != NULL);
419
420   CFX_ByteTextBuf textBuf;
421   if (!pInterForm->ExportFormToFDFTextBuf(textBuf))
422     return FALSE;
423
424   CJS_Context* pContext = (CJS_Context*)cc;
425   ASSERT(pContext != NULL);
426   CPDFDoc_Environment* pEnv = pContext->GetReaderApp();
427   ASSERT(pEnv != NULL);
428   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
429   ASSERT(pRuntime != NULL);
430
431   pRuntime->BeginBlock();
432   pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI,
433                        cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(),
434                        cMsg.c_str());
435   pRuntime->EndBlock();
436   return TRUE;
437 }
438
439 FX_BOOL Document::print(IFXJS_Context* cc,
440                         const CJS_Parameters& params,
441                         CJS_Value& vRet,
442                         CFX_WideString& sError) {
443   CJS_Context* pContext = (CJS_Context*)cc;
444   ASSERT(pContext != NULL);
445   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
446   ASSERT(pRuntime != NULL);
447
448   FX_BOOL bUI = TRUE;
449   int nStart = 0;
450   int nEnd = 0;
451   FX_BOOL bSilent = FALSE;
452   FX_BOOL bShrinkToFit = FALSE;
453   FX_BOOL bPrintAsImage = FALSE;
454   FX_BOOL bReverse = FALSE;
455   FX_BOOL bAnnotations = FALSE;
456
457   int nlength = params.size();
458   if (nlength == 9) {
459     if (params[8].GetType() == CJS_Value::VT_fxobject) {
460       v8::Local<v8::Object> pObj = params[8].ToV8Object();
461       {
462         if (FXJS_GetObjDefnID(pObj) ==
463             FXJS_GetObjDefnID(pRuntime->GetIsolate(), L"PrintParamsObj")) {
464           if (CJS_Object* pJSObj = params[8].ToCJSObject()) {
465             if (PrintParamsObj* pprintparamsObj =
466                     (PrintParamsObj*)pJSObj->GetEmbedObject()) {
467               bUI = pprintparamsObj->bUI;
468               nStart = pprintparamsObj->nStart;
469               nEnd = pprintparamsObj->nEnd;
470               bSilent = pprintparamsObj->bSilent;
471               bShrinkToFit = pprintparamsObj->bShrinkToFit;
472               bPrintAsImage = pprintparamsObj->bPrintAsImage;
473               bReverse = pprintparamsObj->bReverse;
474               bAnnotations = pprintparamsObj->bAnnotations;
475             }
476           }
477         }
478       }
479     }
480   } else {
481     if (nlength >= 1)
482       bUI = params[0].ToBool();
483     if (nlength >= 2)
484       nStart = params[1].ToInt();
485     if (nlength >= 3)
486       nEnd = params[2].ToInt();
487     if (nlength >= 4)
488       bSilent = params[3].ToBool();
489     if (nlength >= 5)
490       bShrinkToFit = params[4].ToBool();
491     if (nlength >= 6)
492       bPrintAsImage = params[5].ToBool();
493     if (nlength >= 7)
494       bReverse = params[6].ToBool();
495     if (nlength >= 8)
496       bAnnotations = params[7].ToBool();
497   }
498
499   ASSERT(m_pDocument != NULL);
500
501   if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv()) {
502     pEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage,
503                       bReverse, bAnnotations);
504     return TRUE;
505   }
506   return FALSE;
507 }
508
509 // removes the specified field from the document.
510 // comment:
511 // note: if the filed name is not retional, adobe is dumb for it.
512
513 FX_BOOL Document::removeField(IFXJS_Context* cc,
514                               const CJS_Parameters& params,
515                               CJS_Value& vRet,
516                               CFX_WideString& sError) {
517   ASSERT(m_pDocument != NULL);
518
519   if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
520         m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM)))
521     return FALSE;
522
523   CJS_Context* pContext = (CJS_Context*)cc;
524   if (params.size() != 1) {
525     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
526     return FALSE;
527   }
528
529   CFX_WideString sFieldName = params[0].ToCFXWideString();
530   CPDFSDK_InterForm* pInterForm =
531       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
532   ASSERT(pInterForm != NULL);
533
534   CFX_PtrArray widgets;
535   pInterForm->GetWidgets(sFieldName, widgets);
536
537   int nSize = widgets.GetSize();
538
539   if (nSize > 0) {
540     for (int i = 0; i < nSize; i++) {
541       CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)widgets[i];
542       ASSERT(pWidget != NULL);
543
544       CPDF_Rect rcAnnot = pWidget->GetRect();
545       rcAnnot.left -= 1;
546       rcAnnot.bottom -= 1;
547       rcAnnot.right += 1;
548       rcAnnot.top += 1;
549
550       CFX_RectArray aRefresh;
551       aRefresh.Add(rcAnnot);
552
553       CPDF_Page* pPage = pWidget->GetPDFPage();
554       ASSERT(pPage != NULL);
555
556       CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage);
557       pPageView->DeleteAnnot(pWidget);
558
559       pPageView->UpdateRects(aRefresh);
560     }
561     m_pDocument->SetChangeMark();
562   }
563
564   return TRUE;
565 }
566
567 // reset filed values within a document.
568 // comment:
569 // note: if the fields names r not rational, aodbe is dumb for it.
570
571 FX_BOOL Document::resetForm(IFXJS_Context* cc,
572                             const CJS_Parameters& params,
573                             CJS_Value& vRet,
574                             CFX_WideString& sError) {
575   ASSERT(m_pDocument != NULL);
576
577   if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
578         m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
579         m_pDocument->GetPermissions(FPDFPERM_FILL_FORM)))
580     return FALSE;
581
582   CPDFSDK_InterForm* pInterForm =
583       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
584   ASSERT(pInterForm != NULL);
585
586   CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
587   ASSERT(pPDFForm != NULL);
588
589   v8::Isolate* isolate = GetIsolate(cc);
590   CJS_Array aName(isolate);
591
592   if (params.size() > 0) {
593     switch (params[0].GetType()) {
594       default:
595         aName.Attach(params[0].ToV8Array());
596         break;
597       case CJS_Value::VT_string:
598         aName.SetElement(0, params[0]);
599         break;
600     }
601
602     CFX_PtrArray aFields;
603
604     for (int i = 0, isz = aName.GetLength(); i < isz; i++) {
605       CJS_Value valElement(isolate);
606       aName.GetElement(i, valElement);
607       CFX_WideString swVal = valElement.ToCFXWideString();
608
609       for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; j++) {
610         aFields.Add((void*)pPDFForm->GetField(j, swVal));
611       }
612     }
613
614     if (aFields.GetSize() > 0) {
615       pPDFForm->ResetForm(aFields, TRUE, TRUE);
616       m_pDocument->SetChangeMark();
617     }
618   } else {
619     pPDFForm->ResetForm(TRUE);
620     m_pDocument->SetChangeMark();
621   }
622
623   return TRUE;
624 }
625
626 FX_BOOL Document::saveAs(IFXJS_Context* cc,
627                          const CJS_Parameters& params,
628                          CJS_Value& vRet,
629                          CFX_WideString& sError) {
630   // Unsafe, not supported.
631   return TRUE;
632 }
633
634 FX_BOOL Document::submitForm(IFXJS_Context* cc,
635                              const CJS_Parameters& params,
636                              CJS_Value& vRet,
637                              CFX_WideString& sError) {
638   ASSERT(m_pDocument != NULL);
639   CJS_Context* pContext = (CJS_Context*)cc;
640   int nSize = params.size();
641   if (nSize < 1) {
642     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
643     return FALSE;
644   }
645
646   CFX_WideString strURL;
647   FX_BOOL bFDF = TRUE;
648   FX_BOOL bEmpty = FALSE;
649   v8::Isolate* isolate = GetIsolate(cc);
650   CJS_Array aFields(isolate);
651
652   CJS_Value v = params[0];
653   if (v.GetType() == CJS_Value::VT_string) {
654     strURL = params[0].ToCFXWideString();
655     if (nSize > 1)
656       bFDF = params[1].ToBool();
657     if (nSize > 2)
658       bEmpty = params[2].ToBool();
659     if (nSize > 3)
660       aFields.Attach(params[3].ToV8Array());
661   } else if (v.GetType() == CJS_Value::VT_object) {
662     v8::Local<v8::Object> pObj = params[0].ToV8Object();
663     v8::Local<v8::Value> pValue = FXJS_GetObjectElement(isolate, pObj, L"cURL");
664     if (!pValue.IsEmpty())
665       strURL =
666           CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
667     pValue = FXJS_GetObjectElement(isolate, pObj, L"bFDF");
668     bFDF = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
669     pValue = FXJS_GetObjectElement(isolate, pObj, L"bEmpty");
670     bEmpty = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToBool();
671     pValue = FXJS_GetObjectElement(isolate, pObj, L"aFields");
672     aFields.Attach(
673         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToV8Array());
674   }
675
676   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
677   CPDFSDK_InterForm* pInterForm =
678       (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
679   CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
680   FX_BOOL bAll = (aFields.GetLength() == 0);
681   if (bAll && bEmpty) {
682     if (pPDFInterForm->CheckRequiredFields()) {
683       pRuntime->BeginBlock();
684       pInterForm->SubmitForm(strURL, FALSE);
685       pRuntime->EndBlock();
686     }
687     return TRUE;
688   }
689
690   CFX_PtrArray fieldObjects;
691   for (int i = 0, sz = aFields.GetLength(); i < sz; i++) {
692     CJS_Value valName(isolate);
693     aFields.GetElement(i, valName);
694
695     CFX_WideString sName = valName.ToCFXWideString();
696     CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
697     for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) {
698       CPDF_FormField* pField = pPDFForm->GetField(j, sName);
699       if (!bEmpty && pField->GetValue().IsEmpty())
700         continue;
701
702       fieldObjects.Add(pField);
703     }
704   }
705
706   if (pPDFInterForm->CheckRequiredFields(&fieldObjects, TRUE)) {
707     pRuntime->BeginBlock();
708     pInterForm->SubmitFields(strURL, fieldObjects, TRUE, !bFDF);
709     pRuntime->EndBlock();
710   }
711   return TRUE;
712 }
713
714 //////////////////////////////////////////////////////////////////////////////////////////////
715
716 void Document::AttachDoc(CPDFSDK_Document* pDoc) {
717   m_pDocument = pDoc;
718 }
719
720 CPDFSDK_Document* Document::GetReaderDoc() {
721   return m_pDocument;
722 }
723
724 FX_BOOL Document::ExtractFileName(CPDFSDK_Document* pDoc,
725                                   CFX_ByteString& strFileName) {
726   return FALSE;
727 }
728
729 FX_BOOL Document::ExtractFolderName(CPDFSDK_Document* pDoc,
730                                     CFX_ByteString& strFolderName) {
731   return FALSE;
732 }
733
734 FX_BOOL Document::bookmarkRoot(IFXJS_Context* cc,
735                                CJS_PropValue& vp,
736                                CFX_WideString& sError) {
737   return TRUE;
738 }
739
740 FX_BOOL Document::mailDoc(IFXJS_Context* cc,
741                           const CJS_Parameters& params,
742                           CJS_Value& vRet,
743                           CFX_WideString& sError) {
744   ASSERT(m_pDocument != NULL);
745
746   FX_BOOL bUI = TRUE;
747   CFX_WideString cTo = L"";
748   CFX_WideString cCc = L"";
749   CFX_WideString cBcc = L"";
750   CFX_WideString cSubject = L"";
751   CFX_WideString cMsg = L"";
752
753   if (params.size() >= 1)
754     bUI = params[0].ToBool();
755   if (params.size() >= 2)
756     cTo = params[1].ToCFXWideString();
757   if (params.size() >= 3)
758     cCc = params[2].ToCFXWideString();
759   if (params.size() >= 4)
760     cBcc = params[3].ToCFXWideString();
761   if (params.size() >= 5)
762     cSubject = params[4].ToCFXWideString();
763   if (params.size() >= 6)
764     cMsg = params[5].ToCFXWideString();
765
766   v8::Isolate* isolate = GetIsolate(cc);
767
768   if (params.size() >= 1 && params[0].GetType() == CJS_Value::VT_object) {
769     v8::Local<v8::Object> pObj = params[0].ToV8Object();
770
771     v8::Local<v8::Value> pValue = FXJS_GetObjectElement(isolate, pObj, L"bUI");
772     bUI = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToInt();
773
774     pValue = FXJS_GetObjectElement(isolate, pObj, L"cTo");
775     cTo = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
776
777     pValue = FXJS_GetObjectElement(isolate, pObj, L"cCc");
778     cCc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
779
780     pValue = FXJS_GetObjectElement(isolate, pObj, L"cBcc");
781     cBcc = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
782
783     pValue = FXJS_GetObjectElement(isolate, pObj, L"cSubject");
784     cSubject =
785         CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
786
787     pValue = FXJS_GetObjectElement(isolate, pObj, L"cMsg");
788     cMsg = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString();
789   }
790
791   CJS_Context* pContext = (CJS_Context*)cc;
792   ASSERT(pContext != NULL);
793   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
794   ASSERT(pRuntime != NULL);
795
796   pRuntime->BeginBlock();
797   CPDFDoc_Environment* pEnv = pRuntime->GetReaderApp();
798   pEnv->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(),
799                        cBcc.c_str(), cMsg.c_str());
800   pRuntime->EndBlock();
801
802   return TRUE;
803 }
804
805 FX_BOOL Document::author(IFXJS_Context* cc,
806                          CJS_PropValue& vp,
807                          CFX_WideString& sError) {
808   ASSERT(m_pDocument != NULL);
809
810   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
811   if (!pDictionary)
812     return FALSE;
813
814   if (vp.IsGetting()) {
815     vp << pDictionary->GetUnicodeText("Author");
816     return TRUE;
817   } else {
818     if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY))
819       return FALSE;
820
821     CFX_WideString csAuthor;
822     vp >> csAuthor;
823     pDictionary->SetAtString("Author", PDF_EncodeText(csAuthor));
824     m_pDocument->SetChangeMark();
825     return TRUE;
826   }
827 }
828
829 FX_BOOL Document::info(IFXJS_Context* cc,
830                        CJS_PropValue& vp,
831                        CFX_WideString& sError) {
832   ASSERT(m_pDocument != NULL);
833
834   CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
835   if (!pDictionary)
836     return FALSE;
837
838   CFX_WideString cwAuthor = pDictionary->GetUnicodeText("Author");
839   CFX_WideString cwTitle = pDictionary->GetUnicodeText("Title");
840   CFX_WideString cwSubject = pDictionary->GetUnicodeText("Subject");
841   CFX_WideString cwKeywords = pDictionary->GetUnicodeText("Keywords");
842   CFX_WideString cwCreator = pDictionary->GetUnicodeText("Creator");
843   CFX_WideString cwProducer = pDictionary->GetUnicodeText("Producer");
844   CFX_WideString cwCreationDate = pDictionary->GetUnicodeText("CreationDate");
845   CFX_WideString cwModDate = pDictionary->GetUnicodeText("ModDate");
846   CFX_WideString cwTrapped = pDictionary->GetUnicodeText("Trapped");
847
848   v8::Isolate* isolate = GetIsolate(cc);
849   if (vp.IsGetting()) {
850     CJS_Context* pContext = (CJS_Context*)cc;
851     CJS_Runtime* pRuntime = pContext->GetJSRuntime();
852     v8::Local<v8::Object> pObj =
853         FXJS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext, -1);
854     FXJS_PutObjectString(isolate, pObj, L"Author", cwAuthor.c_str());
855     FXJS_PutObjectString(isolate, pObj, L"Title", cwTitle.c_str());
856     FXJS_PutObjectString(isolate, pObj, L"Subject", cwSubject.c_str());
857     FXJS_PutObjectString(isolate, pObj, L"Keywords", cwKeywords.c_str());
858     FXJS_PutObjectString(isolate, pObj, L"Creator", cwCreator.c_str());
859     FXJS_PutObjectString(isolate, pObj, L"Producer", cwProducer.c_str());
860     FXJS_PutObjectString(isolate, pObj, L"CreationDate",
861                          cwCreationDate.c_str());
862     FXJS_PutObjectString(isolate, pObj, L"ModDate", cwModDate.c_str());
863     FXJS_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         FXJS_PutObjectString(isolate, pObj, wsKey.c_str(),
874                              pValueObj->GetUnicodeText().c_str());
875       if (pValueObj->GetType() == PDFOBJ_NUMBER)
876         FXJS_PutObjectNumber(isolate, pObj, wsKey.c_str(),
877                              (float)pValueObj->GetNumber());
878       if (pValueObj->GetType() == PDFOBJ_BOOLEAN)
879         FXJS_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 = CJS_Value::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() != CJS_Value::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 (FXJS_GetObjDefnID(pJSIcon) !=
1377       FXJS_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 = FXJS_NewFxDynamicObj(
1425         pRuntime->GetIsolate(), pContext,
1426         FXJS_GetObjDefnID(pRuntime->GetIsolate(), L"Icon"));
1427     if (pObj.IsEmpty())
1428       return FALSE;
1429
1430     CJS_Icon* pJS_Icon = (CJS_Icon*)FXJS_GetPrivate(m_isolate, 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 = FXJS_NewFxDynamicObj(
1469           pRuntime->GetIsolate(), pContext,
1470           FXJS_GetObjDefnID(pRuntime->GetIsolate(), L"Icon"));
1471       if (pObj.IsEmpty())
1472         return FALSE;
1473
1474       CJS_Icon* pJS_Icon = (CJS_Icon*)FXJS_GetPrivate(m_isolate, 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 = FXJS_NewFxDynamicObj(
1666       pRuntime->GetIsolate(), pContext,
1667       FXJS_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 }