1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2015 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
5ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "core/include/fxcrt/fx_string.h"
6ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "public/fpdf_doc.h"
7ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "public/fpdfview.h"
8ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "testing/embedder_test.h"
9ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "testing/fx_string_testhelpers.h"
10ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "testing/test_support.h"
11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "testing/gtest/include/gtest/gtest.h"
12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
13ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannclass FPDFDocEmbeddertest : public EmbedderTest {};
14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovTEST_F(FPDFDocEmbeddertest, DestGetPageIndex) {
16ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_TRUE(OpenDocument("named_dests.pdf"));
17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  // NULL FPDF_DEST case.
19ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), nullptr));
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  // Page number directly in item from Dests NameTree.
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  EXPECT_NE(nullptr, dest);
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest));
25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  // Page number via object reference in item from Dests NameTree.
27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  dest = FPDF_GetNamedDestByName(document(), "Next");
28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  EXPECT_NE(nullptr, dest);
29ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest));
30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  // Page number directly in item from Dests dictionary.
32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  EXPECT_NE(nullptr, dest);
34ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(11U, FPDFDest_GetPageIndex(document(), dest));
35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  // Invalid object reference in item from Dests NameTree.
37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  EXPECT_NE(nullptr, dest);
39ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest));
40ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
41ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
42ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannTEST_F(FPDFDocEmbeddertest, ActionGetFilePath) {
43ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_TRUE(OpenDocument("launch_action.pdf"));
44ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
45ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_PAGE page = FPDF_LoadPage(document(), 0);
46ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT_TRUE(page);
47ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
48ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // The target action is nearly the size of the whole page.
49ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
50ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT_TRUE(link);
51ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
52ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_ACTION action = FPDFLink_GetAction(link);
53ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT_TRUE(action);
54ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
55ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const char kExpectedResult[] = "test.pdf";
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const unsigned long kExpectedLength = sizeof(kExpectedResult);
57ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
58ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT_EQ(kExpectedLength, bufsize);
59ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
60ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  char buf[kExpectedLength];
61ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(bufsize, FPDFAction_GetFilePath(action, buf, bufsize));
62ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(std::string(kExpectedResult), std::string(buf));
63ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
64ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_ClosePage(page);
65ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
66ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
67ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannTEST_F(FPDFDocEmbeddertest, NoBookmarks) {
68ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Open a file with no bookmarks.
69ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_TRUE(OpenDocument("named_dests.pdf"));
70ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
71ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // The non-existent top-level bookmark has no title.
72ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned short buf[128];
73ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(0, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
74ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
75ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // The non-existent top-level bookmark has no children.
76ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), nullptr));
77ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
78ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
79ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannTEST_F(FPDFDocEmbeddertest, Bookmarks) {
80ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Open a file with two bookmarks.
81ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
83ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // The existent top-level bookmark has no title.
84ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned short buf[128];
85ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(0, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
86ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
87ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
88ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_NE(nullptr, child);
89ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(34, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
90ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(CFX_WideString(L"A Good Beginning"),
91ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            CFX_WideString::FromUTF16LE(buf, 16));
92ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
93ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), child));
94ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
95ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child);
96ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_NE(nullptr, sibling);
97ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(28, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf)));
98ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(CFX_WideString(L"A Good Ending"),
99ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            CFX_WideString::FromUTF16LE(buf, 13));
100ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
101ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling));
102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
103ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
104ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannTEST_F(FPDFDocEmbeddertest, FindBookmarks) {
105ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Open a file with two bookmarks.
106ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
107ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Find the first one, based on its known title.
109ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
110ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      GetFPDFWideString(L"A Good Beginning");
111ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get());
112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_NE(nullptr, child);
113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
114ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Check that the string matches.
115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned short buf[128];
116ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(34, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
117ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(CFX_WideString(L"A Good Beginning"),
118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            CFX_WideString::FromUTF16LE(buf, 16));
119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Check that it is them same as the one returned by GetFirstChild.
121ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));
122ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // Try to find one using a non-existent title.
124ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  std::unique_ptr<unsigned short, pdfium::FreeDeleter> bad_title =
125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      GetFPDFWideString(L"A BAD Beginning");
126ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get()));
127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
128