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 "fpdfsdk/javascript/app.h"
      8 
      9 #include <map>
     10 #include <memory>
     11 #include <vector>
     12 
     13 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
     14 #include "fpdfsdk/cpdfsdk_interform.h"
     15 #include "fpdfsdk/javascript/Document.h"
     16 #include "fpdfsdk/javascript/JS_Define.h"
     17 #include "fpdfsdk/javascript/JS_EventHandler.h"
     18 #include "fpdfsdk/javascript/JS_Object.h"
     19 #include "fpdfsdk/javascript/JS_Value.h"
     20 #include "fpdfsdk/javascript/cjs_event_context.h"
     21 #include "fpdfsdk/javascript/cjs_runtime.h"
     22 #include "fpdfsdk/javascript/resource.h"
     23 #include "third_party/base/stl_util.h"
     24 
     25 class GlobalTimer {
     26  public:
     27   GlobalTimer(app* pObj,
     28               CPDFSDK_FormFillEnvironment* pFormFillEnv,
     29               CJS_Runtime* pRuntime,
     30               int nType,
     31               const CFX_WideString& script,
     32               uint32_t dwElapse,
     33               uint32_t dwTimeOut);
     34   ~GlobalTimer();
     35 
     36   static void Trigger(int nTimerID);
     37   static void Cancel(int nTimerID);
     38 
     39   bool IsOneShot() const { return m_nType == 1; }
     40   uint32_t GetTimeOut() const { return m_dwTimeOut; }
     41   int GetTimerID() const { return m_nTimerID; }
     42   CJS_Runtime* GetRuntime() const { return m_pRuntime.Get(); }
     43   CFX_WideString GetJScript() const { return m_swJScript; }
     44 
     45  private:
     46   using TimerMap = std::map<uint32_t, GlobalTimer*>;
     47   static TimerMap* GetGlobalTimerMap();
     48 
     49   uint32_t m_nTimerID;
     50   app* const m_pEmbedObj;
     51   bool m_bProcessing;
     52 
     53   // data
     54   const int m_nType;  // 0:Interval; 1:TimeOut
     55   const uint32_t m_dwTimeOut;
     56   const CFX_WideString m_swJScript;
     57   CJS_Runtime::ObservedPtr m_pRuntime;
     58   CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
     59 };
     60 
     61 GlobalTimer::GlobalTimer(app* pObj,
     62                          CPDFSDK_FormFillEnvironment* pFormFillEnv,
     63                          CJS_Runtime* pRuntime,
     64                          int nType,
     65                          const CFX_WideString& script,
     66                          uint32_t dwElapse,
     67                          uint32_t dwTimeOut)
     68     : m_nTimerID(0),
     69       m_pEmbedObj(pObj),
     70       m_bProcessing(false),
     71       m_nType(nType),
     72       m_dwTimeOut(dwTimeOut),
     73       m_swJScript(script),
     74       m_pRuntime(pRuntime),
     75       m_pFormFillEnv(pFormFillEnv) {
     76   CFX_SystemHandler* pHandler = m_pFormFillEnv->GetSysHandler();
     77   m_nTimerID = pHandler->SetTimer(dwElapse, Trigger);
     78   if (m_nTimerID)
     79     (*GetGlobalTimerMap())[m_nTimerID] = this;
     80 }
     81 
     82 GlobalTimer::~GlobalTimer() {
     83   if (!m_nTimerID)
     84     return;
     85 
     86   if (GetRuntime())
     87     m_pFormFillEnv->GetSysHandler()->KillTimer(m_nTimerID);
     88 
     89   GetGlobalTimerMap()->erase(m_nTimerID);
     90 }
     91 
     92 // static
     93 void GlobalTimer::Trigger(int nTimerID) {
     94   auto it = GetGlobalTimerMap()->find(nTimerID);
     95   if (it == GetGlobalTimerMap()->end())
     96     return;
     97 
     98   GlobalTimer* pTimer = it->second;
     99   if (pTimer->m_bProcessing)
    100     return;
    101 
    102   pTimer->m_bProcessing = true;
    103   if (pTimer->m_pEmbedObj)
    104     pTimer->m_pEmbedObj->TimerProc(pTimer);
    105 
    106   // Timer proc may have destroyed timer, find it again.
    107   it = GetGlobalTimerMap()->find(nTimerID);
    108   if (it == GetGlobalTimerMap()->end())
    109     return;
    110 
    111   pTimer = it->second;
    112   pTimer->m_bProcessing = false;
    113   if (pTimer->IsOneShot())
    114     pTimer->m_pEmbedObj->CancelProc(pTimer);
    115 }
    116 
    117 // static
    118 void GlobalTimer::Cancel(int nTimerID) {
    119   auto it = GetGlobalTimerMap()->find(nTimerID);
    120   if (it == GetGlobalTimerMap()->end())
    121     return;
    122 
    123   GlobalTimer* pTimer = it->second;
    124   pTimer->m_pEmbedObj->CancelProc(pTimer);
    125 }
    126 
    127 // static
    128 GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() {
    129   // Leak the timer array at shutdown.
    130   static auto* s_TimerMap = new TimerMap;
    131   return s_TimerMap;
    132 }
    133 
    134 JSConstSpec CJS_TimerObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
    135 
    136 JSPropertySpec CJS_TimerObj::PropertySpecs[] = {{0, 0, 0}};
    137 
    138 JSMethodSpec CJS_TimerObj::MethodSpecs[] = {{0, 0}};
    139 
    140 IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj)
    141 
    142 TimerObj::TimerObj(CJS_Object* pJSObject)
    143     : CJS_EmbedObj(pJSObject), m_nTimerID(0) {}
    144 
    145 TimerObj::~TimerObj() {}
    146 
    147 void TimerObj::SetTimer(GlobalTimer* pTimer) {
    148   m_nTimerID = pTimer->GetTimerID();
    149 }
    150 
    151 #define JS_STR_VIEWERTYPE L"pdfium"
    152 #define JS_STR_VIEWERVARIATION L"Full"
    153 #define JS_STR_PLATFORM L"WIN"
    154 #define JS_STR_LANGUAGE L"ENU"
    155 #define JS_NUM_VIEWERVERSION 8
    156 #ifdef PDF_ENABLE_XFA
    157 #define JS_NUM_VIEWERVERSION_XFA 11
    158 #endif  // PDF_ENABLE_XFA
    159 #define JS_NUM_FORMSVERSION 7
    160 
    161 JSConstSpec CJS_App::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
    162 
    163 JSPropertySpec CJS_App::PropertySpecs[] = {
    164     {"activeDocs", get_activeDocs_static, set_activeDocs_static},
    165     {"calculate", get_calculate_static, set_calculate_static},
    166     {"formsVersion", get_formsVersion_static, set_formsVersion_static},
    167     {"fs", get_fs_static, set_fs_static},
    168     {"fullscreen", get_fullscreen_static, set_fullscreen_static},
    169     {"language", get_language_static, set_language_static},
    170     {"media", get_media_static, set_media_static},
    171     {"platform", get_platform_static, set_platform_static},
    172     {"runtimeHighlight", get_runtimeHighlight_static,
    173      set_runtimeHighlight_static},
    174     {"viewerType", get_viewerType_static, set_viewerType_static},
    175     {"viewerVariation", get_viewerVariation_static, set_viewerVariation_static},
    176     {"viewerVersion", get_viewerVersion_static, set_viewerVersion_static},
    177     {0, 0, 0}};
    178 
    179 JSMethodSpec CJS_App::MethodSpecs[] = {{"alert", alert_static},
    180                                        {"beep", beep_static},
    181                                        {"browseForDoc", browseForDoc_static},
    182                                        {"clearInterval", clearInterval_static},
    183                                        {"clearTimeOut", clearTimeOut_static},
    184                                        {"execDialog", execDialog_static},
    185                                        {"execMenuItem", execMenuItem_static},
    186                                        {"findComponent", findComponent_static},
    187                                        {"goBack", goBack_static},
    188                                        {"goForward", goForward_static},
    189                                        {"launchURL", launchURL_static},
    190                                        {"mailMsg", mailMsg_static},
    191                                        {"newFDF", newFDF_static},
    192                                        {"newDoc", newDoc_static},
    193                                        {"openDoc", openDoc_static},
    194                                        {"openFDF", openFDF_static},
    195                                        {"popUpMenuEx", popUpMenuEx_static},
    196                                        {"popUpMenu", popUpMenu_static},
    197                                        {"response", response_static},
    198                                        {"setInterval", setInterval_static},
    199                                        {"setTimeOut", setTimeOut_static},
    200                                        {0, 0}};
    201 
    202 IMPLEMENT_JS_CLASS(CJS_App, app)
    203 
    204 app::app(CJS_Object* pJSObject)
    205     : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {}
    206 
    207 app::~app() {
    208 }
    209 
    210 bool app::activeDocs(CJS_Runtime* pRuntime,
    211                      CJS_PropValue& vp,
    212                      CFX_WideString& sError) {
    213   if (!vp.IsGetting())
    214     return false;
    215 
    216   CJS_Document* pJSDocument = nullptr;
    217   v8::Local<v8::Object> pObj = pRuntime->GetThisObj();
    218   if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID)
    219     pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pObj));
    220 
    221   CJS_Array aDocs;
    222   aDocs.SetElement(pRuntime, 0, CJS_Value(pRuntime, pJSDocument));
    223   if (aDocs.GetLength(pRuntime) > 0)
    224     vp << aDocs;
    225   else
    226     vp.GetJSValue()->SetNull(pRuntime);
    227 
    228   return true;
    229 }
    230 
    231 bool app::calculate(CJS_Runtime* pRuntime,
    232                     CJS_PropValue& vp,
    233                     CFX_WideString& sError) {
    234   if (vp.IsSetting()) {
    235     bool bVP;
    236     vp >> bVP;
    237     m_bCalculate = (bool)bVP;
    238     pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate(
    239         (bool)m_bCalculate);
    240   } else {
    241     vp << (bool)m_bCalculate;
    242   }
    243   return true;
    244 }
    245 
    246 bool app::formsVersion(CJS_Runtime* pRuntime,
    247                        CJS_PropValue& vp,
    248                        CFX_WideString& sError) {
    249   if (vp.IsGetting()) {
    250     vp << JS_NUM_FORMSVERSION;
    251     return true;
    252   }
    253 
    254   return false;
    255 }
    256 
    257 bool app::viewerType(CJS_Runtime* pRuntime,
    258                      CJS_PropValue& vp,
    259                      CFX_WideString& sError) {
    260   if (vp.IsGetting()) {
    261     vp << JS_STR_VIEWERTYPE;
    262     return true;
    263   }
    264 
    265   return false;
    266 }
    267 
    268 bool app::viewerVariation(CJS_Runtime* pRuntime,
    269                           CJS_PropValue& vp,
    270                           CFX_WideString& sError) {
    271   if (vp.IsGetting()) {
    272     vp << JS_STR_VIEWERVARIATION;
    273     return true;
    274   }
    275 
    276   return false;
    277 }
    278 
    279 bool app::viewerVersion(CJS_Runtime* pRuntime,
    280                         CJS_PropValue& vp,
    281                         CFX_WideString& sError) {
    282   if (!vp.IsGetting())
    283     return false;
    284 #ifdef PDF_ENABLE_XFA
    285   CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext();
    286   if (pXFAContext->GetDocType() == 1 || pXFAContext->GetDocType() == 2) {
    287     vp << JS_NUM_VIEWERVERSION_XFA;
    288     return true;
    289   }
    290 #endif  // PDF_ENABLE_XFA
    291   vp << JS_NUM_VIEWERVERSION;
    292   return true;
    293 }
    294 
    295 bool app::platform(CJS_Runtime* pRuntime,
    296                    CJS_PropValue& vp,
    297                    CFX_WideString& sError) {
    298   if (!vp.IsGetting())
    299     return false;
    300 #ifdef PDF_ENABLE_XFA
    301   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    302   if (!pFormFillEnv)
    303     return false;
    304   CFX_WideString platfrom = pFormFillEnv->GetPlatform();
    305   if (!platfrom.IsEmpty()) {
    306     vp << platfrom;
    307     return true;
    308   }
    309 #endif
    310   vp << JS_STR_PLATFORM;
    311   return true;
    312 }
    313 
    314 bool app::language(CJS_Runtime* pRuntime,
    315                    CJS_PropValue& vp,
    316                    CFX_WideString& sError) {
    317   if (!vp.IsGetting())
    318     return false;
    319 #ifdef PDF_ENABLE_XFA
    320   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    321   if (!pFormFillEnv)
    322     return false;
    323   CFX_WideString language = pFormFillEnv->GetLanguage();
    324   if (!language.IsEmpty()) {
    325     vp << language;
    326     return true;
    327   }
    328 #endif
    329   vp << JS_STR_LANGUAGE;
    330   return true;
    331 }
    332 
    333 // creates a new fdf object that contains no data
    334 // comment: need reader support
    335 // note:
    336 // CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF();
    337 bool app::newFDF(CJS_Runtime* pRuntime,
    338                  const std::vector<CJS_Value>& params,
    339                  CJS_Value& vRet,
    340                  CFX_WideString& sError) {
    341   return true;
    342 }
    343 // opens a specified pdf document and returns its document object
    344 // comment:need reader support
    345 // note: as defined in js reference, the proto of this function's fourth
    346 // parmeters, how old an fdf document while do not show it.
    347 // CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool
    348 // bUserConv);
    349 
    350 bool app::openFDF(CJS_Runtime* pRuntime,
    351                   const std::vector<CJS_Value>& params,
    352                   CJS_Value& vRet,
    353                   CFX_WideString& sError) {
    354   return true;
    355 }
    356 
    357 bool app::alert(CJS_Runtime* pRuntime,
    358                 const std::vector<CJS_Value>& params,
    359                 CJS_Value& vRet,
    360                 CFX_WideString& sError) {
    361   std::vector<CJS_Value> newParams = JS_ExpandKeywordParams(
    362       pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle");
    363 
    364   if (newParams[0].GetType() == CJS_Value::VT_unknown) {
    365     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    366     return false;
    367   }
    368 
    369   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    370   if (!pFormFillEnv) {
    371     vRet = CJS_Value(pRuntime, 0);
    372     return true;
    373   }
    374 
    375   CFX_WideString swMsg;
    376   if (newParams[0].GetType() == CJS_Value::VT_object) {
    377     CJS_Array carray;
    378     if (newParams[0].ConvertToArray(pRuntime, carray)) {
    379       swMsg = L"[";
    380       CJS_Value element(pRuntime);
    381       for (int i = 0; i < carray.GetLength(pRuntime); ++i) {
    382         if (i)
    383           swMsg += L", ";
    384         carray.GetElement(pRuntime, i, element);
    385         swMsg += element.ToCFXWideString(pRuntime);
    386       }
    387       swMsg += L"]";
    388     } else {
    389       swMsg = newParams[0].ToCFXWideString(pRuntime);
    390     }
    391   } else {
    392     swMsg = newParams[0].ToCFXWideString(pRuntime);
    393   }
    394 
    395   int iIcon = 0;
    396   if (newParams[1].GetType() != CJS_Value::VT_unknown)
    397     iIcon = newParams[1].ToInt(pRuntime);
    398 
    399   int iType = 0;
    400   if (newParams[2].GetType() != CJS_Value::VT_unknown)
    401     iType = newParams[2].ToInt(pRuntime);
    402 
    403   CFX_WideString swTitle;
    404   if (newParams[3].GetType() != CJS_Value::VT_unknown)
    405     swTitle = newParams[3].ToCFXWideString(pRuntime);
    406   else
    407     swTitle = JSGetStringFromID(IDS_STRING_JSALERT);
    408 
    409   pRuntime->BeginBlock();
    410   pFormFillEnv->KillFocusAnnot(0);
    411 
    412   vRet = CJS_Value(pRuntime, pFormFillEnv->JS_appAlert(
    413                                  swMsg.c_str(), swTitle.c_str(), iType, iIcon));
    414   pRuntime->EndBlock();
    415   return true;
    416 }
    417 
    418 bool app::beep(CJS_Runtime* pRuntime,
    419                const std::vector<CJS_Value>& params,
    420                CJS_Value& vRet,
    421                CFX_WideString& sError) {
    422   if (params.size() == 1) {
    423     pRuntime->GetFormFillEnv()->JS_appBeep(params[0].ToInt(pRuntime));
    424     return true;
    425   }
    426 
    427   sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    428   return false;
    429 }
    430 
    431 bool app::findComponent(CJS_Runtime* pRuntime,
    432                         const std::vector<CJS_Value>& params,
    433                         CJS_Value& vRet,
    434                         CFX_WideString& sError) {
    435   return true;
    436 }
    437 
    438 bool app::popUpMenuEx(CJS_Runtime* pRuntime,
    439                       const std::vector<CJS_Value>& params,
    440                       CJS_Value& vRet,
    441                       CFX_WideString& sError) {
    442   return false;
    443 }
    444 
    445 bool app::fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError) {
    446   return false;
    447 }
    448 
    449 bool app::setInterval(CJS_Runtime* pRuntime,
    450                       const std::vector<CJS_Value>& params,
    451                       CJS_Value& vRet,
    452                       CFX_WideString& sError) {
    453   if (params.size() > 2 || params.size() == 0) {
    454     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    455     return false;
    456   }
    457 
    458   CFX_WideString script =
    459       params.size() > 0 ? params[0].ToCFXWideString(pRuntime) : L"";
    460   if (script.IsEmpty()) {
    461     sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE);
    462     return true;
    463   }
    464 
    465   uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
    466 
    467   GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(),
    468                                           pRuntime, 0, script, dwInterval, 0);
    469   m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
    470 
    471   v8::Local<v8::Object> pRetObj =
    472       pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
    473   if (pRetObj.IsEmpty())
    474     return false;
    475 
    476   CJS_TimerObj* pJS_TimerObj =
    477       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
    478   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
    479   pTimerObj->SetTimer(timerRef);
    480 
    481   vRet = CJS_Value(pRuntime, pRetObj);
    482   return true;
    483 }
    484 
    485 bool app::setTimeOut(CJS_Runtime* pRuntime,
    486                      const std::vector<CJS_Value>& params,
    487                      CJS_Value& vRet,
    488                      CFX_WideString& sError) {
    489   if (params.size() > 2 || params.size() == 0) {
    490     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    491     return false;
    492   }
    493 
    494   CFX_WideString script = params[0].ToCFXWideString(pRuntime);
    495   if (script.IsEmpty()) {
    496     sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE);
    497     return true;
    498   }
    499 
    500   uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
    501   GlobalTimer* timerRef =
    502       new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script,
    503                       dwTimeOut, dwTimeOut);
    504   m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
    505 
    506   v8::Local<v8::Object> pRetObj =
    507       pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
    508   if (pRetObj.IsEmpty())
    509     return false;
    510 
    511   CJS_TimerObj* pJS_TimerObj =
    512       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
    513   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
    514   pTimerObj->SetTimer(timerRef);
    515   vRet = CJS_Value(pRuntime, pRetObj);
    516   return true;
    517 }
    518 
    519 bool app::clearTimeOut(CJS_Runtime* pRuntime,
    520                        const std::vector<CJS_Value>& params,
    521                        CJS_Value& vRet,
    522                        CFX_WideString& sError) {
    523   if (params.size() != 1) {
    524     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    525     return false;
    526   }
    527 
    528   app::ClearTimerCommon(pRuntime, params[0]);
    529   return true;
    530 }
    531 
    532 bool app::clearInterval(CJS_Runtime* pRuntime,
    533                         const std::vector<CJS_Value>& params,
    534                         CJS_Value& vRet,
    535                         CFX_WideString& sError) {
    536   if (params.size() != 1) {
    537     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    538     return false;
    539   }
    540 
    541   app::ClearTimerCommon(pRuntime, params[0]);
    542   return true;
    543 }
    544 
    545 void app::ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param) {
    546   if (param.GetType() != CJS_Value::VT_object)
    547     return;
    548 
    549   v8::Local<v8::Object> pObj = param.ToV8Object(pRuntime);
    550   if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::g_nObjDefnID)
    551     return;
    552 
    553   CJS_Object* pJSObj = param.ToCJSObject(pRuntime);
    554   if (!pJSObj)
    555     return;
    556 
    557   TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject());
    558   if (!pTimerObj)
    559     return;
    560 
    561   GlobalTimer::Cancel(pTimerObj->GetTimerID());
    562 }
    563 
    564 bool app::execMenuItem(CJS_Runtime* pRuntime,
    565                        const std::vector<CJS_Value>& params,
    566                        CJS_Value& vRet,
    567                        CFX_WideString& sError) {
    568   return false;
    569 }
    570 
    571 void app::TimerProc(GlobalTimer* pTimer) {
    572   CJS_Runtime* pRuntime = pTimer->GetRuntime();
    573   if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0))
    574     RunJsScript(pRuntime, pTimer->GetJScript());
    575 }
    576 
    577 void app::CancelProc(GlobalTimer* pTimer) {
    578   m_Timers.erase(pdfium::FakeUniquePtr<GlobalTimer>(pTimer));
    579 }
    580 
    581 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) {
    582   if (!pRuntime->IsBlocking()) {
    583     IJS_EventContext* pContext = pRuntime->NewEventContext();
    584     pContext->OnExternal_Exec();
    585     CFX_WideString wtInfo;
    586     pContext->RunScript(wsScript, &wtInfo);
    587     pRuntime->ReleaseEventContext(pContext);
    588   }
    589 }
    590 
    591 bool app::goBack(CJS_Runtime* pRuntime,
    592                  const std::vector<CJS_Value>& params,
    593                  CJS_Value& vRet,
    594                  CFX_WideString& sError) {
    595   // Not supported.
    596   return true;
    597 }
    598 
    599 bool app::goForward(CJS_Runtime* pRuntime,
    600                     const std::vector<CJS_Value>& params,
    601                     CJS_Value& vRet,
    602                     CFX_WideString& sError) {
    603   // Not supported.
    604   return true;
    605 }
    606 
    607 bool app::mailMsg(CJS_Runtime* pRuntime,
    608                   const std::vector<CJS_Value>& params,
    609                   CJS_Value& vRet,
    610                   CFX_WideString& sError) {
    611   std::vector<CJS_Value> newParams =
    612       JS_ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc",
    613                              L"cBcc", L"cSubject", L"cMsg");
    614 
    615   if (newParams[0].GetType() == CJS_Value::VT_unknown) {
    616     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    617     return false;
    618   }
    619   bool bUI = newParams[0].ToBool(pRuntime);
    620 
    621   CFX_WideString cTo;
    622   if (newParams[1].GetType() != CJS_Value::VT_unknown) {
    623     cTo = newParams[1].ToCFXWideString(pRuntime);
    624   } else {
    625     if (!bUI) {
    626       // cTo parameter required when UI not invoked.
    627       sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    628       return false;
    629     }
    630   }
    631 
    632   CFX_WideString cCc;
    633   if (newParams[2].GetType() != CJS_Value::VT_unknown)
    634     cCc = newParams[2].ToCFXWideString(pRuntime);
    635 
    636   CFX_WideString cBcc;
    637   if (newParams[3].GetType() != CJS_Value::VT_unknown)
    638     cBcc = newParams[3].ToCFXWideString(pRuntime);
    639 
    640   CFX_WideString cSubject;
    641   if (newParams[4].GetType() != CJS_Value::VT_unknown)
    642     cSubject = newParams[4].ToCFXWideString(pRuntime);
    643 
    644   CFX_WideString cMsg;
    645   if (newParams[5].GetType() != CJS_Value::VT_unknown)
    646     cMsg = newParams[5].ToCFXWideString(pRuntime);
    647 
    648   pRuntime->BeginBlock();
    649   pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(),
    650                                              cSubject.c_str(), cCc.c_str(),
    651                                              cBcc.c_str(), cMsg.c_str());
    652   pRuntime->EndBlock();
    653   return true;
    654 }
    655 
    656 bool app::launchURL(CJS_Runtime* pRuntime,
    657                     const std::vector<CJS_Value>& params,
    658                     CJS_Value& vRet,
    659                     CFX_WideString& sError) {
    660   // Unsafe, not supported.
    661   return true;
    662 }
    663 
    664 bool app::runtimeHighlight(CJS_Runtime* pRuntime,
    665                            CJS_PropValue& vp,
    666                            CFX_WideString& sError) {
    667   if (vp.IsSetting()) {
    668     vp >> m_bRuntimeHighLight;
    669   } else {
    670     vp << m_bRuntimeHighLight;
    671   }
    672   return true;
    673 }
    674 
    675 bool app::fullscreen(CJS_Runtime* pRuntime,
    676                      CJS_PropValue& vp,
    677                      CFX_WideString& sError) {
    678   return false;
    679 }
    680 
    681 bool app::popUpMenu(CJS_Runtime* pRuntime,
    682                     const std::vector<CJS_Value>& params,
    683                     CJS_Value& vRet,
    684                     CFX_WideString& sError) {
    685   return false;
    686 }
    687 
    688 bool app::browseForDoc(CJS_Runtime* pRuntime,
    689                        const std::vector<CJS_Value>& params,
    690                        CJS_Value& vRet,
    691                        CFX_WideString& sError) {
    692   // Unsafe, not supported.
    693   return true;
    694 }
    695 
    696 CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath) {
    697   CFX_WideString sRet = L"/";
    698 
    699   for (int i = 0, sz = sOldPath.GetLength(); i < sz; i++) {
    700     wchar_t c = sOldPath.GetAt(i);
    701     if (c == L':') {
    702     } else {
    703       if (c == L'\\') {
    704         sRet += L"/";
    705       } else {
    706         sRet += c;
    707       }
    708     }
    709   }
    710 
    711   return sRet;
    712 }
    713 
    714 bool app::newDoc(CJS_Runtime* pRuntime,
    715                  const std::vector<CJS_Value>& params,
    716                  CJS_Value& vRet,
    717                  CFX_WideString& sError) {
    718   return false;
    719 }
    720 
    721 bool app::openDoc(CJS_Runtime* pRuntime,
    722                   const std::vector<CJS_Value>& params,
    723                   CJS_Value& vRet,
    724                   CFX_WideString& sError) {
    725   return false;
    726 }
    727 
    728 bool app::response(CJS_Runtime* pRuntime,
    729                    const std::vector<CJS_Value>& params,
    730                    CJS_Value& vRet,
    731                    CFX_WideString& sError) {
    732   std::vector<CJS_Value> newParams =
    733       JS_ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle",
    734                              L"cDefault", L"bPassword", L"cLabel");
    735 
    736   if (newParams[0].GetType() == CJS_Value::VT_unknown) {
    737     sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
    738     return false;
    739   }
    740   CFX_WideString swQuestion = newParams[0].ToCFXWideString(pRuntime);
    741 
    742   CFX_WideString swTitle = L"PDF";
    743   if (newParams[1].GetType() != CJS_Value::VT_unknown)
    744     swTitle = newParams[1].ToCFXWideString(pRuntime);
    745 
    746   CFX_WideString swDefault;
    747   if (newParams[2].GetType() != CJS_Value::VT_unknown)
    748     swDefault = newParams[2].ToCFXWideString(pRuntime);
    749 
    750   bool bPassword = false;
    751   if (newParams[3].GetType() != CJS_Value::VT_unknown)
    752     bPassword = newParams[3].ToBool(pRuntime);
    753 
    754   CFX_WideString swLabel;
    755   if (newParams[4].GetType() != CJS_Value::VT_unknown)
    756     swLabel = newParams[4].ToCFXWideString(pRuntime);
    757 
    758   const int MAX_INPUT_BYTES = 2048;
    759   std::unique_ptr<char[]> pBuff(new char[MAX_INPUT_BYTES + 2]);
    760   memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2);
    761 
    762   int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse(
    763       swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(),
    764       bPassword, pBuff.get(), MAX_INPUT_BYTES);
    765 
    766   if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) {
    767     sError = JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG);
    768     return false;
    769   }
    770 
    771   vRet = CJS_Value(pRuntime, CFX_WideString::FromUTF16LE(
    772                                  reinterpret_cast<uint16_t*>(pBuff.get()),
    773                                  nLengthBytes / sizeof(uint16_t))
    774                                  .c_str());
    775 
    776   return true;
    777 }
    778 
    779 bool app::media(CJS_Runtime* pRuntime,
    780                 CJS_PropValue& vp,
    781                 CFX_WideString& sError) {
    782   return false;
    783 }
    784 
    785 bool app::execDialog(CJS_Runtime* pRuntime,
    786                      const std::vector<CJS_Value>& params,
    787                      CJS_Value& vRet,
    788                      CFX_WideString& sError) {
    789   return true;
    790 }
    791