1 // Copyright 2019 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 #include <memory>
6 #include <string>
7 #include <vector>
8
9 #include "core/fxcrt/fx_memory.h"
10 #include "public/fpdf_javascript.h"
11 #include "public/fpdfview.h"
12 #include "testing/embedder_test.h"
13 #include "testing/fx_string_testhelpers.h"
14 #include "testing/utils/hash.h"
15
16 class FPDFJavaScriptEmbedderTest : public EmbedderTest {};
17
TEST_F(FPDFJavaScriptEmbedderTest,CountJS)18 TEST_F(FPDFJavaScriptEmbedderTest, CountJS) {
19 // Open a file with JS.
20 ASSERT_TRUE(OpenDocument("bug_679649.pdf"));
21 EXPECT_EQ(1, FPDFDoc_GetJavaScriptActionCount(document()));
22 }
23
TEST_F(FPDFJavaScriptEmbedderTest,CountNoJS)24 TEST_F(FPDFJavaScriptEmbedderTest, CountNoJS) {
25 // Open a file without JS.
26 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
27 EXPECT_EQ(0, FPDFDoc_GetJavaScriptActionCount(document()));
28
29 // Provide no document.
30 EXPECT_EQ(-1, FPDFDoc_GetJavaScriptActionCount(nullptr));
31 }
32
TEST_F(FPDFJavaScriptEmbedderTest,GetJS)33 TEST_F(FPDFJavaScriptEmbedderTest, GetJS) {
34 ASSERT_TRUE(OpenDocument("js.pdf"));
35 EXPECT_EQ(6, FPDFDoc_GetJavaScriptActionCount(document()));
36
37 ScopedFPDFJavaScriptAction js;
38 js.reset(FPDFDoc_GetJavaScriptAction(document(), -1));
39 EXPECT_FALSE(js);
40 js.reset(FPDFDoc_GetJavaScriptAction(document(), 6));
41 EXPECT_FALSE(js);
42 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, -1));
43 EXPECT_FALSE(js);
44 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 0));
45 EXPECT_FALSE(js);
46 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 1));
47 EXPECT_FALSE(js);
48 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 2));
49 EXPECT_FALSE(js);
50 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 5));
51 EXPECT_FALSE(js);
52 js.reset(FPDFDoc_GetJavaScriptAction(nullptr, 6));
53 EXPECT_FALSE(js);
54
55 js.reset(FPDFDoc_GetJavaScriptAction(document(), 0));
56 EXPECT_TRUE(js);
57 js.reset(FPDFDoc_GetJavaScriptAction(document(), 1));
58 EXPECT_TRUE(js);
59 js.reset(FPDFDoc_GetJavaScriptAction(document(), 2));
60 EXPECT_TRUE(js);
61 js.reset(FPDFDoc_GetJavaScriptAction(document(), 3));
62 EXPECT_FALSE(js);
63 js.reset(FPDFDoc_GetJavaScriptAction(document(), 4));
64 EXPECT_FALSE(js);
65 js.reset(FPDFDoc_GetJavaScriptAction(document(), 5));
66 EXPECT_FALSE(js);
67 }
68
TEST_F(FPDFJavaScriptEmbedderTest,GetJSName)69 TEST_F(FPDFJavaScriptEmbedderTest, GetJSName) {
70 ASSERT_TRUE(OpenDocument("bug_679649.pdf"));
71 ScopedFPDFJavaScriptAction js(FPDFDoc_GetJavaScriptAction(document(), 0));
72 ASSERT_TRUE(js);
73
74 {
75 FPDF_WCHAR buf[10];
76 EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, nullptr, 0));
77 EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, buf, 0));
78 EXPECT_EQ(0u, FPDFJavaScriptAction_GetName(nullptr, buf, sizeof(buf)));
79 }
80
81 constexpr size_t kExpectedLength = 22;
82 ASSERT_EQ(kExpectedLength,
83 FPDFJavaScriptAction_GetName(js.get(), nullptr, 0));
84
85 // Check that the name not returned if the buffer is too small.
86 // The result buffer should be overwritten with an empty string.
87 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kExpectedLength);
88 // Write in the buffer to verify it's not overwritten.
89 memcpy(buf.data(), "abcdefgh", 8);
90 EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(),
91 kExpectedLength - 1));
92 EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
93
94 EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(),
95 kExpectedLength));
96 EXPECT_EQ(L"startDelay", GetPlatformWString(buf.data()));
97 }
98
TEST_F(FPDFJavaScriptEmbedderTest,GetJSScript)99 TEST_F(FPDFJavaScriptEmbedderTest, GetJSScript) {
100 ASSERT_TRUE(OpenDocument("bug_679649.pdf"));
101 ScopedFPDFJavaScriptAction js(FPDFDoc_GetJavaScriptAction(document(), 0));
102 ASSERT_TRUE(js);
103
104 {
105 FPDF_WCHAR buf[10];
106 EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, nullptr, 0));
107 EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, buf, 0));
108 EXPECT_EQ(0u, FPDFJavaScriptAction_GetScript(nullptr, buf, sizeof(buf)));
109 }
110
111 constexpr size_t kExpectedLength = 218;
112 ASSERT_EQ(kExpectedLength,
113 FPDFJavaScriptAction_GetScript(js.get(), nullptr, 0));
114
115 // Check that the string value of an AP is not returned if the buffer is too
116 // small. The result buffer should be overwritten with an empty string.
117 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(kExpectedLength);
118 // Write in the buffer to verify it's not overwritten.
119 memcpy(buf.data(), "abcdefgh", 8);
120 EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetScript(
121 js.get(), buf.data(), kExpectedLength - 1));
122 EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
123
124 static const wchar_t kExpectedScript[] =
125 L"function ping() {\n app.alert(\"ping\");\n}\n"
126 L"var timer = app.setTimeOut(\"ping()\", 100);\napp.clearTimeOut(timer);";
127 EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetScript(
128 js.get(), buf.data(), kExpectedLength));
129 EXPECT_EQ(kExpectedScript, GetPlatformWString(buf.data()));
130 }
131