• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The PDFium Authors
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 <array>
6 #include <set>
7 #include <string>
8 #include <vector>
9 
10 #include "core/fpdfapi/parser/cpdf_dictionary.h"
11 #include "core/fpdfapi/parser/cpdf_document.h"
12 #include "core/fpdfapi/parser/cpdf_reference.h"
13 #include "core/fxcrt/bytestring.h"
14 #include "core/fxcrt/fx_safe_types.h"
15 #include "core/fxge/cfx_defaultrenderdevice.h"
16 #include "fpdfsdk/cpdfsdk_helpers.h"
17 #include "public/cpp/fpdf_scopers.h"
18 #include "public/fpdf_doc.h"
19 #include "public/fpdf_edit.h"
20 #include "public/fpdfview.h"
21 #include "testing/embedder_test.h"
22 #include "testing/fx_string_testhelpers.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace {
26 
27 // Look for "/Type/Page" but ignore "/Type/Pages".
CountPageEntries(const std::string & data)28 int CountPageEntries(const std::string& data) {
29   static constexpr char kNeedle[] = "/Type/Page";
30   static constexpr size_t kNeedleLen = std::size(kNeedle) - 1;
31 
32   size_t pos = 0;
33   int count = 0;
34   while (pos < data.size()) {
35     const size_t found_pos = data.find(kNeedle, pos);
36     if (found_pos == std::string::npos) {
37       break;
38     }
39 
40     FX_SAFE_SIZE_T next_pos = found_pos;
41     next_pos += kNeedleLen;
42     pos = next_pos.ValueOrDefault(std::string::npos);
43     if (pos < data.size() && data[pos] == 's') {
44       // Ignore "/Type/Pages".
45       ++pos;
46     } else {
47       ++count;
48     }
49   }
50   return count;
51 }
52 
53 // Look for ">stream\r\n".
CountStreamEntries(const std::string & data)54 int CountStreamEntries(const std::string& data) {
55   static constexpr char kNeedle[] = ">stream\r\n";
56   static constexpr size_t kNeedleLen = std::size(kNeedle) - 1;
57 
58   size_t pos = 0;
59   int count = 0;
60   while (pos < data.size()) {
61     const size_t found_pos = data.find(kNeedle, pos);
62     if (found_pos == std::string::npos) {
63       break;
64     }
65 
66     FX_SAFE_SIZE_T next_pos = found_pos;
67     next_pos += kNeedleLen;
68     pos = next_pos.ValueOrDefault(std::string::npos);
69     ++count;
70   }
71   return count;
72 }
73 
74 }  // namespace
75 
76 class FPDFDocEmbedderTest : public EmbedderTest {};
77 
TEST_F(FPDFDocEmbedderTest,MultipleSamePage)78 TEST_F(FPDFDocEmbedderTest, MultipleSamePage) {
79   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
80   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document());
81 
82   std::set<FPDF_PAGE> unique_pages;
83   std::vector<ScopedFPDFPage> owned_pages(4);
84   for (auto& ref : owned_pages) {
85     ref.reset(FPDF_LoadPage(document(), 0));
86     unique_pages.insert(ref.get());
87   }
88 #ifdef PDF_ENABLE_XFA
89   EXPECT_EQ(1u, unique_pages.size());
90   EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
91 #else   // PDF_ENABLE_XFA
92   EXPECT_EQ(4u, unique_pages.size());
93   EXPECT_EQ(4u, pDoc->GetParsedPageCountForTesting());
94 #endif  // PDF_ENABLE_XFA
95 }
96 
TEST_F(FPDFDocEmbedderTest,DestGetPageIndex)97 TEST_F(FPDFDocEmbedderTest, DestGetPageIndex) {
98   ASSERT_TRUE(OpenDocument("named_dests.pdf"));
99 
100   // NULL argument cases.
101   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(nullptr, nullptr));
102   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), nullptr));
103 
104   // Page number directly in item from Dests NameTree.
105   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
106   EXPECT_TRUE(dest);
107   EXPECT_EQ(1, FPDFDest_GetDestPageIndex(document(), dest));
108 
109   // Page number via object reference in item from Dests NameTree.
110   dest = FPDF_GetNamedDestByName(document(), "Next");
111   EXPECT_TRUE(dest);
112   EXPECT_EQ(1, FPDFDest_GetDestPageIndex(document(), dest));
113 
114   // Page number directly in item from Dests dictionary.
115   dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
116   EXPECT_TRUE(dest);
117   EXPECT_EQ(11, FPDFDest_GetDestPageIndex(document(), dest));
118 
119   // Invalid object reference in item from Dests NameTree.
120   dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
121   EXPECT_TRUE(dest);
122   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), dest));
123 }
124 
TEST_F(FPDFDocEmbedderTest,DestGetView)125 TEST_F(FPDFDocEmbedderTest, DestGetView) {
126   ASSERT_TRUE(OpenDocument("named_dests.pdf"));
127 
128   unsigned long numParams;
129   FS_FLOAT params[4];
130 
131   numParams = 42;
132   std::fill_n(params, 4, 42.4242f);
133   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_UNKNOWN_MODE),
134             FPDFDest_GetView(nullptr, &numParams, params));
135   EXPECT_EQ(0U, numParams);
136   EXPECT_FLOAT_EQ(42.4242f, params[0]);
137 
138   numParams = 42;
139   std::fill_n(params, 4, 42.4242f);
140   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
141   EXPECT_TRUE(dest);
142   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
143             FPDFDest_GetView(dest, &numParams, params));
144   EXPECT_EQ(3U, numParams);
145   EXPECT_FLOAT_EQ(0, params[0]);
146   EXPECT_FLOAT_EQ(0, params[1]);
147   EXPECT_FLOAT_EQ(1, params[2]);
148   EXPECT_FLOAT_EQ(42.4242f, params[3]);
149 
150   numParams = 42;
151   std::fill_n(params, 4, 42.4242f);
152   dest = FPDF_GetNamedDestByName(document(), "Next");
153   EXPECT_TRUE(dest);
154   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
155             FPDFDest_GetView(dest, &numParams, params));
156   EXPECT_EQ(0U, numParams);
157   EXPECT_FLOAT_EQ(42.4242f, params[0]);
158 
159   numParams = 42;
160   std::fill_n(params, 4, 42.4242f);
161   dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
162   EXPECT_TRUE(dest);
163   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
164             FPDFDest_GetView(dest, &numParams, params));
165   EXPECT_EQ(3U, numParams);
166   EXPECT_FLOAT_EQ(200, params[0]);
167   EXPECT_FLOAT_EQ(400, params[1]);
168   EXPECT_FLOAT_EQ(800, params[2]);
169   EXPECT_FLOAT_EQ(42.4242f, params[3]);
170 
171   numParams = 42;
172   std::fill_n(params, 4, 42.4242f);
173   dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
174   EXPECT_TRUE(dest);
175   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
176             FPDFDest_GetView(dest, &numParams, params));
177   EXPECT_EQ(3U, numParams);
178   EXPECT_FLOAT_EQ(0, params[0]);
179   EXPECT_FLOAT_EQ(0, params[1]);
180   EXPECT_FLOAT_EQ(-200, params[2]);
181   EXPECT_FLOAT_EQ(42.4242f, params[3]);
182 }
183 
TEST_F(FPDFDocEmbedderTest,DestGetLocationInPage)184 TEST_F(FPDFDocEmbedderTest, DestGetLocationInPage) {
185   ASSERT_TRUE(OpenDocument("named_dests.pdf"));
186 
187   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
188   EXPECT_TRUE(dest);
189 
190   FPDF_BOOL hasX = 0;
191   FPDF_BOOL hasY = 0;
192   FPDF_BOOL hasZoom = 0;
193   FS_FLOAT x = -1.0f;
194   FS_FLOAT y = -1.0f;
195   FS_FLOAT zoom = -1.0f;
196 
197   // NULL argument case
198   EXPECT_FALSE(FPDFDest_GetLocationInPage(nullptr, &hasX, &hasY, &hasZoom, &x,
199                                           &y, &zoom));
200 
201   // Actual argument case.
202   EXPECT_TRUE(
203       FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom));
204   EXPECT_TRUE(hasX);
205   EXPECT_TRUE(hasY);
206   EXPECT_TRUE(hasZoom);
207   EXPECT_EQ(0, x);
208   EXPECT_EQ(0, y);
209   EXPECT_EQ(1, zoom);
210 }
211 
TEST_F(FPDFDocEmbedderTest,Bug1506First)212 TEST_F(FPDFDocEmbedderTest, Bug1506First) {
213   ASSERT_TRUE(OpenDocument("bug_1506.pdf"));
214 
215   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
216   ASSERT_TRUE(dest);
217   EXPECT_EQ(3, FPDFDest_GetDestPageIndex(document(), dest));
218 }
219 
TEST_F(FPDFDocEmbedderTest,Bug1506Second)220 TEST_F(FPDFDocEmbedderTest, Bug1506Second) {
221   ASSERT_TRUE(OpenDocument("bug_1506.pdf"));
222 
223   std::vector<ScopedEmbedderTestPage> pages;
224   for (int i : {0, 2}) {
225     pages.push_back(LoadScopedPage(i));
226   }
227 
228   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
229   ASSERT_TRUE(dest);
230   EXPECT_EQ(3, FPDFDest_GetDestPageIndex(document(), dest));
231 }
232 
TEST_F(FPDFDocEmbedderTest,Bug1506Third)233 TEST_F(FPDFDocEmbedderTest, Bug1506Third) {
234   ASSERT_TRUE(OpenDocument("bug_1506.pdf"));
235 
236   std::vector<ScopedEmbedderTestPage> pages;
237   for (int i : {0, 1, 3}) {
238     pages.push_back(LoadScopedPage(i));
239   }
240 
241   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
242   ASSERT_TRUE(dest);
243   EXPECT_EQ(3, FPDFDest_GetDestPageIndex(document(), dest));
244 }
245 
TEST_F(FPDFDocEmbedderTest,Bug680376)246 TEST_F(FPDFDocEmbedderTest, Bug680376) {
247   ASSERT_TRUE(OpenDocument("bug_680376.pdf"));
248 
249   // Page number directly in item from Dests NameTree.
250   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
251   EXPECT_TRUE(dest);
252   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), dest));
253 }
254 
TEST_F(FPDFDocEmbedderTest,Bug821454)255 TEST_F(FPDFDocEmbedderTest, Bug821454) {
256   ASSERT_TRUE(OpenDocument("bug_821454.pdf"));
257 
258   ScopedEmbedderTestPage page = LoadScopedPage(0);
259   ASSERT_TRUE(page);
260 
261   // Cover some invalid argument cases while we're at it.
262   EXPECT_FALSE(FPDFLink_GetLinkAtPoint(nullptr, 150, 360));
263   EXPECT_EQ(-1, FPDFLink_GetLinkZOrderAtPoint(nullptr, 150, 360));
264 
265   FPDF_LINK link1 = FPDFLink_GetLinkAtPoint(page.get(), 150, 360);
266   ASSERT_TRUE(link1);
267   FPDF_LINK link2 = FPDFLink_GetLinkAtPoint(page.get(), 150, 420);
268   ASSERT_TRUE(link2);
269 
270   EXPECT_EQ(0, FPDFLink_GetLinkZOrderAtPoint(page.get(), 150, 360));
271   EXPECT_EQ(1, FPDFLink_GetLinkZOrderAtPoint(page.get(), 150, 420));
272 
273   FPDF_DEST dest1 = FPDFLink_GetDest(document(), link1);
274   ASSERT_TRUE(dest1);
275   FPDF_DEST dest2 = FPDFLink_GetDest(document(), link2);
276   ASSERT_TRUE(dest2);
277 
278   // Cover more invalid argument cases while we're at it.
279   EXPECT_FALSE(FPDFLink_GetDest(nullptr, nullptr));
280   EXPECT_FALSE(FPDFLink_GetDest(nullptr, link1));
281   EXPECT_FALSE(FPDFLink_GetDest(document(), nullptr));
282 
283   EXPECT_EQ(0, FPDFDest_GetDestPageIndex(document(), dest1));
284   EXPECT_EQ(0, FPDFDest_GetDestPageIndex(document(), dest2));
285 
286   {
287     FPDF_BOOL has_x_coord;
288     FPDF_BOOL has_y_coord;
289     FPDF_BOOL has_zoom;
290     FS_FLOAT x;
291     FS_FLOAT y;
292     FS_FLOAT zoom;
293     FPDF_BOOL success = FPDFDest_GetLocationInPage(
294         dest1, &has_x_coord, &has_y_coord, &has_zoom, &x, &y, &zoom);
295     ASSERT_TRUE(success);
296     EXPECT_TRUE(has_x_coord);
297     EXPECT_TRUE(has_y_coord);
298     EXPECT_FALSE(has_zoom);
299     EXPECT_FLOAT_EQ(100.0f, x);
300     EXPECT_FLOAT_EQ(200.0f, y);
301   }
302   {
303     FPDF_BOOL has_x_coord;
304     FPDF_BOOL has_y_coord;
305     FPDF_BOOL has_zoom;
306     FS_FLOAT x;
307     FS_FLOAT y;
308     FS_FLOAT zoom;
309     FPDF_BOOL success = FPDFDest_GetLocationInPage(
310         dest2, &has_x_coord, &has_y_coord, &has_zoom, &x, &y, &zoom);
311     ASSERT_TRUE(success);
312     EXPECT_TRUE(has_x_coord);
313     EXPECT_TRUE(has_y_coord);
314     EXPECT_FALSE(has_zoom);
315     EXPECT_FLOAT_EQ(150.0f, x);
316     EXPECT_FLOAT_EQ(250.0f, y);
317   }
318 }
319 
TEST_F(FPDFDocEmbedderTest,ActionBadArguments)320 TEST_F(FPDFDocEmbedderTest, ActionBadArguments) {
321   ASSERT_TRUE(OpenDocument("launch_action.pdf"));
322   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_UNSUPPORTED),
323             FPDFAction_GetType(nullptr));
324 
325   EXPECT_FALSE(FPDFAction_GetDest(nullptr, nullptr));
326   EXPECT_FALSE(FPDFAction_GetDest(document(), nullptr));
327   EXPECT_EQ(0u, FPDFAction_GetFilePath(nullptr, nullptr, 0));
328   EXPECT_EQ(0u, FPDFAction_GetURIPath(nullptr, nullptr, nullptr, 0));
329   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), nullptr, nullptr, 0));
330 }
331 
TEST_F(FPDFDocEmbedderTest,ActionLaunch)332 TEST_F(FPDFDocEmbedderTest, ActionLaunch) {
333   ASSERT_TRUE(OpenDocument("launch_action.pdf"));
334 
335   ScopedEmbedderTestPage page = LoadScopedPage(0);
336   ASSERT_TRUE(page);
337 
338   // The target action is nearly the size of the whole page.
339   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
340   ASSERT_TRUE(link);
341 
342   FPDF_ACTION action = FPDFLink_GetAction(link);
343   ASSERT_TRUE(action);
344   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_LAUNCH),
345             FPDFAction_GetType(action));
346 
347   const char kExpectedResult[] = "test.pdf";
348   const unsigned long kExpectedLength = sizeof(kExpectedResult);
349   unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
350   EXPECT_EQ(kExpectedLength, bufsize);
351 
352   char buf[1024];
353   EXPECT_EQ(bufsize, FPDFAction_GetFilePath(action, buf, bufsize));
354   EXPECT_STREQ(kExpectedResult, buf);
355 
356   // Other public methods are not appropriate for launch actions.
357   EXPECT_FALSE(FPDFAction_GetDest(document(), action));
358   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
359 }
360 
TEST_F(FPDFDocEmbedderTest,ActionUri)361 TEST_F(FPDFDocEmbedderTest, ActionUri) {
362   ASSERT_TRUE(OpenDocument("uri_action.pdf"));
363 
364   ScopedEmbedderTestPage page = LoadScopedPage(0);
365   ASSERT_TRUE(page);
366 
367   // The target action is nearly the size of the whole page.
368   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
369   ASSERT_TRUE(link);
370 
371   FPDF_ACTION action = FPDFLink_GetAction(link);
372   ASSERT_TRUE(action);
373   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
374             FPDFAction_GetType(action));
375 
376   const char kExpectedResult[] = "https://example.com/page.html";
377   const unsigned long kExpectedLength = sizeof(kExpectedResult);
378   unsigned long bufsize = FPDFAction_GetURIPath(document(), action, nullptr, 0);
379   ASSERT_EQ(kExpectedLength, bufsize);
380 
381   char buf[1024];
382   EXPECT_EQ(bufsize, FPDFAction_GetURIPath(document(), action, buf, bufsize));
383   EXPECT_STREQ(kExpectedResult, buf);
384 
385   // Other public methods are not appropriate for URI actions
386   EXPECT_FALSE(FPDFAction_GetDest(document(), action));
387   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
388 }
389 
TEST_F(FPDFDocEmbedderTest,ActionUriNonAscii)390 TEST_F(FPDFDocEmbedderTest, ActionUriNonAscii) {
391   ASSERT_TRUE(OpenDocument("uri_action_nonascii.pdf"));
392 
393   ScopedEmbedderTestPage page = LoadScopedPage(0);
394   ASSERT_TRUE(page);
395 
396   // The target action is nearly the size of the whole page.
397   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
398   ASSERT_TRUE(link);
399 
400   FPDF_ACTION action = FPDFLink_GetAction(link);
401   ASSERT_TRUE(action);
402   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
403             FPDFAction_GetType(action));
404 
405   // FPDFAction_GetURIPath() may return data in any encoding, or even with bad
406   // encoding.
407   const char kExpectedResult[] =
408       "https://example.com/\xA5octal\xC7"
409       "chars";
410   const unsigned long kExpectedLength = sizeof(kExpectedResult);
411   unsigned long bufsize = FPDFAction_GetURIPath(document(), action, nullptr, 0);
412   ASSERT_EQ(kExpectedLength, bufsize);
413 
414   char buf[1024];
415   EXPECT_EQ(bufsize, FPDFAction_GetURIPath(document(), action, buf, bufsize));
416   EXPECT_STREQ(kExpectedResult, buf);
417 }
418 
TEST_F(FPDFDocEmbedderTest,LinkToAnnotConversion)419 TEST_F(FPDFDocEmbedderTest, LinkToAnnotConversion) {
420   ASSERT_TRUE(OpenDocument("annots.pdf"));
421   ScopedEmbedderTestPage page = LoadScopedPage(0);
422   ASSERT_TRUE(page);
423   {
424     FPDF_LINK first_link = FPDFLink_GetLinkAtPoint(page.get(), 69.00, 653.00);
425     ScopedFPDFAnnotation first_annot(FPDFLink_GetAnnot(page.get(), first_link));
426     EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page.get(), first_annot.get()));
427 
428     FPDF_LINK second_link = FPDFLink_GetLinkAtPoint(page.get(), 80.00, 633.00);
429     ScopedFPDFAnnotation second_annot(
430         FPDFLink_GetAnnot(page.get(), second_link));
431     EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page.get(), second_annot.get()));
432 
433     // Also test invalid arguments.
434     EXPECT_FALSE(FPDFLink_GetAnnot(nullptr, nullptr));
435     EXPECT_FALSE(FPDFLink_GetAnnot(page.get(), nullptr));
436     EXPECT_FALSE(FPDFLink_GetAnnot(nullptr, second_link));
437   }
438 }
439 
TEST_F(FPDFDocEmbedderTest,ActionGoto)440 TEST_F(FPDFDocEmbedderTest, ActionGoto) {
441   ASSERT_TRUE(OpenDocument("goto_action.pdf"));
442 
443   ScopedEmbedderTestPage page = LoadScopedPage(0);
444   ASSERT_TRUE(page);
445 
446   // The target action is nearly the size of the whole page.
447   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
448   ASSERT_TRUE(link);
449 
450   FPDF_ACTION action = FPDFLink_GetAction(link);
451   ASSERT_TRUE(action);
452   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_GOTO),
453             FPDFAction_GetType(action));
454 
455   EXPECT_TRUE(FPDFAction_GetDest(document(), action));
456 
457   // Other public methods are not appropriate for GoTo actions.
458   char buf[1024];
459   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
460   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
461 }
462 
TEST_F(FPDFDocEmbedderTest,ActionEmbeddedGoto)463 TEST_F(FPDFDocEmbedderTest, ActionEmbeddedGoto) {
464   ASSERT_TRUE(OpenDocument("gotoe_action.pdf"));
465 
466   ScopedEmbedderTestPage page = LoadScopedPage(0);
467   ASSERT_TRUE(page);
468 
469   // The target action is nearly the size of the whole page.
470   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
471   ASSERT_TRUE(link);
472 
473   FPDF_ACTION action = FPDFLink_GetAction(link);
474   ASSERT_TRUE(action);
475   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_EMBEDDEDGOTO),
476             FPDFAction_GetType(action));
477 
478   FPDF_DEST dest = FPDFAction_GetDest(document(), action);
479   EXPECT_TRUE(dest);
480 
481   unsigned long num_params = 42;
482   FS_FLOAT params[4];
483   std::fill_n(params, 4, 42.4242f);
484   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
485             FPDFDest_GetView(dest, &num_params, params));
486   EXPECT_EQ(0u, num_params);
487   EXPECT_FLOAT_EQ(42.4242f, params[0]);
488 
489   const char kExpectedResult[] = "ExampleFile.pdf";
490   const unsigned long kExpectedLength = sizeof(kExpectedResult);
491   char buf[1024];
492   unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
493   EXPECT_EQ(kExpectedLength, bufsize);
494   EXPECT_EQ(kExpectedLength, FPDFAction_GetFilePath(action, buf, bufsize));
495   EXPECT_STREQ(kExpectedResult, buf);
496 }
497 
TEST_F(FPDFDocEmbedderTest,ActionNonesuch)498 TEST_F(FPDFDocEmbedderTest, ActionNonesuch) {
499   ASSERT_TRUE(OpenDocument("nonesuch_action.pdf"));
500 
501   ScopedEmbedderTestPage page = LoadScopedPage(0);
502   ASSERT_TRUE(page);
503 
504   // The target action is nearly the size of the whole page.
505   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page.get(), 100, 100);
506   ASSERT_TRUE(link);
507 
508   FPDF_ACTION action = FPDFLink_GetAction(link);
509   ASSERT_TRUE(action);
510   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_UNSUPPORTED),
511             FPDFAction_GetType(action));
512 
513   // No public methods are appropriate for unsupported actions.
514   char buf[1024];
515   EXPECT_FALSE(FPDFAction_GetDest(document(), action));
516   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
517   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
518 }
519 
TEST_F(FPDFDocEmbedderTest,NoBookmarks)520 TEST_F(FPDFDocEmbedderTest, NoBookmarks) {
521   unsigned short buf[128];
522 
523   // Open a file with no bookmarks.
524   ASSERT_TRUE(OpenDocument("named_dests.pdf"));
525 
526   // NULL argument cases.
527   EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
528   EXPECT_FALSE(FPDFBookmark_GetFirstChild(nullptr, nullptr));
529   EXPECT_FALSE(FPDFBookmark_GetFirstChild(document(), nullptr));
530   EXPECT_FALSE(FPDFBookmark_GetNextSibling(nullptr, nullptr));
531   EXPECT_FALSE(FPDFBookmark_GetNextSibling(document(), nullptr));
532   EXPECT_FALSE(FPDFBookmark_Find(nullptr, nullptr));
533   EXPECT_FALSE(FPDFBookmark_Find(document(), nullptr));
534   EXPECT_FALSE(FPDFBookmark_GetDest(nullptr, nullptr));
535   EXPECT_FALSE(FPDFBookmark_GetDest(document(), nullptr));
536   EXPECT_FALSE(FPDFBookmark_GetAction(nullptr));
537 }
538 
TEST_F(FPDFDocEmbedderTest,Bookmarks)539 TEST_F(FPDFDocEmbedderTest, Bookmarks) {
540   unsigned short buf[128];
541 
542   // Open a file with many bookmarks.
543   ASSERT_TRUE(OpenDocument("bookmarks.pdf"));
544 
545   FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
546   EXPECT_TRUE(child);
547   EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
548   EXPECT_EQ(L"A Good Beginning", GetPlatformWString(buf));
549   EXPECT_EQ(0, FPDFBookmark_GetCount(child));
550   EXPECT_EQ(0, FPDFBookmark_GetCount(nullptr));
551 
552   EXPECT_FALSE(FPDFBookmark_GetDest(document(), child));
553   EXPECT_FALSE(FPDFBookmark_GetAction(child));
554 
555   FPDF_BOOKMARK grand_child = FPDFBookmark_GetFirstChild(document(), child);
556   EXPECT_FALSE(grand_child);
557 
558   FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child);
559   EXPECT_TRUE(sibling);
560   EXPECT_EQ(24u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf)));
561   EXPECT_EQ(L"Open Middle", GetPlatformWString(buf));
562   EXPECT_TRUE(FPDFBookmark_GetAction(sibling));
563   EXPECT_EQ(1, FPDFBookmark_GetCount(sibling));
564 
565   FPDF_BOOKMARK sibling2 = FPDFBookmark_GetNextSibling(document(), sibling);
566   EXPECT_TRUE(sibling2);
567   EXPECT_EQ(42u, FPDFBookmark_GetTitle(sibling2, buf, sizeof(buf)));
568   EXPECT_EQ(L"A Good Closed Ending", GetPlatformWString(buf));
569   EXPECT_EQ(-2, FPDFBookmark_GetCount(sibling2));
570 
571   EXPECT_FALSE(FPDFBookmark_GetNextSibling(document(), sibling2));
572 
573   grand_child = FPDFBookmark_GetFirstChild(document(), sibling);
574   EXPECT_TRUE(grand_child);
575   EXPECT_EQ(46u, FPDFBookmark_GetTitle(grand_child, buf, sizeof(buf)));
576   EXPECT_EQ(L"Open Middle Descendant", GetPlatformWString(buf));
577   EXPECT_EQ(0, FPDFBookmark_GetCount(grand_child));
578   EXPECT_TRUE(FPDFBookmark_GetDest(document(), grand_child));
579 
580   EXPECT_FALSE(FPDFBookmark_GetNextSibling(document(), grand_child));
581 }
582 
TEST_F(FPDFDocEmbedderTest,FindBookmarks)583 TEST_F(FPDFDocEmbedderTest, FindBookmarks) {
584   unsigned short buf[128];
585 
586   // Open a file with many bookmarks.
587   ASSERT_TRUE(OpenDocument("bookmarks.pdf"));
588 
589   // Find the first one, based on its known title.
590   ScopedFPDFWideString title = GetFPDFWideString(L"A Good Beginning");
591   FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get());
592   EXPECT_TRUE(child);
593 
594   // Check that the string matches.
595   EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
596   EXPECT_EQ(L"A Good Beginning", GetPlatformWString(buf));
597 
598   // Check that it is them same as the one returned by GetFirstChild.
599   EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));
600 
601   // Try to find one using a non-existent title.
602   ScopedFPDFWideString bad_title = GetFPDFWideString(L"A BAD Beginning");
603   EXPECT_FALSE(FPDFBookmark_Find(document(), bad_title.get()));
604 }
605 
606 // Check circular bookmarks will not cause infinite loop.
TEST_F(FPDFDocEmbedderTest,FindBookmarksBug420)607 TEST_F(FPDFDocEmbedderTest, FindBookmarksBug420) {
608   // Open a file with circular bookmarks.
609   ASSERT_TRUE(OpenDocument("bookmarks_circular.pdf"));
610 
611   // Try to find a title.
612   ScopedFPDFWideString title = GetFPDFWideString(L"anything");
613   EXPECT_FALSE(FPDFBookmark_Find(document(), title.get()));
614 }
615 
TEST_F(FPDFDocEmbedderTest,DeletePage)616 TEST_F(FPDFDocEmbedderTest, DeletePage) {
617   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
618   EXPECT_EQ(1, FPDF_GetPageCount(document()));
619 
620   FPDFPage_Delete(nullptr, 0);
621   EXPECT_EQ(1, FPDF_GetPageCount(document()));
622 
623   FPDFPage_Delete(document(), -1);
624   EXPECT_EQ(1, FPDF_GetPageCount(document()));
625   FPDFPage_Delete(document(), 1);
626   EXPECT_EQ(1, FPDF_GetPageCount(document()));
627 
628   FPDFPage_Delete(document(), 0);
629   EXPECT_EQ(0, FPDF_GetPageCount(document()));
630 }
631 
TEST_F(FPDFDocEmbedderTest,DeletePageAndRender)632 TEST_F(FPDFDocEmbedderTest, DeletePageAndRender) {
633   struct PageData {
634     int width;
635     int height;
636     const char* checksum;
637   };
638   const std::array<const PageData, 5> expected_page_data = {{
639       {200, 250,
640        []() {
641          return CFX_DefaultRenderDevice::UseSkiaRenderer()
642                     ? "4b6590a267eae90b8be1607e808fb57f"
643                     : "1e5d1cf19ffbb9cf9dbf099483cea327";
644        }()},
645       {250, 200,
646        []() {
647          return CFX_DefaultRenderDevice::UseSkiaRenderer()
648                     ? "e8edd3655f6629ff489bd8c3bb110c82"
649                     : "65c80685916aa36e767dd2270ba4d72b";
650        }()},
651       {200, 250,
652        []() {
653          return CFX_DefaultRenderDevice::UseSkiaRenderer()
654                     ? "a2bde6b68d7981e665ab25bc633746aa"
655                     : "a53b21c68edf43c1cddb5c06e361bb45";
656        }()},
657       {200, 250,
658        []() {
659          return CFX_DefaultRenderDevice::UseSkiaRenderer()
660                     ? "a8c5b3e626f665eddf593c6d4c32ae9e"
661                     : "dcd768be15efb9c6e5093cf74508752c";
662        }()},
663       {200, 250,
664        []() {
665          return CFX_DefaultRenderDevice::UseSkiaRenderer()
666                     ? "72eb157853ae2d19b70ea62e3f5ac202"
667                     : "7a3f8f79ebcb350854c0d69607729ec5";
668        }()},
669   }};
670 
671   // Render the original document. (page indices 0-4)
672   ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
673   EXPECT_EQ(5, FPDF_GetPageCount(document()));
674   for (int i = 0; i < 5; ++i) {
675     ScopedEmbedderTestPage page = LoadScopedPage(i);
676     ASSERT_TRUE(page);
677     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
678     const PageData& expected = expected_page_data[i];
679     CompareBitmap(bitmap.get(), expected.width, expected.height,
680                   expected.checksum);
681   }
682 
683   // Delete the first page and render again. (original page indices 1-4)
684   FPDFPage_Delete(document(), 0);
685   EXPECT_EQ(4, FPDF_GetPageCount(document()));
686   for (int i = 0; i < 4; ++i) {
687     ScopedEmbedderTestPage page = LoadScopedPage(i);
688     ASSERT_TRUE(page);
689     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
690     const PageData& expected = expected_page_data[i + 1];
691     CompareBitmap(bitmap.get(), expected.width, expected.height,
692                   expected.checksum);
693   }
694 
695   // Delete the last page and render again. (original page indices 1-3)
696   FPDFPage_Delete(document(), 3);
697   EXPECT_EQ(3, FPDF_GetPageCount(document()));
698   for (int i = 0; i < 3; ++i) {
699     ScopedEmbedderTestPage page = LoadScopedPage(i);
700     ASSERT_TRUE(page);
701     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
702     const PageData& expected = expected_page_data[i + 1];
703     CompareBitmap(bitmap.get(), expected.width, expected.height,
704                   expected.checksum);
705   }
706 
707   // Delete the middle page and render again. (original page indices 1, 3)
708   FPDFPage_Delete(document(), 1);
709   EXPECT_EQ(2, FPDF_GetPageCount(document()));
710   for (int i = 0; i < 2; ++i) {
711     ScopedEmbedderTestPage page = LoadScopedPage(i);
712     ASSERT_TRUE(page);
713     ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
714     int adjusted_index = i == 0 ? 1 : 3;
715     const PageData& expected = expected_page_data[adjusted_index];
716     CompareBitmap(bitmap.get(), expected.width, expected.height,
717                   expected.checksum);
718   }
719 }
720 
TEST_F(FPDFDocEmbedderTest,DeletePageAndSaveWithBookmarks)721 TEST_F(FPDFDocEmbedderTest, DeletePageAndSaveWithBookmarks) {
722   // The bookmarks reference the deleted page.
723   ASSERT_TRUE(OpenDocument("bookmarks.pdf"));
724 
725   EXPECT_EQ(2, FPDF_GetPageCount(document()));
726   FPDFPage_Delete(document(), 0);
727   EXPECT_EQ(1, FPDF_GetPageCount(document()));
728 
729   ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
730   EXPECT_EQ(1, CountPageEntries(GetString()));
731   EXPECT_EQ(1, CountStreamEntries(GetString()));
732 }
733 
TEST_F(FPDFDocEmbedderTest,DeletePageAndSaveWithCustomObject)734 TEST_F(FPDFDocEmbedderTest, DeletePageAndSaveWithCustomObject) {
735   // There exists a non-standard object that references the deleted page.
736   ASSERT_TRUE(OpenDocument("hello_world_2_pages_custom_object.pdf"));
737 
738   EXPECT_EQ(2, FPDF_GetPageCount(document()));
739   FPDFPage_Delete(document(), 0);
740   EXPECT_EQ(1, FPDF_GetPageCount(document()));
741 
742   ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
743   EXPECT_EQ(1, CountPageEntries(GetString()));
744   EXPECT_EQ(1, CountStreamEntries(GetString()));
745 }
746 
TEST_F(FPDFDocEmbedderTest,DeletePageAndSaveWithCustomObjectForNewPage)747 TEST_F(FPDFDocEmbedderTest, DeletePageAndSaveWithCustomObjectForNewPage) {
748   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
749 
750   EXPECT_EQ(1, FPDF_GetPageCount(document()));
751 
752   {
753     ScopedFPDFPage new_page(FPDFPage_New(document(), 1, 300, 200));
754     ASSERT_TRUE(new_page);
755     EXPECT_EQ(2, FPDF_GetPageCount(document()));
756 
757     // Add a non-standard object that references the newly created page.
758     CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document());
759     ASSERT_TRUE(doc);
760 
761     CPDF_Page* page = CPDFPageFromFPDFPage(new_page.get());
762     ASSERT_TRUE(page);
763 
764     RetainPtr<CPDF_Dictionary> root_dict = doc->GetMutableRoot();
765     ASSERT_TRUE(root_dict);
766     root_dict->SetNewFor<CPDF_Reference>("CustomField", doc,
767                                          page->GetDict()->GetObjNum());
768   }
769 
770   FPDFPage_Delete(document(), 1);
771   EXPECT_EQ(1, FPDF_GetPageCount(document()));
772 
773   ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
774   EXPECT_EQ(1, CountPageEntries(GetString()));
775   EXPECT_EQ(1, CountStreamEntries(GetString()));
776 }
777 
TEST_F(FPDFDocEmbedderTest,DeletePageAndSaveForPageWithMultipleUses)778 TEST_F(FPDFDocEmbedderTest, DeletePageAndSaveForPageWithMultipleUses) {
779   // The deleted pages both use the same /Page object.
780   ASSERT_TRUE(OpenDocument("bug_1229106.pdf"));
781 
782   EXPECT_EQ(4, FPDF_GetPageCount(document()));
783   FPDFPage_Delete(document(), 0);
784   EXPECT_EQ(3, FPDF_GetPageCount(document()));
785 
786   ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
787   EXPECT_EQ(2, CountPageEntries(GetString()));
788   EXPECT_EQ(2, CountStreamEntries(GetString()));
789 
790   ClearString();
791   FPDFPage_Delete(document(), 0);
792   EXPECT_EQ(2, FPDF_GetPageCount(document()));
793 
794   ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
795   EXPECT_EQ(1, CountPageEntries(GetString()));
796   EXPECT_EQ(1, CountStreamEntries(GetString()));
797 }
798 
TEST_F(FPDFDocEmbedderTest,GetFileIdentifier)799 TEST_F(FPDFDocEmbedderTest, GetFileIdentifier) {
800   ASSERT_TRUE(OpenDocument("split_streams.pdf"));
801   constexpr size_t kMd5Length = 17;
802   char buf[kMd5Length];
803   EXPECT_EQ(0u,
804             FPDF_GetFileIdentifier(document(), static_cast<FPDF_FILEIDTYPE>(-1),
805                                    buf, sizeof(buf)));
806   EXPECT_EQ(0u,
807             FPDF_GetFileIdentifier(document(), static_cast<FPDF_FILEIDTYPE>(2),
808                                    buf, sizeof(buf)));
809   EXPECT_EQ(0u, FPDF_GetFileIdentifier(nullptr, FILEIDTYPE_PERMANENT, buf,
810                                        sizeof(buf)));
811   EXPECT_EQ(kMd5Length, FPDF_GetFileIdentifier(document(), FILEIDTYPE_PERMANENT,
812                                                nullptr, 0));
813 
814   constexpr char kExpectedPermanent[] =
815       "\xF3\x41\xAE\x65\x4A\x77\xAC\xD5\x06\x5A\x76\x45\xE5\x96\xE6\xE6";
816   ASSERT_EQ(kMd5Length, FPDF_GetFileIdentifier(document(), FILEIDTYPE_PERMANENT,
817                                                buf, sizeof(buf)));
818   EXPECT_EQ(kExpectedPermanent, ByteString(buf));
819 
820   constexpr char kExpectedChanging[] =
821       "\xBC\x37\x29\x8A\x3F\x87\xF4\x79\x22\x9B\xCE\x99\x7C\xA7\x91\xF7";
822   ASSERT_EQ(kMd5Length, FPDF_GetFileIdentifier(document(), FILEIDTYPE_CHANGING,
823                                                buf, sizeof(buf)));
824   EXPECT_EQ(kExpectedChanging, ByteString(buf));
825 }
826 
TEST_F(FPDFDocEmbedderTest,GetNonHexFileIdentifier)827 TEST_F(FPDFDocEmbedderTest, GetNonHexFileIdentifier) {
828   ASSERT_TRUE(OpenDocument("non_hex_file_id.pdf"));
829   char buf[18];
830 
831   constexpr char kPermanentNonHex[] = "permanent non-hex";
832   ASSERT_EQ(18u, FPDF_GetFileIdentifier(document(), FILEIDTYPE_PERMANENT, buf,
833                                         sizeof(buf)));
834   EXPECT_EQ(kPermanentNonHex, ByteString(buf));
835 
836   constexpr char kChangingNonHex[] = "changing non-hex";
837   ASSERT_EQ(17u, FPDF_GetFileIdentifier(document(), FILEIDTYPE_CHANGING, buf,
838                                         sizeof(buf)));
839   EXPECT_EQ(kChangingNonHex, ByteString(buf));
840 }
841 
TEST_F(FPDFDocEmbedderTest,GetNonexistentFileIdentifier)842 TEST_F(FPDFDocEmbedderTest, GetNonexistentFileIdentifier) {
843   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
844   EXPECT_EQ(
845       0u, FPDF_GetFileIdentifier(document(), FILEIDTYPE_PERMANENT, nullptr, 0));
846   EXPECT_EQ(
847       0u, FPDF_GetFileIdentifier(document(), FILEIDTYPE_CHANGING, nullptr, 0));
848 }
849 
TEST_F(FPDFDocEmbedderTest,GetMetaText)850 TEST_F(FPDFDocEmbedderTest, GetMetaText) {
851   ASSERT_TRUE(OpenDocument("bug_601362.pdf"));
852 
853   // Invalid document / tag results in 0.
854   unsigned short buf[128];
855   EXPECT_EQ(0u, FPDF_GetMetaText(document(), nullptr, buf, sizeof(buf)));
856   EXPECT_EQ(0u, FPDF_GetMetaText(nullptr, "", buf, sizeof(buf)));
857 
858   // Tags that do not eixst results in an empty wide string.
859   EXPECT_EQ(2u, FPDF_GetMetaText(document(), "", buf, sizeof(buf)));
860   EXPECT_EQ(2u, FPDF_GetMetaText(document(), "foo", buf, sizeof(buf)));
861   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
862   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Author", buf, sizeof(buf)));
863   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Subject", buf, sizeof(buf)));
864   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Keywords", buf, sizeof(buf)));
865   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf)));
866 
867   ASSERT_EQ(30u, FPDF_GetMetaText(document(), "Creator", buf, sizeof(buf)));
868   EXPECT_EQ(L"Microsoft Word", GetPlatformWString(buf));
869 
870   ASSERT_EQ(48u,
871             FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf)));
872   EXPECT_EQ(L"D:20160411190039+00'00'", GetPlatformWString(buf));
873 
874   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
875   EXPECT_EQ(L"D:20160411190039+00'00'", GetPlatformWString(buf));
876 }
877 
TEST_F(FPDFDocEmbedderTest,Utf8Metadata)878 TEST_F(FPDFDocEmbedderTest, Utf8Metadata) {
879   ASSERT_TRUE(OpenDocument("utf-8.pdf"));
880 
881   unsigned short buf[128];
882 
883   ASSERT_EQ(34u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf)));
884   EXPECT_EQ(L"Manüally Created", GetPlatformWString(buf));
885 
886   FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
887   EXPECT_TRUE(child);
888   EXPECT_EQ(16u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
889   EXPECT_EQ(L"Titlè 1", GetPlatformWString(buf));
890 }
891 
TEST_F(FPDFDocEmbedderTest,Bug182)892 TEST_F(FPDFDocEmbedderTest, Bug182) {
893   ASSERT_TRUE(OpenDocument("bug_182.pdf"));
894 
895   unsigned short buf[128];
896 
897   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
898   EXPECT_EQ(L"Super Visual Formade 印刷", GetPlatformWString(buf));
899 }
900 
TEST_F(FPDFDocEmbedderTest,GetMetaTextSameObjectNumber)901 TEST_F(FPDFDocEmbedderTest, GetMetaTextSameObjectNumber) {
902   ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
903 
904   // The PDF has been edited. It has two %%EOF markers, and 2 objects numbered
905   // (1 0). Both objects are /Info dictionaries, but contain different data.
906   // Make sure ModDate is the date of the last modification.
907   unsigned short buf[128];
908   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
909   EXPECT_EQ(L"D:20170612232940-04'00'", GetPlatformWString(buf));
910 }
911 
TEST_F(FPDFDocEmbedderTest,GetMetaTextInAttachmentFile)912 TEST_F(FPDFDocEmbedderTest, GetMetaTextInAttachmentFile) {
913   ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
914 
915   // Make sure this is the date from the PDF itself and not the attached PDF.
916   unsigned short buf[128];
917   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
918   EXPECT_EQ(L"D:20170712214448-07'00'", GetPlatformWString(buf));
919 }
920 
TEST_F(FPDFDocEmbedderTest,GetMetaTextFromNewDocument)921 TEST_F(FPDFDocEmbedderTest, GetMetaTextFromNewDocument) {
922   ScopedFPDFDocument empty_doc(FPDF_CreateNewDocument());
923   unsigned short buf[128];
924   EXPECT_EQ(2u, FPDF_GetMetaText(empty_doc.get(), "Title", buf, sizeof(buf)));
925 }
926 
TEST_F(FPDFDocEmbedderTest,GetPageAAction)927 TEST_F(FPDFDocEmbedderTest, GetPageAAction) {
928   ASSERT_TRUE(OpenDocument("get_page_aaction.pdf"));
929   ScopedEmbedderTestPage page = LoadScopedPage(0);
930   EXPECT_TRUE(page);
931 
932   EXPECT_FALSE(FPDF_GetPageAAction(nullptr, FPDFPAGE_AACTION_OPEN));
933   EXPECT_FALSE(FPDF_GetPageAAction(page.get(), FPDFPAGE_AACTION_CLOSE));
934   EXPECT_FALSE(FPDF_GetPageAAction(page.get(), -1));
935   EXPECT_FALSE(FPDF_GetPageAAction(page.get(), 999));
936 
937   FPDF_ACTION action = FPDF_GetPageAAction(page.get(), FPDFPAGE_AACTION_OPEN);
938   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_EMBEDDEDGOTO),
939             FPDFAction_GetType(action));
940 
941   const char kExpectedResult[] = "\\\\127.0.0.1\\c$\\Program Files\\test.exe";
942   const unsigned long kExpectedLength = sizeof(kExpectedResult);
943   char buf[1024];
944 
945   unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
946   EXPECT_EQ(kExpectedLength, bufsize);
947   EXPECT_EQ(kExpectedLength, FPDFAction_GetFilePath(action, buf, bufsize));
948   EXPECT_STREQ(kExpectedResult, buf);
949 
950   ScopedEmbedderTestPage page1 = LoadScopedPage(1);
951 
952   EXPECT_TRUE(page1.get());
953   EXPECT_FALSE(FPDF_GetPageAAction(page1.get(), -1));
954 }
955 
TEST_F(FPDFDocEmbedderTest,NoPageLabels)956 TEST_F(FPDFDocEmbedderTest, NoPageLabels) {
957   ASSERT_TRUE(OpenDocument("about_blank.pdf"));
958   EXPECT_EQ(1, FPDF_GetPageCount(document()));
959 
960   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 0, nullptr, 0));
961 }
962 
TEST_F(FPDFDocEmbedderTest,GetPageLabels)963 TEST_F(FPDFDocEmbedderTest, GetPageLabels) {
964   ASSERT_TRUE(OpenDocument("page_labels.pdf"));
965   EXPECT_EQ(7, FPDF_GetPageCount(document()));
966 
967   // We do not request labels, when use FPDFAvail_IsXXXAvail.
968   // Flush all data, to allow read labels.
969   SetWholeFileAvailable();
970 
971   unsigned short buf[128];
972   EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf)));
973   EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf)));
974 
975   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf)));
976   EXPECT_EQ(L"i", GetPlatformWString(buf));
977 
978   ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf)));
979   EXPECT_EQ(L"ii", GetPlatformWString(buf));
980 
981   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf)));
982   EXPECT_EQ(L"1", GetPlatformWString(buf));
983 
984   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf)));
985   EXPECT_EQ(L"2", GetPlatformWString(buf));
986 
987   ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf)));
988   EXPECT_EQ(L"zzA", GetPlatformWString(buf));
989 
990   ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf)));
991   EXPECT_EQ(L"zzB", GetPlatformWString(buf));
992 
993   ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf)));
994   EXPECT_EQ(L"", GetPlatformWString(buf));
995 
996   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf)));
997   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf)));
998 }
999 
1000 #ifdef PDF_ENABLE_XFA
TEST_F(FPDFDocEmbedderTest,GetXFALinks)1001 TEST_F(FPDFDocEmbedderTest, GetXFALinks) {
1002   ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1003 
1004   ScopedFPDFPage page(FPDF_LoadPage(document(), 0));
1005   ASSERT_TRUE(page);
1006 
1007   FPDFLink_GetLinkAtPoint(page.get(), 150, 360);
1008   FPDFLink_GetLinkAtPoint(page.get(), 150, 420);
1009 
1010   // Test passes if it doesn't crash. See https://crbug.com/840922
1011 }
1012 #endif  // PDF_ENABLE_XFA
1013