1 // Copyright 2015 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 <set>
7 #include <string>
8 #include <vector>
9 
10 #include "core/fpdfapi/parser/cpdf_document.h"
11 #include "core/fxcrt/fx_string.h"
12 #include "fpdfsdk/cpdfsdk_helpers.h"
13 #include "public/cpp/fpdf_scopers.h"
14 #include "public/fpdf_doc.h"
15 #include "public/fpdf_edit.h"
16 #include "public/fpdfview.h"
17 #include "testing/embedder_test.h"
18 #include "testing/fx_string_testhelpers.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 class FPDFDocEmbedderTest : public EmbedderTest {};
22 
TEST_F(FPDFDocEmbedderTest,MultipleSamePage)23 TEST_F(FPDFDocEmbedderTest, MultipleSamePage) {
24   EXPECT_TRUE(OpenDocument("hello_world.pdf"));
25   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document());
26 
27   std::set<FPDF_PAGE> unique_pages;
28   std::vector<ScopedFPDFPage> owned_pages(4);
29   for (auto& ref : owned_pages) {
30     ref.reset(FPDF_LoadPage(document(), 0));
31     unique_pages.insert(ref.get());
32   }
33 #ifdef PDF_ENABLE_XFA
34   EXPECT_EQ(1u, unique_pages.size());
35   EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
36 #else   // PDF_ENABLE_XFA
37   EXPECT_EQ(4u, unique_pages.size());
38   EXPECT_EQ(4u, pDoc->GetParsedPageCountForTesting());
39 #endif  // PDF_ENABLE_XFA
40 }
41 
TEST_F(FPDFDocEmbedderTest,DestGetPageIndex)42 TEST_F(FPDFDocEmbedderTest, DestGetPageIndex) {
43   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
44 
45   // NULL argument cases.
46   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(nullptr, nullptr));
47   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), nullptr));
48 
49   // Page number directly in item from Dests NameTree.
50   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
51   EXPECT_TRUE(dest);
52   EXPECT_EQ(1, FPDFDest_GetDestPageIndex(document(), dest));
53 
54   // Page number via object reference in item from Dests NameTree.
55   dest = FPDF_GetNamedDestByName(document(), "Next");
56   EXPECT_TRUE(dest);
57   EXPECT_EQ(1, FPDFDest_GetDestPageIndex(document(), dest));
58 
59   // Page number directly in item from Dests dictionary.
60   dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
61   EXPECT_TRUE(dest);
62   EXPECT_EQ(11, FPDFDest_GetDestPageIndex(document(), dest));
63 
64   // Invalid object reference in item from Dests NameTree.
65   dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
66   EXPECT_TRUE(dest);
67   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), dest));
68 }
69 
TEST_F(FPDFDocEmbedderTest,DestGetView)70 TEST_F(FPDFDocEmbedderTest, DestGetView) {
71   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
72 
73   unsigned long numParams;
74   FS_FLOAT params[4];
75 
76   numParams = 42;
77   std::fill_n(params, 4, 42.4242f);
78   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_UNKNOWN_MODE),
79             FPDFDest_GetView(nullptr, &numParams, params));
80   EXPECT_EQ(0U, numParams);
81   EXPECT_FLOAT_EQ(42.4242f, params[0]);
82 
83   numParams = 42;
84   std::fill_n(params, 4, 42.4242f);
85   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
86   EXPECT_TRUE(dest);
87   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
88             FPDFDest_GetView(dest, &numParams, params));
89   EXPECT_EQ(3U, numParams);
90   EXPECT_FLOAT_EQ(0, params[0]);
91   EXPECT_FLOAT_EQ(0, params[1]);
92   EXPECT_FLOAT_EQ(1, params[2]);
93   EXPECT_FLOAT_EQ(42.4242f, params[3]);
94 
95   numParams = 42;
96   std::fill_n(params, 4, 42.4242f);
97   dest = FPDF_GetNamedDestByName(document(), "Next");
98   EXPECT_TRUE(dest);
99   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
100             FPDFDest_GetView(dest, &numParams, params));
101   EXPECT_EQ(0U, numParams);
102   EXPECT_FLOAT_EQ(42.4242f, params[0]);
103 
104   numParams = 42;
105   std::fill_n(params, 4, 42.4242f);
106   dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
107   EXPECT_TRUE(dest);
108   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
109             FPDFDest_GetView(dest, &numParams, params));
110   EXPECT_EQ(3U, numParams);
111   EXPECT_FLOAT_EQ(200, params[0]);
112   EXPECT_FLOAT_EQ(400, params[1]);
113   EXPECT_FLOAT_EQ(800, params[2]);
114   EXPECT_FLOAT_EQ(42.4242f, params[3]);
115 
116   numParams = 42;
117   std::fill_n(params, 4, 42.4242f);
118   dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
119   EXPECT_TRUE(dest);
120   EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
121             FPDFDest_GetView(dest, &numParams, params));
122   EXPECT_EQ(3U, numParams);
123   EXPECT_FLOAT_EQ(0, params[0]);
124   EXPECT_FLOAT_EQ(0, params[1]);
125   EXPECT_FLOAT_EQ(-200, params[2]);
126   EXPECT_FLOAT_EQ(42.4242f, params[3]);
127 }
128 
TEST_F(FPDFDocEmbedderTest,DestGetLocationInPage)129 TEST_F(FPDFDocEmbedderTest, DestGetLocationInPage) {
130   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
131 
132   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
133   EXPECT_TRUE(dest);
134 
135   FPDF_BOOL hasX = 0;
136   FPDF_BOOL hasY = 0;
137   FPDF_BOOL hasZoom = 0;
138   FS_FLOAT x = -1.0f;
139   FS_FLOAT y = -1.0f;
140   FS_FLOAT zoom = -1.0f;
141 
142   // NULL argument case
143   EXPECT_FALSE(FPDFDest_GetLocationInPage(nullptr, &hasX, &hasY, &hasZoom, &x,
144                                           &y, &zoom));
145 
146   // Actual argument case.
147   EXPECT_TRUE(
148       FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom));
149   EXPECT_TRUE(hasX);
150   EXPECT_TRUE(hasY);
151   EXPECT_TRUE(hasZoom);
152   EXPECT_EQ(0, x);
153   EXPECT_EQ(0, y);
154   EXPECT_EQ(1, zoom);
155 }
156 
TEST_F(FPDFDocEmbedderTest,BUG_680376)157 TEST_F(FPDFDocEmbedderTest, BUG_680376) {
158   EXPECT_TRUE(OpenDocument("bug_680376.pdf"));
159 
160   // Page number directly in item from Dests NameTree.
161   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
162   EXPECT_TRUE(dest);
163   EXPECT_EQ(-1, FPDFDest_GetDestPageIndex(document(), dest));
164 }
165 
TEST_F(FPDFDocEmbedderTest,BUG_821454)166 TEST_F(FPDFDocEmbedderTest, BUG_821454) {
167   EXPECT_TRUE(OpenDocument("bug_821454.pdf"));
168 
169   FPDF_PAGE page = LoadPage(0);
170   ASSERT_TRUE(page);
171 
172   // Cover some NULL arg cases while we're at it.
173   EXPECT_FALSE(FPDFLink_GetLinkAtPoint(nullptr, 150, 360));
174   EXPECT_EQ(-1, FPDFLink_GetLinkZOrderAtPoint(nullptr, 150, 360));
175 
176   FPDF_LINK link1 = FPDFLink_GetLinkAtPoint(page, 150, 360);
177   ASSERT_TRUE(link1);
178   FPDF_LINK link2 = FPDFLink_GetLinkAtPoint(page, 150, 420);
179   ASSERT_TRUE(link2);
180 
181   EXPECT_EQ(0, FPDFLink_GetLinkZOrderAtPoint(page, 150, 360));
182   EXPECT_EQ(1, FPDFLink_GetLinkZOrderAtPoint(page, 150, 420));
183 
184   FPDF_DEST dest1 = FPDFLink_GetDest(document(), link1);
185   ASSERT_TRUE(dest1);
186   FPDF_DEST dest2 = FPDFLink_GetDest(document(), link2);
187   ASSERT_TRUE(dest2);
188 
189   EXPECT_EQ(0, FPDFDest_GetDestPageIndex(document(), dest1));
190   EXPECT_EQ(0, FPDFDest_GetDestPageIndex(document(), dest2));
191 
192   {
193     FPDF_BOOL has_x_coord;
194     FPDF_BOOL has_y_coord;
195     FPDF_BOOL has_zoom;
196     FS_FLOAT x;
197     FS_FLOAT y;
198     FS_FLOAT zoom;
199     FPDF_BOOL success = FPDFDest_GetLocationInPage(
200         dest1, &has_x_coord, &has_y_coord, &has_zoom, &x, &y, &zoom);
201     ASSERT_TRUE(success);
202     EXPECT_TRUE(has_x_coord);
203     EXPECT_TRUE(has_y_coord);
204     EXPECT_FALSE(has_zoom);
205     EXPECT_FLOAT_EQ(100.0f, x);
206     EXPECT_FLOAT_EQ(200.0f, y);
207   }
208   {
209     FPDF_BOOL has_x_coord;
210     FPDF_BOOL has_y_coord;
211     FPDF_BOOL has_zoom;
212     FS_FLOAT x;
213     FS_FLOAT y;
214     FS_FLOAT zoom;
215     FPDF_BOOL success = FPDFDest_GetLocationInPage(
216         dest2, &has_x_coord, &has_y_coord, &has_zoom, &x, &y, &zoom);
217     ASSERT_TRUE(success);
218     EXPECT_TRUE(has_x_coord);
219     EXPECT_TRUE(has_y_coord);
220     EXPECT_FALSE(has_zoom);
221     EXPECT_FLOAT_EQ(150.0f, x);
222     EXPECT_FLOAT_EQ(250.0f, y);
223   }
224 
225   UnloadPage(page);
226 }
227 
TEST_F(FPDFDocEmbedderTest,ActionBadArguments)228 TEST_F(FPDFDocEmbedderTest, ActionBadArguments) {
229   EXPECT_TRUE(OpenDocument("launch_action.pdf"));
230   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_UNSUPPORTED),
231             FPDFAction_GetType(nullptr));
232 
233   EXPECT_EQ(nullptr, FPDFAction_GetDest(nullptr, nullptr));
234   EXPECT_EQ(nullptr, FPDFAction_GetDest(document(), nullptr));
235   EXPECT_EQ(0u, FPDFAction_GetFilePath(nullptr, nullptr, 0));
236   EXPECT_EQ(0u, FPDFAction_GetURIPath(nullptr, nullptr, nullptr, 0));
237   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), nullptr, nullptr, 0));
238 }
239 
TEST_F(FPDFDocEmbedderTest,ActionLaunch)240 TEST_F(FPDFDocEmbedderTest, ActionLaunch) {
241   EXPECT_TRUE(OpenDocument("launch_action.pdf"));
242 
243   FPDF_PAGE page = LoadPage(0);
244   ASSERT_TRUE(page);
245 
246   // The target action is nearly the size of the whole page.
247   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
248   ASSERT_TRUE(link);
249 
250   FPDF_ACTION action = FPDFLink_GetAction(link);
251   ASSERT_TRUE(action);
252   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_LAUNCH),
253             FPDFAction_GetType(action));
254 
255   const char kExpectedResult[] = "test.pdf";
256   const unsigned long kExpectedLength = sizeof(kExpectedResult);
257   unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
258   EXPECT_EQ(kExpectedLength, bufsize);
259 
260   char buf[1024];
261   EXPECT_EQ(bufsize, FPDFAction_GetFilePath(action, buf, bufsize));
262   EXPECT_STREQ(kExpectedResult, buf);
263 
264   // Other public methods are not appropriate for launch actions.
265   EXPECT_EQ(nullptr, FPDFAction_GetDest(document(), action));
266   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
267 
268   UnloadPage(page);
269 }
270 
TEST_F(FPDFDocEmbedderTest,ActionURI)271 TEST_F(FPDFDocEmbedderTest, ActionURI) {
272   EXPECT_TRUE(OpenDocument("uri_action.pdf"));
273 
274   FPDF_PAGE page = LoadPage(0);
275   ASSERT_TRUE(page);
276 
277   // The target action is nearly the size of the whole page.
278   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
279   ASSERT_TRUE(link);
280 
281   FPDF_ACTION action = FPDFLink_GetAction(link);
282   ASSERT_TRUE(action);
283   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_URI),
284             FPDFAction_GetType(action));
285 
286   const char kExpectedResult[] = "https://example.com/page.html";
287   const unsigned long kExpectedLength = sizeof(kExpectedResult);
288   unsigned long bufsize = FPDFAction_GetURIPath(document(), action, nullptr, 0);
289   ASSERT_EQ(kExpectedLength, bufsize);
290 
291   char buf[1024];
292   EXPECT_EQ(bufsize, FPDFAction_GetURIPath(document(), action, buf, bufsize));
293   EXPECT_STREQ(kExpectedResult, buf);
294 
295   // Other public methods are not appropriate for URI actions
296   EXPECT_EQ(nullptr, FPDFAction_GetDest(document(), action));
297   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
298 
299   UnloadPage(page);
300 }
301 
TEST_F(FPDFDocEmbedderTest,ActionGoto)302 TEST_F(FPDFDocEmbedderTest, ActionGoto) {
303   EXPECT_TRUE(OpenDocument("goto_action.pdf"));
304 
305   FPDF_PAGE page = LoadPage(0);
306   ASSERT_TRUE(page);
307 
308   // The target action is nearly the size of the whole page.
309   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
310   ASSERT_TRUE(link);
311 
312   FPDF_ACTION action = FPDFLink_GetAction(link);
313   ASSERT_TRUE(action);
314   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_GOTO),
315             FPDFAction_GetType(action));
316 
317   EXPECT_TRUE(FPDFAction_GetDest(document(), action));
318 
319   // Other public methods are not appropriate for GoTo actions.
320   char buf[1024];
321   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
322   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
323 
324   UnloadPage(page);
325 }
326 
TEST_F(FPDFDocEmbedderTest,ActionNonesuch)327 TEST_F(FPDFDocEmbedderTest, ActionNonesuch) {
328   EXPECT_TRUE(OpenDocument("nonesuch_action.pdf"));
329 
330   FPDF_PAGE page = LoadPage(0);
331   ASSERT_TRUE(page);
332 
333   // The target action is nearly the size of the whole page.
334   FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
335   ASSERT_TRUE(link);
336 
337   FPDF_ACTION action = FPDFLink_GetAction(link);
338   ASSERT_TRUE(action);
339   EXPECT_EQ(static_cast<unsigned long>(PDFACTION_UNSUPPORTED),
340             FPDFAction_GetType(action));
341 
342   // No public methods are appropriate for unsupported actions.
343   char buf[1024];
344   EXPECT_FALSE(FPDFAction_GetDest(document(), action));
345   EXPECT_EQ(0u, FPDFAction_GetFilePath(action, buf, sizeof(buf)));
346   EXPECT_EQ(0u, FPDFAction_GetURIPath(document(), action, buf, sizeof(buf)));
347 
348   UnloadPage(page);
349 }
350 
TEST_F(FPDFDocEmbedderTest,NoBookmarks)351 TEST_F(FPDFDocEmbedderTest, NoBookmarks) {
352   unsigned short buf[128];
353 
354   // Open a file with no bookmarks.
355   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
356 
357   // NULL argument cases.
358   EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
359   EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(nullptr, nullptr));
360   EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), nullptr));
361   EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(nullptr, nullptr));
362   EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), nullptr));
363   EXPECT_EQ(nullptr, FPDFBookmark_Find(nullptr, nullptr));
364   EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), nullptr));
365   EXPECT_EQ(nullptr, FPDFBookmark_GetDest(nullptr, nullptr));
366   EXPECT_EQ(nullptr, FPDFBookmark_GetDest(document(), nullptr));
367   EXPECT_EQ(nullptr, FPDFBookmark_GetAction(nullptr));
368 }
369 
TEST_F(FPDFDocEmbedderTest,Bookmarks)370 TEST_F(FPDFDocEmbedderTest, Bookmarks) {
371   unsigned short buf[128];
372 
373   // Open a file with two bookmarks.
374   EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
375 
376   FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
377   EXPECT_TRUE(child);
378   EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
379   EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
380 
381   FPDF_DEST dest = FPDFBookmark_GetDest(document(), child);
382   EXPECT_FALSE(dest);  // TODO(tsepez): put real dest into bookmarks.pdf
383 
384   FPDF_ACTION action = FPDFBookmark_GetAction(child);
385   EXPECT_FALSE(action);  // TODO(tsepez): put real action into bookmarks.pdf
386 
387   FPDF_BOOKMARK grand_child = FPDFBookmark_GetFirstChild(document(), child);
388   EXPECT_FALSE(grand_child);
389 
390   FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child);
391   EXPECT_TRUE(sibling);
392   EXPECT_EQ(28u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf)));
393   EXPECT_EQ(WideString(L"A Good Ending"), WideString::FromUTF16LE(buf, 13));
394 
395   EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling));
396 }
397 
TEST_F(FPDFDocEmbedderTest,FindBookmarks)398 TEST_F(FPDFDocEmbedderTest, FindBookmarks) {
399   unsigned short buf[128];
400 
401   // Open a file with two bookmarks.
402   EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
403 
404   // Find the first one, based on its known title.
405   ScopedFPDFWideString title = GetFPDFWideString(L"A Good Beginning");
406   FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get());
407   EXPECT_TRUE(child);
408 
409   // Check that the string matches.
410   EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
411   EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
412 
413   // Check that it is them same as the one returned by GetFirstChild.
414   EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));
415 
416   // Try to find one using a non-existent title.
417   ScopedFPDFWideString bad_title = GetFPDFWideString(L"A BAD Beginning");
418   EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get()));
419 }
420 
421 // Check circular bookmarks will not cause infinite loop.
TEST_F(FPDFDocEmbedderTest,FindBookmarks_bug420)422 TEST_F(FPDFDocEmbedderTest, FindBookmarks_bug420) {
423   // Open a file with circular bookmarks.
424   EXPECT_TRUE(OpenDocument("bookmarks_circular.pdf"));
425 
426   // Try to find a title.
427   ScopedFPDFWideString title = GetFPDFWideString(L"anything");
428   EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), title.get()));
429 }
430 
TEST_F(FPDFDocEmbedderTest,DeletePage)431 TEST_F(FPDFDocEmbedderTest, DeletePage) {
432   EXPECT_TRUE(OpenDocument("hello_world.pdf"));
433   EXPECT_EQ(1, FPDF_GetPageCount(document()));
434 
435   FPDFPage_Delete(nullptr, 0);
436   EXPECT_EQ(1, FPDF_GetPageCount(document()));
437 
438   FPDFPage_Delete(document(), -1);
439   EXPECT_EQ(1, FPDF_GetPageCount(document()));
440   FPDFPage_Delete(document(), 1);
441   EXPECT_EQ(1, FPDF_GetPageCount(document()));
442 
443   FPDFPage_Delete(document(), 0);
444   EXPECT_EQ(0, FPDF_GetPageCount(document()));
445 }
446 
TEST_F(FPDFDocEmbedderTest,GetMetaText)447 TEST_F(FPDFDocEmbedderTest, GetMetaText) {
448   ASSERT_TRUE(OpenDocument("bug_601362.pdf"));
449 
450   // Invalid document / tag results in 0.
451   unsigned short buf[128];
452   EXPECT_EQ(0u, FPDF_GetMetaText(document(), nullptr, buf, sizeof(buf)));
453   EXPECT_EQ(0u, FPDF_GetMetaText(nullptr, "", buf, sizeof(buf)));
454 
455   // Tags that do not eixst results in an empty wide string.
456   EXPECT_EQ(2u, FPDF_GetMetaText(document(), "", buf, sizeof(buf)));
457   EXPECT_EQ(2u, FPDF_GetMetaText(document(), "foo", buf, sizeof(buf)));
458   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
459   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Author", buf, sizeof(buf)));
460   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Subject", buf, sizeof(buf)));
461   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Keywords", buf, sizeof(buf)));
462   ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf)));
463 
464   constexpr wchar_t kExpectedCreator[] = L"Microsoft Word";
465   ASSERT_EQ(30u, FPDF_GetMetaText(document(), "Creator", buf, sizeof(buf)));
466   EXPECT_EQ(WideString(kExpectedCreator),
467             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreator)));
468 
469   constexpr wchar_t kExpectedCreationDate[] = L"D:20160411190039+00'00'";
470   ASSERT_EQ(48u,
471             FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf)));
472   EXPECT_EQ(WideString(kExpectedCreationDate),
473             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreationDate)));
474 
475   constexpr wchar_t kExpectedModDate[] = L"D:20160411190039+00'00'";
476   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
477   EXPECT_EQ(WideString(kExpectedModDate),
478             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
479 }
480 
TEST_F(FPDFDocEmbedderTest,Bug_182)481 TEST_F(FPDFDocEmbedderTest, Bug_182) {
482   ASSERT_TRUE(OpenDocument("bug_182.pdf"));
483 
484   unsigned short buf[128];
485   constexpr wchar_t kExpectedTitle[] = L"Super Visual Formade 印刷";
486 
487   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
488   EXPECT_EQ(WideString(kExpectedTitle),
489             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedTitle)));
490 }
491 
TEST_F(FPDFDocEmbedderTest,GetMetaTextSameObjectNumber)492 TEST_F(FPDFDocEmbedderTest, GetMetaTextSameObjectNumber) {
493   ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
494 
495   // The PDF has been edited. It has two %%EOF markers, and 2 objects numbered
496   // (1 0). Both objects are /Info dictionaries, but contain different data.
497   // Make sure ModDate is the date of the last modification.
498   unsigned short buf[128];
499   constexpr wchar_t kExpectedModDate[] = L"D:20170612232940-04'00'";
500   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
501   EXPECT_EQ(WideString(kExpectedModDate),
502             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
503 }
504 
TEST_F(FPDFDocEmbedderTest,GetMetaTextInAttachmentFile)505 TEST_F(FPDFDocEmbedderTest, GetMetaTextInAttachmentFile) {
506   ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
507 
508   // Make sure this is the date from the PDF itself and not the attached PDF.
509   unsigned short buf[128];
510   constexpr wchar_t kExpectedModDate[] = L"D:20170712214448-07'00'";
511   ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
512   EXPECT_EQ(WideString(kExpectedModDate),
513             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
514 }
515 
TEST_F(FPDFDocEmbedderTest,GetMetaTextFromNewDocument)516 TEST_F(FPDFDocEmbedderTest, GetMetaTextFromNewDocument) {
517   FPDF_DOCUMENT empty_doc = FPDF_CreateNewDocument();
518   unsigned short buf[128];
519   EXPECT_EQ(2u, FPDF_GetMetaText(empty_doc, "Title", buf, sizeof(buf)));
520   FPDF_CloseDocument(empty_doc);
521 }
522 
TEST_F(FPDFDocEmbedderTest,NoPageLabels)523 TEST_F(FPDFDocEmbedderTest, NoPageLabels) {
524   EXPECT_TRUE(OpenDocument("about_blank.pdf"));
525   EXPECT_EQ(1, FPDF_GetPageCount(document()));
526 
527   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 0, nullptr, 0));
528 }
529 
TEST_F(FPDFDocEmbedderTest,GetPageLabels)530 TEST_F(FPDFDocEmbedderTest, GetPageLabels) {
531   EXPECT_TRUE(OpenDocument("page_labels.pdf"));
532   EXPECT_EQ(7, FPDF_GetPageCount(document()));
533 
534   // We do not request labels, when use FPDFAvail_IsXXXAvail.
535   // Flush all data, to allow read labels.
536   SetWholeFileAvailable();
537 
538   unsigned short buf[128];
539   EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf)));
540   EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf)));
541 
542   const wchar_t kExpectedPageLabel0[] = L"i";
543   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf)));
544   EXPECT_EQ(WideString(kExpectedPageLabel0),
545             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0)));
546 
547   const wchar_t kExpectedPageLabel1[] = L"ii";
548   ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf)));
549   EXPECT_EQ(WideString(kExpectedPageLabel1),
550             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1)));
551 
552   const wchar_t kExpectedPageLabel2[] = L"1";
553   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf)));
554   EXPECT_EQ(WideString(kExpectedPageLabel2),
555             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2)));
556 
557   const wchar_t kExpectedPageLabel3[] = L"2";
558   ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf)));
559   EXPECT_EQ(WideString(kExpectedPageLabel3),
560             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3)));
561 
562   const wchar_t kExpectedPageLabel4[] = L"zzA";
563   ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf)));
564   EXPECT_EQ(WideString(kExpectedPageLabel4),
565             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4)));
566 
567   const wchar_t kExpectedPageLabel5[] = L"zzB";
568   ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf)));
569   EXPECT_EQ(WideString(kExpectedPageLabel5),
570             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5)));
571 
572   const wchar_t kExpectedPageLabel6[] = L"";
573   ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf)));
574   EXPECT_EQ(WideString(kExpectedPageLabel6),
575             WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6)));
576 
577   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf)));
578   ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf)));
579 }
580 
581 #ifdef PDF_ENABLE_XFA
TEST_F(FPDFDocEmbedderTest,GetXFALinks)582 TEST_F(FPDFDocEmbedderTest, GetXFALinks) {
583   EXPECT_TRUE(OpenDocument("simple_xfa.pdf"));
584 
585   ScopedFPDFPage page(FPDF_LoadPage(document(), 0));
586   ASSERT_TRUE(page);
587 
588   FPDFLink_GetLinkAtPoint(page.get(), 150, 360);
589   FPDFLink_GetLinkAtPoint(page.get(), 150, 420);
590 
591   // Test passes if it doesn't crash. See https://crbug.com/840922
592 }
593 #endif  // PDF_ENABLE_XFA
594