Remove PrintParams object.

The only way to theoretically get one is via doc.getPrintParams(),
and it always returns in error.

Even if one were returend to JS, there aren't any methods/callbacks
to change its properties.

Even if there were methods to change its properties, the information
it stores doesn't align with what is in the JS spec for this object.

Even if it were aligned with the JS spec, the way we check for its
presence as the ninth parameter in CJS_Document::print() doesn't
match the way its use is documented in the spec as the sole
first parameter.

Instead implement the older, simpler behaviour as spec'd prior to
6.0, and toss this enhancement altogether.

Move function to check the result of ExpandKeywordParams() to
js_define.h so other files can use it. Update comment in that
file to remove reference to deprecated enum.

Expand test for API and introduce callback to log parameters.

Change-Id: I047e2be0d2afbad91d6b58c6c74bbea083fed330
Reviewed-on: https://pdfium-review.googlesource.com/c/44271
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/BUILD.gn b/fxjs/BUILD.gn
index 2022d3b..5f475ed 100644
--- a/fxjs/BUILD.gn
+++ b/fxjs/BUILD.gn
@@ -74,8 +74,6 @@
       "cjs_object.h",
       "cjs_position.cpp",
       "cjs_position.h",
-      "cjs_printparamsobj.cpp",
-      "cjs_printparamsobj.h",
       "cjs_publicmethods.cpp",
       "cjs_publicmethods.h",
       "cjs_report.cpp",
diff --git a/fxjs/cjs_app.cpp b/fxjs/cjs_app.cpp
index e217753..f279250 100644
--- a/fxjs/cjs_app.cpp
+++ b/fxjs/cjs_app.cpp
@@ -21,17 +21,6 @@
 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
 #endif  // PDF_ENABLE_XFA
 
-namespace {
-
-bool IsTypeKnown(v8::Local<v8::Value> value) {
-  return !value.IsEmpty() &&
-         (value->IsString() || value->IsNumber() || value->IsBoolean() ||
-          value->IsDate() || value->IsObject() || value->IsNull() ||
-          value->IsUndefined());
-}
-
-}  // namespace
-
 #define JS_STR_VIEWERTYPE L"pdfium"
 #define JS_STR_VIEWERVARIATION L"Full"
 #define JS_STR_PLATFORM L"WIN"
@@ -237,7 +226,7 @@
   std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
       pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle");
 
-  if (!IsTypeKnown(newParams[0]))
+  if (!IsExpandedParamKnown(newParams[0]))
     return CJS_Result::Failure(JSMessage::kParamError);
 
   CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
@@ -260,15 +249,15 @@
   }
 
   int iIcon = JSPLATFORM_ALERT_ICON_DEFAULT;
-  if (IsTypeKnown(newParams[1]))
+  if (IsExpandedParamKnown(newParams[1]))
     iIcon = pRuntime->ToInt32(newParams[1]);
 
   int iType = JSPLATFORM_ALERT_BUTTON_DEFAULT;
-  if (IsTypeKnown(newParams[2]))
+  if (IsExpandedParamKnown(newParams[2]))
     iType = pRuntime->ToInt32(newParams[2]);
 
   WideString swTitle;
-  if (IsTypeKnown(newParams[3]))
+  if (IsExpandedParamKnown(newParams[3]))
     swTitle = pRuntime->ToWideString(newParams[3]);
   else
     swTitle = JSGetStringFromID(JSMessage::kAlert);
@@ -288,7 +277,7 @@
     return CJS_Result::Failure(JSMessage::kParamError);
 
   int type = JSPLATFORM_BEEP_DEFAULT;
-  if (IsTypeKnown(params[0]))
+  if (IsExpandedParamKnown(params[0]))
     type = pRuntime->ToInt32(params[0]);
 
   pRuntime->GetFormFillEnv()->JS_appBeep(type);
@@ -448,12 +437,12 @@
       ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", L"cBcc",
                           L"cSubject", L"cMsg");
 
