Home | History | Annotate | Download | only in fxjs
      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 "fxjs/cjs_app.h"
      8 
      9 #include "fpdfsdk/cpdfsdk_interform.h"
     10 #include "fxjs/cjs_document.h"
     11 #include "fxjs/cjs_timerobj.h"
     12 #include "fxjs/global_timer.h"
     13 #include "fxjs/ijs_event_context.h"
     14 #include "fxjs/js_resources.h"
     15 
     16 namespace {
     17 
     18 bool IsTypeKnown(v8::Local<v8::Value> value) {
     19   return !value.IsEmpty() &&
     20          (value->IsString() || value->IsNumber() || value->IsBoolean() ||
     21           value->IsDate() || value->IsObject() || value->IsNull() ||
     22           value->IsUndefined());
     23 }
     24 
     25 }  // namespace
     26 
     27 #define JS_STR_VIEWERTYPE L"pdfium"
     28 #define JS_STR_VIEWERVARIATION L"Full"
     29 #define JS_STR_PLATFORM L"WIN"
     30 #define JS_STR_LANGUAGE L"ENU"
     31 #define JS_NUM_VIEWERVERSION 8
     32 #ifdef PDF_ENABLE_XFA
     33 #define JS_NUM_VIEWERVERSION_XFA 11
     34 #endif  // PDF_ENABLE_XFA
     35 #define JS_NUM_FORMSVERSION 7
     36 
     37 const JSPropertySpec CJS_App::PropertySpecs[] = {
     38     {"activeDocs", get_active_docs_static, set_active_docs_static},
     39     {"calculate", get_calculate_static, set_calculate_static},
     40     {"formsVersion", get_forms_version_static, set_forms_version_static},
     41     {"fs", get_fs_static, set_fs_static},
     42     {"fullscreen", get_fullscreen_static, set_fullscreen_static},
     43     {"language", get_language_static, set_language_static},
     44     {"media", get_media_static, set_media_static},
     45     {"platform", get_platform_static, set_platform_static},
     46     {"runtimeHighlight", get_runtime_highlight_static,
     47      set_runtime_highlight_static},
     48     {"viewerType", get_viewer_type_static, set_viewer_type_static},
     49     {"viewerVariation", get_viewer_variation_static,
     50      set_viewer_variation_static},
     51     {"viewerVersion", get_viewer_version_static, set_viewer_version_static}};
     52 
     53 const JSMethodSpec CJS_App::MethodSpecs[] = {
     54     {"alert", alert_static},
     55     {"beep", beep_static},
     56     {"browseForDoc", browseForDoc_static},
     57     {"clearInterval", clearInterval_static},
     58     {"clearTimeOut", clearTimeOut_static},
     59     {"execDialog", execDialog_static},
     60     {"execMenuItem", execMenuItem_static},
     61     {"findComponent", findComponent_static},
     62     {"goBack", goBack_static},
     63     {"goForward", goForward_static},
     64     {"launchURL", launchURL_static},
     65     {"mailMsg", mailMsg_static},
     66     {"newFDF", newFDF_static},
     67     {"newDoc", newDoc_static},
     68     {"openDoc", openDoc_static},
     69     {"openFDF", openFDF_static},
     70     {"popUpMenuEx", popUpMenuEx_static},
     71     {"popUpMenu", popUpMenu_static},
     72     {"response", response_static},
     73     {"setInterval", setInterval_static},
     74     {"setTimeOut", setTimeOut_static}};
     75 
     76 int CJS_App::ObjDefnID = -1;
     77 
     78 // static
     79 void CJS_App::DefineJSObjects(CFXJS_Engine* pEngine) {
     80   ObjDefnID =
     81       pEngine->DefineObj("app", FXJSOBJTYPE_STATIC, JSConstructor<CJS_App, app>,
     82                          JSDestructor<CJS_App>);
     83   DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs));
     84   DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs));
     85 }
     86 
     87 app::app(CJS_Object* pJSObject)
     88     : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {}
     89 
     90 app::~app() {}
     91 
     92 CJS_Return app::get_active_docs(CJS_Runtime* pRuntime) {
     93   CJS_Document* pJSDocument = nullptr;
     94   v8::Local<v8::Object> pObj = pRuntime->GetThisObj();
     95   if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::GetObjDefnID())
     96     pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pObj));
     97 
     98   v8::Local<v8::Array> aDocs = pRuntime->NewArray();
     99   pRuntime->PutArrayElement(
    100       aDocs, 0,
    101       pJSDocument ? v8::Local<v8::Value>(pJSDocument->ToV8Object())
    102                   : v8::Local<v8::Value>());
    103   if (pRuntime->GetArrayLength(aDocs) > 0)
    104     return CJS_Return(aDocs);
    105   return CJS_Return(pRuntime->NewUndefined());
    106 }
    107 
    108 CJS_Return app::set_active_docs(CJS_Runtime* pRuntime,
    109                                 v8::Local<v8::Value> vp) {
    110   return CJS_Return(false);
    111 }
    112 
    113 CJS_Return app::get_calculate(CJS_Runtime* pRuntime) {
    114   return CJS_Return(pRuntime->NewBoolean(m_bCalculate));
    115 }
    116 
    117 CJS_Return app::set_calculate(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    118   m_bCalculate = pRuntime->ToBoolean(vp);
    119   pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate(m_bCalculate);
    120   return CJS_Return(true);
    121 }
    122 
    123 CJS_Return app::get_forms_version(CJS_Runtime* pRuntime) {
    124   return CJS_Return(pRuntime->NewNumber(JS_NUM_FORMSVERSION));
    125 }
    126 
    127 CJS_Return app::set_forms_version(CJS_Runtime* pRuntime,
    128                                   v8::Local<v8::Value> vp) {
    129   return CJS_Return(false);
    130 }
    131 
    132 CJS_Return app::get_viewer_type(CJS_Runtime* pRuntime) {
    133   return CJS_Return(pRuntime->NewString(JS_STR_VIEWERTYPE));
    134 }
    135 
    136 CJS_Return app::set_viewer_type(CJS_Runtime* pRuntime,
    137                                 v8::Local<v8::Value> vp) {
    138   return CJS_Return(false);
    139 }
    140 
    141 CJS_Return app::get_viewer_variation(CJS_Runtime* pRuntime) {
    142   return CJS_Return(pRuntime->NewString(JS_STR_VIEWERVARIATION));
    143 }
    144 
    145 CJS_Return app::set_viewer_variation(CJS_Runtime* pRuntime,
    146                                      v8::Local<v8::Value> vp) {
    147   return CJS_Return(false);
    148 }
    149 
    150 CJS_Return app::get_viewer_version(CJS_Runtime* pRuntime) {
    151 #ifdef PDF_ENABLE_XFA
    152   CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext();
    153   if (pXFAContext->ContainsXFAForm())
    154     return CJS_Return(pRuntime->NewNumber(JS_NUM_VIEWERVERSION_XFA));
    155 #endif  // PDF_ENABLE_XFA
    156   return CJS_Return(pRuntime->NewNumber(JS_NUM_VIEWERVERSION));
    157 }
    158 
    159 CJS_Return app::set_viewer_version(CJS_Runtime* pRuntime,
    160                                    v8::Local<v8::Value> vp) {
    161   return CJS_Return(false);
    162 }
    163 
    164 CJS_Return app::get_platform(CJS_Runtime* pRuntime) {
    165 #ifdef PDF_ENABLE_XFA
    166   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    167   if (!pFormFillEnv)
    168     return CJS_Return(false);
    169 
    170   WideString platfrom = pFormFillEnv->GetPlatform();
    171   if (!platfrom.IsEmpty())
    172     return CJS_Return(pRuntime->NewString(platfrom.c_str()));
    173 #endif
    174   return CJS_Return(pRuntime->NewString(JS_STR_PLATFORM));
    175 }
    176 
    177 CJS_Return app::set_platform(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    178   return CJS_Return(false);
    179 }
    180 
    181 CJS_Return app::get_language(CJS_Runtime* pRuntime) {
    182 #ifdef PDF_ENABLE_XFA
    183   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    184   if (!pFormFillEnv)
    185     return CJS_Return(false);
    186 
    187   WideString language = pFormFillEnv->GetLanguage();
    188   if (!language.IsEmpty())
    189     return CJS_Return(pRuntime->NewString(language.c_str()));
    190 #endif
    191   return CJS_Return(pRuntime->NewString(JS_STR_LANGUAGE));
    192 }
    193 
    194 CJS_Return app::set_language(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    195   return CJS_Return(false);
    196 }
    197 
    198 // creates a new fdf object that contains no data
    199 // comment: need reader support
    200 // note:
    201 // CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF();
    202 CJS_Return app::newFDF(CJS_Runtime* pRuntime,
    203                        const std::vector<v8::Local<v8::Value>>& params) {
    204   return CJS_Return(true);
    205 }
    206 
    207 // opens a specified pdf document and returns its document object
    208 // comment:need reader support
    209 // note: as defined in js reference, the proto of this function's fourth
    210 // parmeters, how old an fdf document while do not show it.
    211 // CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool
    212 // bUserConv);
    213 
    214 CJS_Return app::openFDF(CJS_Runtime* pRuntime,
    215                         const std::vector<v8::Local<v8::Value>>& params) {
    216   return CJS_Return(true);
    217 }
    218 
    219 CJS_Return app::alert(CJS_Runtime* pRuntime,
    220                       const std::vector<v8::Local<v8::Value>>& params) {
    221   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
    222       pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle");
    223 
    224   if (!IsTypeKnown(newParams[0]))
    225     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    226 
    227   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
    228   if (!pFormFillEnv)
    229     return CJS_Return(pRuntime->NewNumber(0));
    230 
    231   WideString swMsg;
    232   if (newParams[0]->IsArray()) {
    233     v8::Local<v8::Array> carray = pRuntime->ToArray(newParams[0]);
    234     swMsg = L"[";
    235     for (size_t i = 0; i < pRuntime->GetArrayLength(carray); ++i) {
    236       if (i)
    237         swMsg += L", ";
    238 
    239       swMsg += pRuntime->ToWideString(pRuntime->GetArrayElement(carray, i));
    240     }
    241     swMsg += L"]";
    242   } else {
    243     swMsg = pRuntime->ToWideString(newParams[0]);
    244   }
    245 
    246   int iIcon = 0;
    247   if (IsTypeKnown(newParams[1]))
    248     iIcon = pRuntime->ToInt32(newParams[1]);
    249 
    250   int iType = 0;
    251   if (IsTypeKnown(newParams[2]))
    252     iType = pRuntime->ToInt32(newParams[2]);
    253 
    254   WideString swTitle;
    255   if (IsTypeKnown(newParams[3]))
    256     swTitle = pRuntime->ToWideString(newParams[3]);
    257   else
    258     swTitle = JSGetStringFromID(JSMessage::kAlert);
    259 
    260   pRuntime->BeginBlock();
    261   pFormFillEnv->KillFocusAnnot(0);
    262 
    263   v8::Local<v8::Value> ret = pRuntime->NewNumber(
    264       pFormFillEnv->JS_appAlert(swMsg.c_str(), swTitle.c_str(), iType, iIcon));
    265   pRuntime->EndBlock();
    266 
    267   return CJS_Return(ret);
    268 }
    269 
    270 CJS_Return app::beep(CJS_Runtime* pRuntime,
    271                      const std::vector<v8::Local<v8::Value>>& params) {
    272   if (params.size() == 1) {
    273     pRuntime->GetFormFillEnv()->JS_appBeep(pRuntime->ToInt32(params[0]));
    274     return CJS_Return(true);
    275   }
    276   return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    277 }
    278 
    279 CJS_Return app::findComponent(CJS_Runtime* pRuntime,
    280                               const std::vector<v8::Local<v8::Value>>& params) {
    281   return CJS_Return(true);
    282 }
    283 
    284 CJS_Return app::popUpMenuEx(CJS_Runtime* pRuntime,
    285                             const std::vector<v8::Local<v8::Value>>& params) {
    286   return CJS_Return(false);
    287 }
    288 
    289 CJS_Return app::get_fs(CJS_Runtime* pRuntime) {
    290   return CJS_Return(false);
    291 }
    292 
    293 CJS_Return app::set_fs(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    294   return CJS_Return(false);
    295 }
    296 
    297 CJS_Return app::setInterval(CJS_Runtime* pRuntime,
    298                             const std::vector<v8::Local<v8::Value>>& params) {
    299   if (params.size() > 2 || params.size() == 0)
    300     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    301 
    302   WideString script =
    303       params.size() > 0 ? pRuntime->ToWideString(params[0]) : L"";
    304   if (script.IsEmpty())
    305     return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError));
    306 
    307   uint32_t dwInterval = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000;
    308   GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(),
    309                                           pRuntime, 0, script, dwInterval, 0);
    310   m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
    311 
    312   v8::Local<v8::Object> pRetObj =
    313       pRuntime->NewFxDynamicObj(CJS_TimerObj::GetObjDefnID());
    314   if (pRetObj.IsEmpty())
    315     return CJS_Return(false);
    316 
    317   CJS_TimerObj* pJS_TimerObj =
    318       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
    319   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
    320   pTimerObj->SetTimer(timerRef);
    321 
    322   return CJS_Return(pRetObj);
    323 }
    324 
    325 CJS_Return app::setTimeOut(CJS_Runtime* pRuntime,
    326                            const std::vector<v8::Local<v8::Value>>& params) {
    327   if (params.size() > 2 || params.size() == 0)
    328     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    329 
    330   WideString script = pRuntime->ToWideString(params[0]);
    331   if (script.IsEmpty())
    332     return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError));
    333 
    334   uint32_t dwTimeOut = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000;
    335   GlobalTimer* timerRef =
    336       new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script,
    337                       dwTimeOut, dwTimeOut);
    338   m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
    339 
    340   v8::Local<v8::Object> pRetObj =
    341       pRuntime->NewFxDynamicObj(CJS_TimerObj::GetObjDefnID());
    342   if (pRetObj.IsEmpty())
    343     return CJS_Return(false);
    344 
    345   CJS_TimerObj* pJS_TimerObj =
    346       static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
    347   TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
    348   pTimerObj->SetTimer(timerRef);
    349 
    350   return CJS_Return(pRetObj);
    351 }
    352 
    353 CJS_Return app::clearTimeOut(CJS_Runtime* pRuntime,
    354                              const std::vector<v8::Local<v8::Value>>& params) {
    355   if (params.size() != 1)
    356     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    357 
    358   app::ClearTimerCommon(pRuntime, params[0]);
    359   return CJS_Return(true);
    360 }
    361 
    362 CJS_Return app::clearInterval(CJS_Runtime* pRuntime,
    363                               const std::vector<v8::Local<v8::Value>>& params) {
    364   if (params.size() != 1)
    365     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    366 
    367   app::ClearTimerCommon(pRuntime, params[0]);
    368   return CJS_Return(true);
    369 }
    370 
    371 void app::ClearTimerCommon(CJS_Runtime* pRuntime, v8::Local<v8::Value> param) {
    372   if (!param->IsObject())
    373     return;
    374 
    375   v8::Local<v8::Object> pObj = pRuntime->ToObject(param);
    376   if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::GetObjDefnID())
    377     return;
    378 
    379   CJS_Object* pJSObj =
    380       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(pObj));
    381   if (!pJSObj)
    382     return;
    383 
    384   TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject());
    385   if (!pTimerObj)
    386     return;
    387 
    388   GlobalTimer::Cancel(pTimerObj->GetTimerID());
    389 }
    390 
    391 CJS_Return app::execMenuItem(CJS_Runtime* pRuntime,
    392                              const std::vector<v8::Local<v8::Value>>& params) {
    393   return CJS_Return(false);
    394 }
    395 
    396 void app::TimerProc(GlobalTimer* pTimer) {
    397   CJS_Runtime* pRuntime = pTimer->GetRuntime();
    398   if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0))
    399     RunJsScript(pRuntime, pTimer->GetJScript());
    400 }
    401 
    402 void app::CancelProc(GlobalTimer* pTimer) {
    403   m_Timers.erase(pdfium::FakeUniquePtr<GlobalTimer>(pTimer));
    404 }
    405 
    406 void app::RunJsScript(CJS_Runtime* pRuntime, const WideString& wsScript) {
    407   if (!pRuntime->IsBlocking()) {
    408     IJS_EventContext* pContext = pRuntime->NewEventContext();
    409     pContext->OnExternal_Exec();
    410     WideString wtInfo;
    411     pContext->RunScript(wsScript, &wtInfo);
    412     pRuntime->ReleaseEventContext(pContext);
    413   }
    414 }
    415 
    416 CJS_Return app::goBack(CJS_Runtime* pRuntime,
    417                        const std::vector<v8::Local<v8::Value>>& params) {
    418   // Not supported.
    419   return CJS_Return(true);
    420 }
    421 
    422 CJS_Return app::goForward(CJS_Runtime* pRuntime,
    423                           const std::vector<v8::Local<v8::Value>>& params) {
    424   // Not supported.
    425   return CJS_Return(true);
    426 }
    427 
    428 CJS_Return app::mailMsg(CJS_Runtime* pRuntime,
    429                         const std::vector<v8::Local<v8::Value>>& params) {
    430   std::vector<v8::Local<v8::Value>> newParams =
    431       ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", L"cBcc",
    432                           L"cSubject", L"cMsg");
    433 
    434   if (!IsTypeKnown(newParams[0]))
    435     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    436 
    437   bool bUI = pRuntime->ToBoolean(newParams[0]);
    438   WideString cTo;
    439   if (IsTypeKnown(newParams[1])) {
    440     cTo = pRuntime->ToWideString(newParams[1]);
    441   } else {
    442     // cTo parameter required when UI not invoked.
    443     if (!bUI)
    444       return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    445   }
    446 
    447   WideString cCc;
    448   if (IsTypeKnown(newParams[2]))
    449     cCc = pRuntime->ToWideString(newParams[2]);
    450 
    451   WideString cBcc;
    452   if (IsTypeKnown(newParams[3]))
    453     cBcc = pRuntime->ToWideString(newParams[3]);
    454 
    455   WideString cSubject;
    456   if (IsTypeKnown(newParams[4]))
    457     cSubject = pRuntime->ToWideString(newParams[4]);
    458 
    459   WideString cMsg;
    460   if (IsTypeKnown(newParams[5]))
    461     cMsg = pRuntime->ToWideString(newParams[5]);
    462 
    463   pRuntime->BeginBlock();
    464   pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(),
    465                                              cSubject.c_str(), cCc.c_str(),
    466                                              cBcc.c_str(), cMsg.c_str());
    467   pRuntime->EndBlock();
    468   return CJS_Return(true);
    469 }
    470 
    471 CJS_Return app::launchURL(CJS_Runtime* pRuntime,
    472                           const std::vector<v8::Local<v8::Value>>& params) {
    473   // Unsafe, not supported.
    474   return CJS_Return(true);
    475 }
    476 
    477 CJS_Return app::get_runtime_highlight(CJS_Runtime* pRuntime) {
    478   return CJS_Return(pRuntime->NewBoolean(m_bRuntimeHighLight));
    479 }
    480 
    481 CJS_Return app::set_runtime_highlight(CJS_Runtime* pRuntime,
    482                                       v8::Local<v8::Value> vp) {
    483   m_bRuntimeHighLight = pRuntime->ToBoolean(vp);
    484   return CJS_Return(true);
    485 }
    486 
    487 CJS_Return app::get_fullscreen(CJS_Runtime* pRuntime) {
    488   return CJS_Return(false);
    489 }
    490 
    491 CJS_Return app::set_fullscreen(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    492   return CJS_Return(false);
    493 }
    494 
    495 CJS_Return app::popUpMenu(CJS_Runtime* pRuntime,
    496                           const std::vector<v8::Local<v8::Value>>& params) {
    497   return CJS_Return(false);
    498 }
    499 
    500 CJS_Return app::browseForDoc(CJS_Runtime* pRuntime,
    501                              const std::vector<v8::Local<v8::Value>>& params) {
    502   // Unsafe, not supported.
    503   return CJS_Return(true);
    504 }
    505 
    506 WideString app::SysPathToPDFPath(const WideString& sOldPath) {
    507   WideString sRet = L"/";
    508   for (const wchar_t& c : sOldPath) {
    509     if (c != L':')
    510       sRet += (c == L'\\') ? L'/' : c;
    511   }
    512   return sRet;
    513 }
    514 
    515 CJS_Return app::newDoc(CJS_Runtime* pRuntime,
    516                        const std::vector<v8::Local<v8::Value>>& params) {
    517   return CJS_Return(false);
    518 }
    519 
    520 CJS_Return app::openDoc(CJS_Runtime* pRuntime,
    521                         const std::vector<v8::Local<v8::Value>>& params) {
    522   return CJS_Return(false);
    523 }
    524 
    525 CJS_Return app::response(CJS_Runtime* pRuntime,
    526                          const std::vector<v8::Local<v8::Value>>& params) {
    527   std::vector<v8::Local<v8::Value>> newParams =
    528       ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle",
    529                           L"cDefault", L"bPassword", L"cLabel");
    530 
    531   if (!IsTypeKnown(newParams[0]))
    532     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
    533 
    534   WideString swQuestion = pRuntime->ToWideString(newParams[0]);
    535   WideString swTitle = L"PDF";
    536   if (IsTypeKnown(newParams[1]))
    537     swTitle = pRuntime->ToWideString(newParams[1]);
    538 
    539   WideString swDefault;
    540   if (IsTypeKnown(newParams[2]))
    541     swDefault = pRuntime->ToWideString(newParams[2]);
    542 
    543   bool bPassword = false;
    544   if (IsTypeKnown(newParams[3]))
    545     bPassword = pRuntime->ToBoolean(newParams[3]);
    546 
    547   WideString swLabel;
    548   if (IsTypeKnown(newParams[4]))
    549     swLabel = pRuntime->ToWideString(newParams[4]);
    550 
    551   const int MAX_INPUT_BYTES = 2048;
    552   std::vector<uint8_t> pBuff(MAX_INPUT_BYTES + 2);
    553   int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse(
    554       swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(),
    555       bPassword, pBuff.data(), MAX_INPUT_BYTES);
    556 
    557   if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES)
    558     return CJS_Return(JSGetStringFromID(JSMessage::kParamTooLongError));
    559 
    560   return CJS_Return(pRuntime->NewString(
    561       WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
    562                               nLengthBytes / sizeof(uint16_t))
    563           .c_str()));
    564 }
    565 
    566 CJS_Return app::get_media(CJS_Runtime* pRuntime) {
    567   return CJS_Return(false);
    568 }
    569 
    570 CJS_Return app::set_media(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    571   return CJS_Return(false);
    572 }
    573 
    574 CJS_Return app::execDialog(CJS_Runtime* pRuntime,
    575                            const std::vector<v8::Local<v8::Value>>& params) {
    576   return CJS_Return(true);
    577 }
    578