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 <string> 7 8 #include "core/fxcrt/fx_string.h" 9 #include "public/fpdf_doc.h" 10 #include "public/fpdf_edit.h" 11 #include "public/fpdfview.h" 12 #include "testing/embedder_test.h" 13 #include "testing/fx_string_testhelpers.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/test_support.h" 16 17 class FPDFDocEmbeddertest : public EmbedderTest {}; 18 19 TEST_F(FPDFDocEmbeddertest, DestGetPageIndex) { 20 EXPECT_TRUE(OpenDocument("named_dests.pdf")); 21 22 // NULL FPDF_DEST case. 23 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), nullptr)); 24 25 // Page number directly in item from Dests NameTree. 26 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First"); 27 EXPECT_TRUE(dest); 28 EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest)); 29 30 // Page number via object reference in item from Dests NameTree. 31 dest = FPDF_GetNamedDestByName(document(), "Next"); 32 EXPECT_TRUE(dest); 33 EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest)); 34 35 // Page number directly in item from Dests dictionary. 36 dest = FPDF_GetNamedDestByName(document(), "FirstAlternate"); 37 EXPECT_TRUE(dest); 38 EXPECT_EQ(11U, FPDFDest_GetPageIndex(document(), dest)); 39 40 // Invalid object reference in item from Dests NameTree. 41 dest = FPDF_GetNamedDestByName(document(), "LastAlternate"); 42 EXPECT_TRUE(dest); 43 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest)); 44 } 45 46 TEST_F(FPDFDocEmbeddertest, DestGetLocationInPage) { 47 EXPECT_TRUE(OpenDocument("named_dests.pdf")); 48 49 // NULL FPDF_DEST case. 50 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), nullptr)); 51 52 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First"); 53 EXPECT_TRUE(dest); 54 55 FPDF_BOOL hasX; 56 FPDF_BOOL hasY; 57 FPDF_BOOL hasZoom; 58 FS_FLOAT x; 59 FS_FLOAT y; 60 FS_FLOAT zoom; 61 EXPECT_TRUE( 62 FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom)); 63 EXPECT_TRUE(hasX); 64 EXPECT_TRUE(hasY); 65 EXPECT_TRUE(hasZoom); 66 EXPECT_EQ(0, x); 67 EXPECT_EQ(0, y); 68 EXPECT_EQ(1, zoom); 69 } 70 71 TEST_F(FPDFDocEmbeddertest, BUG_680376) { 72 EXPECT_TRUE(OpenDocument("bug_680376.pdf")); 73 74 // Page number directly in item from Dests NameTree. 75 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First"); 76 EXPECT_TRUE(dest); 77 EXPECT_EQ(static_cast<unsigned long>(-1), 78 FPDFDest_GetPageIndex(document(), dest)); 79 } 80 81 TEST_F(FPDFDocEmbeddertest, ActionGetFilePath) { 82 EXPECT_TRUE(OpenDocument("launch_action.pdf")); 83 84 FPDF_PAGE page = FPDF_LoadPage(document(), 0); 85 ASSERT_TRUE(page); 86 87 // The target action is nearly the size of the whole page. 88 FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100); 89 ASSERT_TRUE(link); 90 91 FPDF_ACTION action = FPDFLink_GetAction(link); 92 ASSERT_TRUE(action); 93 94 const char kExpectedResult[] = "test.pdf"; 95 const unsigned long kExpectedLength = sizeof(kExpectedResult); 96 unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0); 97 ASSERT_EQ(kExpectedLength, bufsize); 98 99 char buf[kExpectedLength]; 100 EXPECT_EQ(bufsize, FPDFAction_GetFilePath(action, buf, bufsize)); 101 EXPECT_EQ(std::string(kExpectedResult), std::string(buf)); 102 103 FPDF_ClosePage(page); 104 } 105 106 TEST_F(FPDFDocEmbeddertest, NoBookmarks) { 107 // Open a file with no bookmarks. 108 EXPECT_TRUE(OpenDocument("named_dests.pdf")); 109 110 // The non-existent top-level bookmark has no title. 111 unsigned short buf[128]; 112 EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf))); 113 114 // The non-existent top-level bookmark has no children. 115 EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), nullptr)); 116 } 117 118 TEST_F(FPDFDocEmbeddertest, Bookmarks) { 119 // Open a file with two bookmarks. 120 EXPECT_TRUE(OpenDocument("bookmarks.pdf")); 121 122 // The existent top-level bookmark has no title. 123 unsigned short buf[128]; 124 EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf))); 125 126 FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr); 127 EXPECT_TRUE(child); 128 EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf))); 129 EXPECT_EQ(CFX_WideString(L"A Good Beginning"), 130 CFX_WideString::FromUTF16LE(buf, 16)); 131 132 EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), child)); 133 134 FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child); 135 EXPECT_TRUE(sibling); 136 EXPECT_EQ(28u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf))); 137 EXPECT_EQ(CFX_WideString(L"A Good Ending"), 138 CFX_WideString::FromUTF16LE(buf, 13)); 139 140 EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling)); 141 } 142 143 TEST_F(FPDFDocEmbeddertest, FindBookmarks) { 144 // Open a file with two bookmarks. 145 EXPECT_TRUE(OpenDocument("bookmarks.pdf")); 146 147 // Find the first one, based on its known title. 148 std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = 149 GetFPDFWideString(L"A Good Beginning"); 150 FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get()); 151 EXPECT_TRUE(child); 152 153 // Check that the string matches. 154 unsigned short buf[128]; 155 EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf))); 156 EXPECT_EQ(CFX_WideString(L"A Good Beginning"), 157 CFX_WideString::FromUTF16LE(buf, 16)); 158 159 // Check that it is them same as the one returned by GetFirstChild. 160 EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr)); 161 162 // Try to find one using a non-existent title. 163 std::unique_ptr<unsigned short, pdfium::FreeDeleter> bad_title = 164 GetFPDFWideString(L"A BAD Beginning"); 165 EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get())); 166 } 167 168 // Check circular bookmarks will not cause infinite loop. 169 TEST_F(FPDFDocEmbeddertest, FindBookmarks_bug420) { 170 // Open a file with circular bookmarks. 171 EXPECT_TRUE(OpenDocument("bookmarks_circular.pdf")); 172 173 // Try to find a title. 174 std::unique_ptr<unsigned short, pdfium::FreeDeleter> title = 175 GetFPDFWideString(L"anything"); 176 EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), title.get())); 177 } 178 179 TEST_F(FPDFDocEmbeddertest, DeletePage) { 180 EXPECT_TRUE(OpenDocument("hello_world.pdf")); 181 EXPECT_EQ(1, FPDF_GetPageCount(document())); 182 FPDFPage_Delete(document(), 0); 183 EXPECT_EQ(0, FPDF_GetPageCount(document())); 184 } 185 186 TEST_F(FPDFDocEmbeddertest, NoPageLabels) { 187 EXPECT_TRUE(OpenDocument("about_blank.pdf")); 188 EXPECT_EQ(1, FPDF_GetPageCount(document())); 189 190 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 0, nullptr, 0)); 191 } 192 193 TEST_F(FPDFDocEmbeddertest, GetPageLabels) { 194 EXPECT_TRUE(OpenDocument("page_labels.pdf")); 195 EXPECT_EQ(7, FPDF_GetPageCount(document())); 196 197 unsigned short buf[128]; 198 EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf))); 199 EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf))); 200 201 const FX_WCHAR kExpectedPageLabel0[] = L"i"; 202 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf))); 203 EXPECT_EQ(CFX_WideString(kExpectedPageLabel0), 204 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0))); 205 206 const FX_WCHAR kExpectedPageLabel1[] = L"ii"; 207 ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf))); 208 EXPECT_EQ(CFX_WideString(kExpectedPageLabel1), 209 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1))); 210 211 const FX_WCHAR kExpectedPageLabel2[] = L"1"; 212 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf))); 213 EXPECT_EQ(CFX_WideString(kExpectedPageLabel2), 214 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2))); 215 216 const FX_WCHAR kExpectedPageLabel3[] = L"2"; 217 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf))); 218 EXPECT_EQ(CFX_WideString(kExpectedPageLabel3), 219 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3))); 220 221 const FX_WCHAR kExpectedPageLabel4[] = L"zzA"; 222 ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf))); 223 EXPECT_EQ(CFX_WideString(kExpectedPageLabel4), 224 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4))); 225 226 const FX_WCHAR kExpectedPageLabel5[] = L"zzB"; 227 ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf))); 228 EXPECT_EQ(CFX_WideString(kExpectedPageLabel5), 229 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5))); 230 231 const FX_WCHAR kExpectedPageLabel6[] = L""; 232 ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf))); 233 EXPECT_EQ(CFX_WideString(kExpectedPageLabel6), 234 CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6))); 235 236 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf))); 237 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf))); 238 } 239