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