Expand CJS_Document::mail{Doc,Form}() parameters

Use ExpandKeywordParams() rather than ad-hoc processing.
Add test case for {} argument.

Change-Id: I1f60a87b3995d62f4bead79245a1f58fd31b102e
Reviewed-on: https://pdfium-review.googlesource.com/c/44290
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
index a0dd2ec..8f60d13 100644
--- a/fxjs/cjs_document.cpp
+++ b/fxjs/cjs_document.cpp
@@ -377,42 +377,40 @@
 CJS_Result CJS_Document::mailDoc(
     CJS_Runtime* pRuntime,
     const std::vector<v8::Local<v8::Value>>& params) {
-  // TODO(tsepez): Check maximum number of allowed params.
-  size_t nLength = params.size();
-  bool bUI = true;
-  WideString cTo;
-  WideString cCc;
-  WideString cBcc;
-  WideString cSubject;
-  WideString cMsg;
+  if (!m_pFormFillEnv)
+    return CJS_Result::Failure(JSMessage::kBadObjectError);
 
-  if (nLength > 0 && params[0]->IsObject()) {
-    v8::Local<v8::Object> pObj = pRuntime->ToObject(params[0]);
-    bUI = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, L"bUI"));
-    cTo = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cTo"));
-    cCc = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cCc"));
-    cBcc = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cBcc"));
-    cSubject =
-        pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cSubject"));
-    cMsg = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cMsg"));
-  } else {
-    if (nLength > 0)
-      bUI = pRuntime->ToBoolean(params[0]);
-    if (nLength > 1)
-      cTo = pRuntime->ToWideString(params[1]);
-    if (nLength > 2)
-      cCc = pRuntime->ToWideString(params[2]);
-    if (nLength > 3)
-      cBcc = pRuntime->ToWideString(params[3]);
-    if (nLength > 4)
-      cSubject = pRuntime->ToWideString(params[4]);
-    if (nLength > 5)
-      cMsg = pRuntime->ToWideString(params[5]);
-  }
+  std::vector<v8::Local<v8::Value>> newParams =
+      ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", L"cBcc",
+                          L"cSubject", L"cMsg");
+
+  bool bUI = true;
+  if (IsExpandedParamKnown(newParams[0]))
+    bUI = pRuntime->ToBoolean(newParams[0]);
+
+  WideString cTo;
+  if (IsExpandedParamKnown(newParams[1]))
+    cTo = pRuntime->ToWideString(newParams[1]);
+
+  WideString cCc;
+  if (IsExpandedParamKnown(newParams[2]))
+    cCc = pRuntime->ToWideString(newParams[2]);
+
+  WideString cBcc;
+  if (IsExpandedParamKnown(newParams[3]))
+    cBcc = pRuntime->ToWideString(newParams[3]);
+
+  WideString cSubject;
+  if (IsExpandedParamKnown(newParams[4]))
+    cSubject = pRuntime->ToWideString(newParams[4]);
+
+  WideString cMsg;
+  if (IsExpandedParamKnown(newParams[5]))
+    cMsg = pRuntime->ToWideString(newParams[5]);
 
   pRuntime->BeginBlock();
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
-  pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo, cSubject, cCc, cBcc, cMsg);
+  m_pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo, cSubject, cCc, cBcc,
+                                 cMsg);
   pRuntime->EndBlock();
   return CJS_Result::Success();
 }
@@ -433,19 +431,38 @@
   if (sTextBuf.GetLength() == 0)
     return CJS_Result::Failure(L"Bad FDF format.");
 
-  size_t nLength = params.size();
-  bool bUI = nLength > 0 ? pRuntime->ToBoolean(params[0]) : true;
-  WideString cTo = nLength > 1 ? pRuntime->ToWideString(params[1]) : L"";
-  WideString cCc = nLength > 2 ? pRuntime->ToWideString(params[2]) : L"";
-  WideString cBcc = nLength > 3 ? pRuntime->ToWideString(params[3]) : L"";
-  WideString cSubject = nLength > 4 ? pRuntime->ToWideString(params[4]) : L"";
-  WideString cMsg = nLength > 5 ? pRuntime->ToWideString(params[5]) : L"";
-  std::vector<char> mutable_buf(sTextBuf.begin(), sTextBuf.end());
+  std::vector<v8::Local<v8::Value>> newParams =
+      ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", L"cBcc",
+                          L"cSubject", L"cMsg");
 
+  bool bUI = true;
+  if (IsExpandedParamKnown(newParams[0]))
+    bUI = pRuntime->ToBoolean(newParams[0]);
+
+  WideString cTo;
+  if (IsExpandedParamKnown(newParams[1]))
+    cTo = pRuntime->ToWideString(newParams[1]);
+
+  WideString cCc;
+  if (IsExpandedParamKnown(newParams[2]))
+    cCc = pRuntime->ToWideString(newParams[2]);
+
+  WideString cBcc;
+  if (IsExpandedParamKnown(newParams[3]))
+    cBcc = pRuntime->ToWideString(newParams[3]);
+
+  WideString cSubject;
+  if (IsExpandedParamKnown(newParams[4]))
+    cSubject = pRuntime->ToWideString(newParams[4]);
+
+  WideString cMsg;
+  if (IsExpandedParamKnown(newParams[5]))
+    cMsg = pRuntime->ToWideString(newParams[5]);
+
+  std::vector<char> mutable_buf(sTextBuf.begin(), sTextBuf.end());
   pRuntime->BeginBlock();
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
-  pFormFillEnv->JS_docmailForm(mutable_buf.data(), mutable_buf.size(), bUI, cTo,
-                               cSubject, cCc, cBcc, cMsg);
+  m_pFormFillEnv->JS_docmailForm(mutable_buf.data(), mutable_buf.size(), bUI,
+                                 cTo, cSubject, cCc, cBcc, cMsg);
   pRuntime->EndBlock();
   return CJS_Result::Success();
 }