-  if (!IsTypeKnown(newParams[0]))
+  if (!IsExpandedParamKnown(newParams[0]))
     return CJS_Result::Failure(JSMessage::kParamError);
 
   bool bUI = pRuntime->ToBoolean(newParams[0]);
   WideString cTo;
-  if (IsTypeKnown(newParams[1])) {
+  if (IsExpandedParamKnown(newParams[1])) {
     cTo = pRuntime->ToWideString(newParams[1]);
   } else {
     // cTo parameter required when UI not invoked.
@@ -462,19 +451,19 @@
   }
 
   WideString cCc;
-  if (IsTypeKnown(newParams[2]))
+  if (IsExpandedParamKnown(newParams[2]))
     cCc = pRuntime->ToWideString(newParams[2]);
 
   WideString cBcc;
-  if (IsTypeKnown(newParams[3]))
+  if (IsExpandedParamKnown(newParams[3]))
     cBcc = pRuntime->ToWideString(newParams[3]);
 
   WideString cSubject;
-  if (IsTypeKnown(newParams[4]))
+  if (IsExpandedParamKnown(newParams[4]))
     cSubject = pRuntime->ToWideString(newParams[4]);
 
   WideString cMsg;
-  if (IsTypeKnown(newParams[5]))
+  if (IsExpandedParamKnown(newParams[5]))
     cMsg = pRuntime->ToWideString(newParams[5]);
 
   pRuntime->BeginBlock();
@@ -546,24 +535,24 @@
       ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle",
                           L"cDefault", L"bPassword", L"cLabel");
 
-  if (!IsTypeKnown(newParams[0]))
+  if (!IsExpandedParamKnown(newParams[0]))
     return CJS_Result::Failure(JSMessage::kParamError);
 
   WideString swQuestion = pRuntime->ToWideString(newParams[0]);
   WideString swTitle = L"PDF";
-  if (IsTypeKnown(newParams[1]))
+  if (IsExpandedParamKnown(newParams[1]))
     swTitle = pRuntime->ToWideString(newParams[1]);
 
   WideString swDefault;
-  if (IsTypeKnown(newParams[2]))
+  if (IsExpandedParamKnown(newParams[2]))
     swDefault = pRuntime->ToWideString(newParams[2]);
 
   bool bPassword = false;
-  if (IsTypeKnown(newParams[3]))
+  if (IsExpandedParamKnown(newParams[3]))
     bPassword = pRuntime->ToBoolean(newParams[3]);
 
   WideString swLabel;
-  if (IsTypeKnown(newParams[4]))
+  if (IsExpandedParamKnown(newParams[4]))
     swLabel = pRuntime->ToWideString(newParams[4]);
 
   const int MAX_INPUT_BYTES = 2048;
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
index 2ecfd42..a0dd2ec 100644
--- a/fxjs/cjs_document.cpp
+++ b/fxjs/cjs_document.cpp
@@ -25,7 +25,6 @@
 #include "fxjs/cjs_delaydata.h"
 #include "fxjs/cjs_field.h"
 #include "fxjs/cjs_icon.h"
