From 58fb36a3de3174db41669c2ed0d67e4a18a4a6de Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Mon, 1 Feb 2016 10:32:14 -0800 Subject: Merge to XFA: Use JS_ExpandKeywordParams() in app.response() Original Review URL: https://codereview.chromium.org/1654523002 . (cherry picked from commit 3859258ebe9e81e1f766b57e7f78c786ae4ed495) TBR=thestig@chromium.org Review URL: https://codereview.chromium.org/1658753002 . --- fpdfsdk/src/javascript/app.cpp | 87 ++++++++-------------- samples/pdfium_test.cc | 27 +++++++ testing/resources/javascript/app_repsonse.in | 75 +++++++++++++++++++ .../resources/javascript/app_repsonse_expected.txt | 10 +++ 4 files changed, 142 insertions(+), 57 deletions(-) create mode 100644 testing/resources/javascript/app_repsonse.in create mode 100644 testing/resources/javascript/app_repsonse_expected.txt diff --git a/fpdfsdk/src/javascript/app.cpp b/fpdfsdk/src/javascript/app.cpp index 057bf7ea58..3a971cf146 100644 --- a/fpdfsdk/src/javascript/app.cpp +++ b/fpdfsdk/src/javascript/app.cpp @@ -690,77 +690,50 @@ FX_BOOL app::response(IJS_Context* cc, const std::vector& params, CJS_Value& vRet, CFX_WideString& sError) { - CFX_WideString swQuestion = L""; - CFX_WideString swLabel = L""; - CFX_WideString swTitle = L"PDF"; - CFX_WideString swDefault = L""; - bool bPassWord = false; - + CJS_Context* pContext = static_cast(cc); CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc); - v8::Isolate* isolate = pRuntime->GetIsolate(); - - int iLength = params.size(); - if (iLength > 0 && params[0].GetType() == CJS_Value::VT_object) { - v8::Local pObj = params[0].ToV8Object(); - v8::Local pValue = - FXJS_GetObjectElement(isolate, pObj, L"cQuestion"); - swQuestion = - CJS_Value(pRuntime, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString(); + std::vector newParams = + JS_ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle", + L"cDefault", L"bPassword", L"cLabel"); - pValue = FXJS_GetObjectElement(isolate, pObj, L"cTitle"); - swTitle = - CJS_Value(pRuntime, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString(); + if (newParams[0].GetType() == CJS_Value::VT_unknown) { + sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR); + return FALSE; + } + CFX_WideString swQuestion = newParams[0].ToCFXWideString(); - pValue = FXJS_GetObjectElement(isolate, pObj, L"cDefault"); - swDefault = - CJS_Value(pRuntime, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString(); + CFX_WideString swTitle = L"PDF"; + if (newParams[1].GetType() != CJS_Value::VT_unknown) + swTitle = newParams[1].ToCFXWideString(); - pValue = FXJS_GetObjectElement(isolate, pObj, L"cLabel"); - swLabel = - CJS_Value(pRuntime, pValue, GET_VALUE_TYPE(pValue)).ToCFXWideString(); + CFX_WideString swDefault; + if (newParams[2].GetType() != CJS_Value::VT_unknown) + swDefault = newParams[2].ToCFXWideString(); - pValue = FXJS_GetObjectElement(isolate, pObj, L"bPassword"); - bPassWord = CJS_Value(pRuntime, pValue, GET_VALUE_TYPE(pValue)).ToBool(); - } else { - switch (iLength) { - case 5: - swLabel = params[4].ToCFXWideString(); - // FALLTHROUGH - case 4: - bPassWord = params[3].ToBool(); - // FALLTHROUGH - case 3: - swDefault = params[2].ToCFXWideString(); - // FALLTHROUGH - case 2: - swTitle = params[1].ToCFXWideString(); - // FALLTHROUGH - case 1: - swQuestion = params[0].ToCFXWideString(); - // FALLTHROUGH - default: - break; - } - } + bool bPassword = false; + if (newParams[3].GetType() != CJS_Value::VT_unknown) + bPassword = newParams[3].ToBool(); - CJS_Context* pContext = (CJS_Context*)cc; - CPDFDoc_Environment* pApp = pContext->GetReaderApp(); + CFX_WideString swLabel; + if (newParams[4].GetType() != CJS_Value::VT_unknown) + swLabel = newParams[4].ToCFXWideString(); const int MAX_INPUT_BYTES = 2048; std::unique_ptr pBuff(new char[MAX_INPUT_BYTES + 2]); memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2); - int nLengthBytes = pApp->JS_appResponse( + + int nLengthBytes = pContext->GetReaderApp()->JS_appResponse( swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(), - bPassWord, pBuff.get(), MAX_INPUT_BYTES); - if (nLengthBytes <= 0) { - vRet.SetNull(); + bPassword, pBuff.get(), MAX_INPUT_BYTES); + + if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) { + sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG); return FALSE; } - nLengthBytes = std::min(nLengthBytes, MAX_INPUT_BYTES); - CFX_WideString ret_string = CFX_WideString::FromUTF16LE( - (unsigned short*)pBuff.get(), nLengthBytes / sizeof(unsigned short)); - vRet = ret_string.c_str(); + vRet = CFX_WideString::FromUTF16LE(reinterpret_cast(pBuff.get()), + nLengthBytes / sizeof(uint16_t)) + .c_str(); return TRUE; } diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index e3e28a5034..11afc2fcd6 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -195,6 +195,9 @@ void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) { } #endif +// These example JS platform callback handlers are entirely optional, +// and exist here to show the flow of information from a document back +// to the embedder. int ExampleAppAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING msg, FPDF_WIDESTRING title, @@ -207,6 +210,29 @@ int ExampleAppAlert(IPDF_JSPLATFORM*, return 0; } +int ExampleAppResponse(IPDF_JSPLATFORM*, + FPDF_WIDESTRING question, + FPDF_WIDESTRING title, + FPDF_WIDESTRING defaultValue, + FPDF_WIDESTRING label, + FPDF_BOOL isPassword, + void* response, + int length) { + printf("%ls: %ls, defaultValue=%ls, label=%ls, isPassword=%d, length=%d\n", + GetPlatformWString(title).c_str(), + GetPlatformWString(question).c_str(), + GetPlatformWString(defaultValue).c_str(), + GetPlatformWString(label).c_str(), isPassword, length); + + // UTF-16, always LE regardless of platform. + uint8_t* ptr = static_cast(response); + ptr[0] = 'N'; + ptr[1] = 0; + ptr[2] = 'o'; + ptr[3] = 0; + return 4; +} + void ExampleDocGotoPage(IPDF_JSPLATFORM*, int pageNumber) { printf("Goto Page: %d\n", pageNumber); } @@ -425,6 +451,7 @@ void RenderPdf(const std::string& name, const char* pBuf, size_t len, memset(&platform_callbacks, '\0', sizeof(platform_callbacks)); platform_callbacks.version = 3; platform_callbacks.app_alert = ExampleAppAlert; + platform_callbacks.app_response = ExampleAppResponse; platform_callbacks.Doc_gotoPage = ExampleDocGotoPage; platform_callbacks.Doc_mail = ExampleDocMail; diff --git a/testing/resources/javascript/app_repsonse.in b/testing/resources/javascript/app_repsonse.in new file mode 100644 index 0000000000..bd78da35e3 --- /dev/null +++ b/testing/resources/javascript/app_repsonse.in @@ -0,0 +1,75 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OpenAction 10 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /Contents [21 0 R] + /MediaBox [0 0 612 792] +>> +% OpenAction action +{{object 10 0}} << + /Type /Action + /S /JavaScript + /JS 11 0 R +>> +endobj +% JS program to exexute +{{object 11 0}} << +>> +stream +var result; +try { + result = app.response("question"); + app.alert("result: " + result); + result = app.response("question", "title", "default", true, "label"); + app.alert("result: " + result); + result = app.response({"cQuestion": "question"}); + app.alert("result: " + result); + result = app.response({ + "cQuestion": "question", + "cTitle": "title", + "cDefault": "default", + "bPassword": true, + "cLabel": "label" + }); + app.alert("result: " + result); +} catch (e) { + app.alert("unexpected error " + e); +} +try { + app.response(); + app.alert("unexpected success"); +} catch (e) { + app.alert("Caught expected error " + e); +} +try { + app.response({}); + app.alert("unexpected success"); +} catch (e) { + app.alert("Caught expected error " + e); +} +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/app_repsonse_expected.txt b/testing/resources/javascript/app_repsonse_expected.txt new file mode 100644 index 0000000000..8a2995986b --- /dev/null +++ b/testing/resources/javascript/app_repsonse_expected.txt @@ -0,0 +1,10 @@ +PDF: question, defaultValue=, label=, isPassword=0, length=2048 +Alert: result: No +title: question, defaultValue=default, label=label, isPassword=1, length=2048 +Alert: result: No +PDF: question, defaultValue=, label=, isPassword=0, length=2048 +Alert: result: No +title: question, defaultValue=default, label=label, isPassword=1, length=2048 +Alert: result: No +Alert: Caught expected error app.response: Incorrect number of parameters passed to function. +Alert: Caught expected error app.response: Incorrect number of parameters passed to function. -- cgit v1.2.3