diff --git a/testing/resources/javascript/document_methods.in b/testing/resources/javascript/document_methods.in
index bb7af74..be4bf63 100644
--- a/testing/resources/javascript/document_methods.in
+++ b/testing/resources/javascript/document_methods.in
@@ -260,10 +260,16 @@
   // TODO(tsepez): test with no permissions.
 
   // Success cases.
-  expect('this.mailDoc(true)', undefined);
+  expect('this.mailDoc()', undefined);
   expect('this.mailDoc(false, "user@example.com", "cc@example.com", ' +
              '"bcc@example.com", "Lottery Winner", "You won the lottery!")',
          undefined);
+  expect('this.mailDoc({})', undefined);
+  expect('this.mailDoc({"bUI": false, "cTo": "user@example.com", ' +
+            '"cCc": "cc@example.com", "cBcc": "bcc@example.com", ' +
+            '"cSubject": "LotteryWinner", "cMsg": "You won the lottery!", ' +
+            '"bogus": "yes"})',
+         undefined);
 }
 
 function testMailForm() {
@@ -273,10 +279,16 @@
   // TODO(tsepez): test with no permissions.
 
   // Success cases.
-  expect('this.mailForm(true)', undefined);
+  expect('this.mailForm()', undefined);
   expect('this.mailForm(false, "user@example.com", "cc@example.com", ' +
              '"bcc@example.com", "Lottery Winner", "You won the lottery!")',
          undefined);
+  expect('this.mailForm({})', undefined);
+  expect('this.mailForm({"bUI": false, "cTo": "user@example.com", ' +
+            '"cCc": "cc@example.com", "cBcc": "bcc@example.com", ' +
+            '"cSubject": "LotteryWinner", "cMsg": "You won the lottery!", ' +
+            '"bogus": "yes"})',
+         undefined);
 }
 
 function testPrint() {
diff --git a/testing/resources/javascript/document_methods_expected.txt b/testing/resources/javascript/document_methods_expected.txt
index e39690b..d4daf99 100644
--- a/testing/resources/javascript/document_methods_expected.txt
+++ b/testing/resources/javascript/document_methods_expected.txt
@@ -109,14 +109,22 @@
 Alert: PASS: this.gotoNamedDest("chicago") threw error Document.gotoNamedDest: Object no longer exists.
 Alert: PASS: typeof this.mailDoc = function
 Mail Msg: 1, to=, cc=, bcc=, subject=, body=
-Alert: PASS: this.mailDoc(true) = undefined
+Alert: PASS: this.mailDoc() = undefined
 Mail Msg: 0, to=user@example.com, cc=cc@example.com, bcc=bcc@example.com, subject=Lottery Winner, body=You won the lottery!
 Alert: PASS: this.mailDoc(false, "user@example.com", "cc@example.com", "bcc@example.com", "Lottery Winner", "You won the lottery!") = undefined
+Mail Msg: 1, to=, cc=, bcc=, subject=, body=
+Alert: PASS: this.mailDoc({}) = undefined
+Mail Msg: 0, to=user@example.com, cc=cc@example.com, bcc=bcc@example.com, subject=LotteryWinner, body=You won the lottery!
+Alert: PASS: this.mailDoc({"bUI": false, "cTo": "user@example.com", "cCc": "cc@example.com", "cBcc": "bcc@example.com", "cSubject": "LotteryWinner", "cMsg": "You won the lottery!", "bogus": "yes"}) = undefined
 Alert: PASS: typeof this.mailForm = function
 Mail Msg: 1, to=, cc=, bcc=, subject=, body=
-Alert: PASS: this.mailForm(true) = undefined
+Alert: PASS: this.mailForm() = undefined
 Mail Msg: 0, to=user@example.com, cc=cc@example.com, bcc=bcc@example.com, subject=Lottery Winner, body=You won the lottery!
 Alert: PASS: this.mailForm(false, "user@example.com", "cc@example.com", "bcc@example.com", "Lottery Winner", "You won the lottery!") = undefined
+Mail Msg: 1, to=, cc=, bcc=, subject=, body=
+Alert: PASS: this.mailForm({}) = undefined
+Mail Msg: 0, to=user@example.com, cc=cc@example.com, bcc=bcc@example.com, subject=LotteryWinner, body=You won the lottery!
+Alert: PASS: this.mailForm({"bUI": false, "cTo": "user@example.com", "cCc": "cc@example.com", "cBcc": "bcc@example.com", "cSubject": "LotteryWinner", "cMsg": "You won the lottery!", "bogus": "yes"}) = undefined
 Alert: PASS: typeof this.print = function
 Doc Print: 1, 0, 0, 0, 0, 0, 0, 0
 Alert: PASS: this.print() = undefined