Add an experimental API to surface a page's additional action.
Add an API to surface a page's additional action (/AA) to the embedder.
FORM_GetPageAAction() returns either a page open action or a page close action, depending on the input type.
Change-Id: I435d04ddd6bd0755d651a3cbb6e1abd93b81d356
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/72590
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_doc.cpp b/fpdfsdk/fpdf_doc.cpp
index b6a5ed4..94a1d04 100644
--- a/fpdfsdk/fpdf_doc.cpp
+++ b/fpdfsdk/fpdf_doc.cpp
@@ -10,6 +10,7 @@
#include <set>
#include <utility>
+#include "constants/form_fields.h"
#include "core/fpdfapi/page/cpdf_annotcontext.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_array.h"
@@ -18,12 +19,14 @@
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfdoc/cpdf_aaction.h"
#include "core/fpdfdoc/cpdf_bookmark.h"
#include "core/fpdfdoc/cpdf_bookmarktree.h"
#include "core/fpdfdoc/cpdf_dest.h"
#include "core/fpdfdoc/cpdf_linklist.h"
#include "core/fpdfdoc/cpdf_pagelabel.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
+#include "public/fpdf_formfill.h"
#include "third_party/base/stl_util.h"
namespace {
@@ -412,6 +415,30 @@
quad_points);
}
+FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDF_GetPageAAction(FPDF_PAGE page,
+ int aa_type) {
+ CPDF_Page* pdf_page = CPDFPageFromFPDFPage(page);
+ if (!pdf_page)
+ return nullptr;
+
+ CPDF_Dictionary* page_dict = pdf_page->GetDict();
+ CPDF_AAction aa(page_dict->GetDictFor(pdfium::form_fields::kAA));
+
+ CPDF_AAction::AActionType type;
+ if (aa_type == FPDFPAGE_AACTION_OPEN)
+ type = CPDF_AAction::kOpenPage;
+ else if (aa_type == FPDFPAGE_AACTION_CLOSE)
+ type = CPDF_AAction::kClosePage;
+ else
+ return nullptr;
+
+ if (!aa.ActionExist(type))
+ return nullptr;
+
+ CPDF_Action action = aa.GetAction(type);
+ return FPDFActionFromCPDFDictionary(action.GetDict());
+}
+
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDF_GetFileIdentifier(FPDF_DOCUMENT document,
FPDF_FILEIDTYPE id_type,
diff --git a/fpdfsdk/fpdf_doc_embeddertest.cpp b/fpdfsdk/fpdf_doc_embeddertest.cpp
index 24f57a9..87033f1 100644
--- a/fpdfsdk/fpdf_doc_embeddertest.cpp
+++ b/fpdfsdk/fpdf_doc_embeddertest.cpp
@@ -672,6 +672,38 @@
FPDF_CloseDocument(empty_doc);
}
+TEST_F(FPDFDocEmbedderTest, GetPageAAction) {
+ ASSERT_TRUE(OpenDocument("get_page_aaction.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ EXPECT_EQ(nullptr, FPDF_GetPageAAction(nullptr, FPDFPAGE_AACTION_OPEN));
+ EXPECT_EQ(nullptr, FPDF_GetPageAAction(page, FPDFPAGE_AACTION_CLOSE));
+ EXPECT_EQ(nullptr, FPDF_GetPageAAction(page, -1));
+ EXPECT_EQ(nullptr, FPDF_GetPageAAction(page, 999));
+
+ FPDF_ACTION action = FPDF_GetPageAAction(page, FPDFPAGE_AACTION_OPEN);
+ EXPECT_EQ(static_cast<unsigned long>(PDFACTION_EMBEDDEDGOTO),
+ FPDFAction_GetType(action));
+
+ const char kExpectedResult[] = "\\\\127.0.0.1\\c$\\Program Files\\test.exe";
+ const unsigned long kExpectedLength = sizeof(kExpectedResult);
+ char buf[1024];
+
+ unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
+ EXPECT_EQ(kExpectedLength, bufsize);
+ EXPECT_EQ(kExpectedLength, FPDFAction_GetFilePath(action, buf, bufsize));
+ EXPECT_STREQ(kExpectedResult, buf);
+
+ UnloadPage(page);
+
+ page = LoadPage(1);
+ EXPECT_TRUE(page);
+ EXPECT_EQ(nullptr, FPDF_GetPageAAction(page, -1));
+
+ UnloadPage(page);
+}
+
TEST_F(FPDFDocEmbedderTest, NoPageLabels) {
ASSERT_TRUE(OpenDocument("about_blank.pdf"));
EXPECT_EQ(1, FPDF_GetPageCount(document()));
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 75d2367..e36ece4 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -144,6 +144,7 @@
CHK(FPDFLink_GetQuadPoints);
CHK(FPDF_GetFileIdentifier);
CHK(FPDF_GetMetaText);
+ CHK(FPDF_GetPageAAction);
CHK(FPDF_GetPageLabel);
// fpdf_edit.h