-#include "fxjs/cjs_printparamsobj.h"
 #include "fxjs/js_resources.h"
 
 namespace {
@@ -454,51 +453,41 @@
 CJS_Result CJS_Document::print(
     CJS_Runtime* pRuntime,
     const std::vector<v8::Local<v8::Value>>& params) {
-  if (!m_pFormFillEnv)
-    return CJS_Result::Failure(JSMessage::kBadObjectError);
+  std::vector<v8::Local<v8::Value>> newParams = ExpandKeywordParams(
+      pRuntime, params, 8, L"bUI", L"nStart", L"nEnd", L"bSilent",
+      L"bShrinkToFit", L"bPrintAsImage", L"bReverse", L"bAnnotations");
 
   bool bUI = true;
+  if (IsExpandedParamKnown(newParams[0]))
+    bUI = pRuntime->ToBoolean(newParams[0]);
+
   int nStart = 0;
+  if (IsExpandedParamKnown(newParams[1]))
+    nStart = pRuntime->ToInt32(newParams[1]);
+
   int nEnd = 0;
+  if (IsExpandedParamKnown(newParams[2]))
+    nEnd = pRuntime->ToInt32(newParams[2]);
+
   bool bSilent = false;
+  if (IsExpandedParamKnown(newParams[3]))
+    bSilent = pRuntime->ToBoolean(newParams[3]);
+
   bool bShrinkToFit = false;
+  if (IsExpandedParamKnown(newParams[4]))
+    bShrinkToFit = pRuntime->ToBoolean(newParams[4]);
+
   bool bPrintAsImage = false;
+  if (IsExpandedParamKnown(newParams[5]))
+    bPrintAsImage = pRuntime->ToBoolean(newParams[5]);
+
   bool bReverse = false;
+  if (IsExpandedParamKnown(newParams[6]))
+    bReverse = pRuntime->ToBoolean(newParams[6]);
+
   bool bAnnotations = false;
-  size_t nLength = params.size();
-  if (nLength == 9) {
-    if (params[8]->IsObject()) {
-      v8::Local<v8::Object> pObj = pRuntime->ToObject(params[8]);
-      auto pPrintObj = JSGetObject<CJS_PrintParamsObj>(pObj);
-      if (pPrintObj) {
-        bUI = pPrintObj->GetUI();
-        nStart = pPrintObj->GetStart();
-        nEnd = pPrintObj->GetEnd();
-        bSilent = pPrintObj->GetSilent();
-        bShrinkToFit = pPrintObj->GetShrinkToFit();
-        bPrintAsImage = pPrintObj->GetPrintAsImage();
-        bReverse = pPrintObj->GetReverse();
-        bAnnotations = pPrintObj->GetAnnotations();
-      }
-    }
-  } else {
-    if (nLength > 0)
-      bUI = pRuntime->ToBoolean(params[0]);
-    if (nLength > 1)
-      nStart = pRuntime->ToInt32(params[1]);
-    if (nLength > 2)
-      nEnd = pRuntime->ToInt32(params[2]);
-    if (nLength > 3)
-      bSilent = pRuntime->ToBoolean(params[3]);
-    if (nLength > 4)
-      bShrinkToFit = pRuntime->ToBoolean(params[4]);
-    if (nLength > 5)
-      bPrintAsImage = pRuntime->ToBoolean(params[5]);
-    if (nLength > 6)
-      bReverse = pRuntime->ToBoolean(params[6]);
-    if (nLength > 7)
-      bAnnotations = pRuntime->ToBoolean(params[7]);
-  }
+  if (IsExpandedParamKnown(newParams[7]))
+    bAnnotations = pRuntime->ToBoolean(newParams[7]);
 
   if (!m_pFormFillEnv)
     return CJS_Result::Failure(JSMessage::kBadObjectError);
@@ -1362,10 +1351,6 @@
 CJS_Result CJS_Document::getPrintParams(
     CJS_Runtime* pRuntime,
     const std::vector<v8::Local<v8::Value>>& params) {
-  v8::Local<v8::Object> pRetObj = pRuntime->NewFXJSBoundObject(
-      CJS_PrintParamsObj::GetObjDefnID(), FXJSOBJTYPE_DYNAMIC);
-  if (pRetObj.IsEmpty())
-    return CJS_Result::Failure(JSMessage::kBadObjectError);
   return CJS_Result::Failure(JSMessage::kNotSupportedError);
 }
 
diff --git a/fxjs/cjs_printparamsobj.cpp b/fxjs/cjs_printparamsobj.cpp
deleted file mode 100644
index 37ff956..0000000
--- a/fxjs/cjs_printparamsobj.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "fxjs/cjs_printparamsobj.h"
-
-#include "fxjs/js_define.h"
-
-int CJS_PrintParamsObj::ObjDefnID = -1;
-
-// static
-int CJS_PrintParamsObj::GetObjDefnID() {
-  return ObjDefnID;
-}
-
-// static
-void CJS_PrintParamsObj::DefineJSObjects(CFXJS_Engine* pEngine) {
-  ObjDefnID =
-      pEngine->DefineObj("PrintParamsObj", FXJSOBJTYPE_DYNAMIC,
-                         JSConstructor<CJS_PrintParamsObj>, JSDestructor);
-}
-
-CJS_PrintParamsObj::CJS_PrintParamsObj(v8::Local<v8::Object> pObject,
-                                       CJS_Runtime* pRuntime)
-    : CJS_Object(pObject, pRuntime) {}
-
-CJS_PrintParamsObj::~CJS_PrintParamsObj() = default;
diff --git a/fxjs/cjs_printparamsobj.h b/fxjs/cjs_printparamsobj.h
deleted file mode 100644
index f8b0557..0000000
--- a/fxjs/cjs_printparamsobj.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef FXJS_CJS_PRINTPARAMSOBJ_H_
-#define FXJS_CJS_PRINTPARAMSOBJ_H_
-
-#include "fxjs/cjs_object.h"
-
-class CJS_PrintParamsObj final : public CJS_Object {
- public:
-  static int GetObjDefnID();
-  static void DefineJSObjects(CFXJS_Engine* pEngine);
-
-  CJS_PrintParamsObj(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime);
-  ~CJS_PrintParamsObj() override;
-
-  bool GetUI() const { return bUI; }
-  int GetStart() const { return nStart; }
-  int GetEnd() const { return nEnd; }
-  bool GetSilent() const { return bSilent; }
-  bool GetShrinkToFit() const { return bShrinkToFit; }
-  bool GetPrintAsImage() const { return bPrintAsImage; }
-  bool GetReverse() const { return bReverse; }
-  bool GetAnnotations() const { return bAnnotations; }
-
- private:
-  static int ObjDefnID;
-
-  bool bUI = true;
-  int nStart = 0;
-  int nEnd = 0;
-  bool bSilent = false;
-  bool bShrinkToFit = false;
-  bool bPrintAsImage = false;
-  bool bReverse = false;
-  bool bAnnotations = true;
-};
-
-#endif  // FXJS_CJS_PRINTPARAMSOBJ_H_
diff --git a/fxjs/cjs_runtime.cpp b/fxjs/cjs_runtime.cpp
index 3bc8448..3914b36 100644
--- a/fxjs/cjs_runtime.cpp
+++ b/fxjs/cjs_runtime.cpp
@@ -29,7 +29,6 @@
 #include "fxjs/cjs_icon.h"
 #include "fxjs/cjs_object.h"
 #include "fxjs/cjs_position.h"
-#include "fxjs/cjs_printparamsobj.h"
 #include "fxjs/cjs_publicmethods.h"
 #include "fxjs/cjs_report.h"
 #include "fxjs/cjs_scalehow.h"
@@ -124,9 +123,8 @@
   CJS_GlobalConsts::DefineJSObjects(this);
   CJS_GlobalArrays::DefineJSObjects(this);
 
-  // ObjDefIDs 21 - 23.
+  // ObjDefIDs 21 - 22.
   CJS_TimerObj::DefineJSObjects(this);
-  CJS_PrintParamsObj::DefineJSObjects(this);
   CJS_Annot::DefineJSObjects(this);
 }
 
diff --git a/fxjs/js_define.cpp b/fxjs/js_define.cpp
index 0a18b6d..54bd8e1 100644
--- a/fxjs/js_define.cpp
+++ b/fxjs/js_define.cpp
@@ -313,3 +313,10 @@
 
   return result;
 }
