| // Copyright 2019 The PDFium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "core/fxcrt/compiler_specific.h" | 
 | #include "core/fxcrt/fx_memcpy_wrappers.h" | 
 | #include "core/fxcrt/fx_memory.h" | 
 | #include "public/fpdf_javascript.h" | 
 | #include "public/fpdfview.h" | 
 | #include "testing/embedder_test.h" | 
 | #include "testing/fx_string_testhelpers.h" | 
 | #include "testing/utils/hash.h" | 
 |  | 
 | class FPDFJavaScriptEmbedderTest : public EmbedderTest {}; | 
 |  | 
 | TEST_F(FPDFJavaScriptEmbedderTest, CountJS) { | 
 |   // Open a file with JS. | 
 |   ASSERT_TRUE(OpenDocument("bug_679649.pdf")); | 
 |   EXPECT_EQ(1, FPDFDoc_GetJavaScriptActionCount(document())); | 
 | } | 
 |  | 
 | TEST_F(FPDFJavaScriptEmbedderTest, CountNoJS) { | 
 |   // Open a file without JS. | 
 |   ASSERT_TRUE(OpenDocument("hello_world.pdf")); | 
 |   EXPECT_EQ(0, FPDFDoc_GetJavaScriptActionCount(document())); | 
 |  | 
 |   // Provide no document. | 
 |   EXPECT_EQ(-1, FPDFDoc_GetJavaScriptActionCount(nullptr)); | 
 | } | 
 |  | 
 | TEST_F(FPDFJavaScriptEmbedderTest, GetJS) { | 
 |   ASSERT_TRUE(OpenDocument("js.pdf")); | 
 |   EXPECT_EQ(5, FPDFDoc_GetJavaScriptActionCount(document())); | 
 |  | 
 |   ScopedFPDFJavaScriptAction js; | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), -1)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 5)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(nullptr, -1)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 0)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 1)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 2)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 5)); | 
 |   EXPECT_FALSE(js); | 
 |  | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 0)); | 
 |   EXPECT_TRUE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 1)); | 
 |   EXPECT_TRUE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 2)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 3)); | 
 |   EXPECT_FALSE(js); | 
 |   js.reset(FPDFDoc_GetJavaScriptAction(document(), 4)); | 
 |   EXPECT_FALSE(js); | 
 | } | 
 |  | 
 | TEST_F(FPDFJavaScriptEmbedderTest, GetJSName) { | 
 |   ASSERT_TRUE(OpenDocument("bug_679649.pdf")); | 
 |   ScopedFPDFJavaScriptAction js(FPDFDoc_GetJavaScriptAction(document(), 0)); | 
 |   ASSERT_TRUE(js); | 
 |  | 
 |   { | 
 |     FPDF_WCHAR buf[10]; | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, nullptr, 0)); | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, buf, 0)); | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, buf, sizeof(buf))); | 
 |   } | 
 |  | 
 |   constexpr size_t kExpectedLength = 22; | 
 |   ASSERT_EQ(kExpectedLength, | 
 |             FPDFJavaScriptAction_GetName(js.get(), nullptr, 0)); | 
 |  | 
 |   // Check that the name not returned if the buffer is too small. | 
 |   // The result buffer should be overwritten with an empty string. | 
 |   std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kExpectedLength); | 
 |   // Write in the buffer to verify it's not overwritten. | 
 |   UNSAFE_TODO(FXSYS_memcpy(buf.data(), "abcdefgh", 8)); | 
 |   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(), | 
 |                                                           kExpectedLength - 1)); | 
 |   EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8)); | 
 |  | 
 |   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(), | 
 |                                                           kExpectedLength)); | 
 |   EXPECT_EQ(L"startDelay", GetPlatformWString(buf.data())); | 
 | } | 
 |  | 
 | TEST_F(FPDFJavaScriptEmbedderTest, GetJSScript) { | 
 |   ASSERT_TRUE(OpenDocument("bug_679649.pdf")); | 
 |   ScopedFPDFJavaScriptAction js(FPDFDoc_GetJavaScriptAction(document(), 0)); | 
 |   ASSERT_TRUE(js); | 
 |  | 
 |   { | 
 |     FPDF_WCHAR buf[10]; | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, nullptr, 0)); | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, buf, 0)); | 
 |     EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, buf, sizeof(buf))); | 
 |   } | 
 |  | 
 |   constexpr size_t kExpectedLength = 218; | 
 |   ASSERT_EQ(kExpectedLength, | 
 |             FPDFJavaScriptAction_GetScript(js.get(), nullptr, 0)); | 
 |  | 
 |   // Check that the string value of an AP is not returned if the buffer is too | 
 |   // small. The result buffer should be overwritten with an empty string. | 
 |   std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kExpectedLength); | 
 |   // Write in the buffer to verify it's not overwritten. | 
 |   UNSAFE_TODO(FXSYS_memcpy(buf.data(), "abcdefgh", 8)); | 
 |   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetScript( | 
 |                                  js.get(), buf.data(), kExpectedLength - 1)); | 
 |   EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8)); | 
 |  | 
 |   static const wchar_t kExpectedScript[] = | 
 |       L"function ping() {\n  app.alert(\"ping\");\n}\n" | 
 |       L"var timer = app.setTimeOut(\"ping()\", 100);\napp.clearTimeOut(timer);"; | 
 |   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetScript( | 
 |                                  js.get(), buf.data(), kExpectedLength)); | 
 |   EXPECT_EQ(kExpectedScript, GetPlatformWString(buf.data())); | 
 | } |