+
+bool IsExpandedParamKnown(v8::Local<v8::Value> value) {
+  return !value.IsEmpty() &&
+         (value->IsString() || value->IsNumber() || value->IsBoolean() ||
+          value->IsDate() || value->IsObject() || value->IsNull() ||
+          value->IsUndefined());
+}
diff --git a/fxjs/js_define.h b/fxjs/js_define.h
index bf7aa35..0705dfe 100644
--- a/fxjs/js_define.h
+++ b/fxjs/js_define.h
@@ -35,14 +35,16 @@
 // with a single argument which is an object containing the actual arguments
 // as its properties. The varying arguments to this method are the property
 // names as wchar_t string literals corresponding to each positional argument.
-// The result will always contain |nKeywords| value, with unspecified ones
-// being set to type VT_unknown.
+// The result will always contain |nKeywords| value, check for the unspecified
+// ones in the result using IsExpandedParamKnown() below.
 std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
     CJS_Runtime* pRuntime,
     const std::vector<v8::Local<v8::Value>>& originals,
     size_t nKeywords,
     ...);
 
+bool IsExpandedParamKnown(v8::Local<v8::Value> value);
+
 // All JS classes have a name, an object defintion ID, and the ability to
 // register themselves with FXJS_V8. We never make a BASE class on its own
 // because it can't really do anything.
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index e64382c..c5c298d 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -219,6 +219,19 @@
          GetPlatformWString(BCC).c_str(), GetPlatformWString(Subject).c_str(),
          GetPlatformWString(Msg).c_str());
 }
+
+void ExampleDocPrint(IPDF_JSPLATFORM*,
+                     FPDF_BOOL bUI,
+                     int nStart,
+                     int nEnd,
+                     FPDF_BOOL bSilent,
+                     FPDF_BOOL bShrinkToFit,
+                     FPDF_BOOL bPrintAsImage,
+                     FPDF_BOOL bReverse,
+                     FPDF_BOOL bAnnotations) {
+  printf("Doc Print: %d, %d, %d, %d, %d, %d, %d, %d\n", bUI, nStart, nEnd,
+         bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations);
+}
 #endif  // PDF_ENABLE_V8
 
 void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {
@@ -724,6 +737,7 @@
   platform_callbacks.app_beep = ExampleAppBeep;
   platform_callbacks.Doc_gotoPage = ExampleDocGotoPage;
   platform_callbacks.Doc_mail = ExampleDocMail;
+  platform_callbacks.Doc_print = ExampleDocPrint;
 #endif  // PDF_ENABLE_V8
 
   FPDF_FORMFILLINFO_PDFiumTest form_callbacks = {};
diff --git a/testing/resources/javascript/document_methods.in b/testing/resources/javascript/document_methods.in
index 0188d7c..bb7af74 100644
--- a/testing/resources/javascript/document_methods.in
+++ b/testing/resources/javascript/document_methods.in
@@ -284,6 +284,12 @@
    expect('typeof this.print', 'function');
 
   // TODO(tsepez): test success cases.
+  expect('this.print()', undefined);
+  expect('this.print(false, 1, 10, true, true, true, true, true)', undefined);
+  expect('this.print({})', undefined);
+  expect('this.print({"bUi": false, "nStart": 42, "nEnd": 17, ' +
+            '"bSilent": true, "bShrinkToFit": true, "bPrintAsImage": true, ' +
+            '"bReverse": true, "bAnnotations": true, "bogus": "yes"})', undefined);
 }
 
 function testRemoveField() {
diff --git a/testing/resources/javascript/document_methods_expected.txt b/testing/resources/javascript/document_methods_expected.txt
index 01bf0ed..e39690b 100644
--- a/testing/resources/javascript/document_methods_expected.txt
+++ b/testing/resources/javascript/document_methods_expected.txt
@@ -118,6 +118,14 @@
 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
 Alert: PASS: typeof this.print = function
+Doc Print: 1, 0, 0, 0, 0, 0, 0, 0
+Alert: PASS: this.print() = undefined
+Doc Print: 0, 1, 10, 1, 1, 1, 1, 1
+Alert: PASS: this.print(false, 1, 10, true, true, true, true, true) = undefined
+Doc Print: 1, 0, 0, 0, 0, 0, 0, 0
+Alert: PASS: this.print({}) = undefined
+Doc Print: 1, 42, 17, 1, 1, 1, 1, 1
+Alert: PASS: this.print({"bUi": false, "nStart": 42, "nEnd": 17, "bSilent": true, "bShrinkToFit": true, "bPrintAsImage": true, "bReverse": true, "bAnnotations": true, "bogus": "yes"}) = undefined
 Alert: PASS: typeof this.removeField = function
 Alert: PASS: this.removeField() threw error Document.removeField: Incorrect number of parameters passed to function.
 Alert: PASS: typeof this.resetForm = function