Add support for action /GoToE

Add support for action /GoToE, to allow embedders to
get the file path and destination associated to this action.

Change-Id: I49eeef889da6babcd212a56f6cc0b291d76b942c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/72530
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfdoc/cpdf_action.cpp b/core/fpdfdoc/cpdf_action.cpp
index 9166b7c..deb9af8 100644
--- a/core/fpdfdoc/cpdf_action.cpp
+++ b/core/fpdfdoc/cpdf_action.cpp
@@ -54,14 +54,15 @@
 
 CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const {
   ActionType type = GetType();
-  if (type != GoTo && type != GoToR)
+  if (type != GoTo && type != GoToR && type != GoToE) {
     return CPDF_Dest(nullptr);
+  }
   return CPDF_Dest::Create(pDoc, m_pDict->GetDirectObjectFor("D"));
 }
 
 WideString CPDF_Action::GetFilePath() const {
   ActionType type = GetType();
-  if (type != GoToR && type != Launch && type != SubmitForm &&
+  if (type != GoToR && type != GoToE && type != Launch && type != SubmitForm &&
       type != ImportData) {
     return WideString();
   }
diff --git a/fpdfsdk/fpdf_doc.cpp b/fpdfsdk/fpdf_doc.cpp
index e85e530..b6a5ed4 100644
--- a/fpdfsdk/fpdf_doc.cpp
+++ b/fpdfsdk/fpdf_doc.cpp
@@ -163,6 +163,8 @@
       return PDFACTION_GOTO;
     case CPDF_Action::GoToR:
       return PDFACTION_REMOTEGOTO;
+    case CPDF_Action::GoToE:
+      return PDFACTION_EMBEDDEDGOTO;
     case CPDF_Action::URI:
       return PDFACTION_URI;
     case CPDF_Action::Launch:
@@ -179,9 +181,10 @@
     return nullptr;
 
   unsigned long type = FPDFAction_GetType(action);
-  if (type != PDFACTION_GOTO && type != PDFACTION_REMOTEGOTO)
+  if (type != PDFACTION_GOTO && type != PDFACTION_REMOTEGOTO &&
+      type != PDFACTION_EMBEDDEDGOTO) {
     return nullptr;
-
+  }
   CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
   return FPDFDestFromCPDFArray(cAction.GetDest(pDoc).GetArray());
 }
@@ -189,8 +192,10 @@
 FPDF_EXPORT unsigned long FPDF_CALLCONV
 FPDFAction_GetFilePath(FPDF_ACTION action, void* buffer, unsigned long buflen) {
   unsigned long type = FPDFAction_GetType(action);
-  if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_LAUNCH)
+  if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_EMBEDDEDGOTO &&
+      type != PDFACTION_LAUNCH) {
     return 0;
+  }
 
   CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
   ByteString path = cAction.GetFilePath().ToUTF8();
diff --git a/fpdfsdk/fpdf_doc_embeddertest.cpp b/fpdfsdk/fpdf_doc_embeddertest.cpp
index 652d565..24f57a9 100644
--- a/fpdfsdk/fpdf_doc_embeddertest.cpp
+++ b/fpdfsdk/fpdf_doc_embeddertest.cpp
@@ -388,6 +388,43 @@
   UnloadPage(page);
 }
 
+TEST_F(FPDFDocEmbedderTest, ActionEmbeddedGoto) {
+  ASSERT_TRUE(OpenDocument("gotoe_action.pdf"));
+
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  // The target action is nearly the size of the whole page.
+  FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
+  ASSERT_TRUE(link);
+
+  FPDF_ACTION action = FPDFLink_GetAction(link);
+  ASSERT_TRUE(action);
+  EXPECT_EQ(static_cast<unsigned long>(PDFACTION_EMBEDDEDGOTO),
+            FPDFAction_GetType(action));
+
+  FPDF_DEST dest = FPDFAction_GetDest(document(), action);
+  EXPECT_TRUE(dest);
+
+  unsigned long num_params = 42;
+  FS_FLOAT params[4];
+  std::fill_n(params, 4, 42.4242f);
+  EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
+            FPDFDest_GetView(dest, &num_params, params));
+  EXPECT_EQ(0u, num_params);
+  EXPECT_FLOAT_EQ(42.4242f, params[0]);
+
+  const char kExpectedResult[] = "ExampleFile.pdf";
+  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);
+}
+
 TEST_F(FPDFDocEmbedderTest, ActionNonesuch) {
   ASSERT_TRUE(OpenDocument("nonesuch_action.pdf"));
 
diff --git a/public/fpdf_doc.h b/public/fpdf_doc.h
index 1c8cf3b..6355ec6 100644
--- a/public/fpdf_doc.h
+++ b/public/fpdf_doc.h
@@ -24,6 +24,8 @@
 #define PDFACTION_URI 3
 // Launch an application or open a file.
 #define PDFACTION_LAUNCH 4
+// Go to a destination in an embedded file.
+#define PDFACTION_EMBEDDEDGOTO 5
 
 // View destination fit types. See pdfmark reference v9, page 48.
 #define PDFDEST_VIEW_UNKNOWN_MODE 0
diff --git a/testing/resources/gotoe_action.in b/testing/resources/gotoe_action.in
new file mode 100644
index 0000000..04b7cf0
--- /dev/null
+++ b/testing/resources/gotoe_action.in
@@ -0,0 +1,48 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [0 0 200 200]
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Annots [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Annot
+  /Subtype /Link
+  /FT /Tx
+  /Ff 29360128
+  /A 5 0 R
+  /T (txtName)
+  /F 4
+  /M (D:20150514070426+05'30')
+  /Rect [1 1 199 199]
+  /BS  <<
+    /W 1
+    /S /S
+  >>
+  /DA (/Helv 0 Tf 0 0 0 rg)
+  /V ()
+>>
+endobj
+{{object 5 0}} <<
+  /S /GoToE
+  /D [1 /Fit]
+  /F (ExampleFile.pdf)
+>>
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/gotoe_action.pdf b/testing/resources/gotoe_action.pdf
new file mode 100644
index 0000000..8d588e0
--- /dev/null
+++ b/testing/resources/gotoe_action.pdf
@@ -0,0 +1,60 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [0 0 200 200]
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Annots [4 0 R]
+>>
+endobj
+4 0 obj <<
+  /Type /Annot
+  /Subtype /Link
+  /FT /Tx
+  /Ff 29360128
+  /A 5 0 R
+  /T (txtName)
+  /F 4
+  /M (D:20150514070426+05'30')
+  /Rect [1 1 199 199]
+  /BS  <<
+    /W 1
+    /S /S
+  >>
+  /DA (/Helv 0 Tf 0 0 0 rg)
+  /V ()
+>>
+endobj
+5 0 obj <<
+  /S /GoToE
+  /D [1 /Fit]
+  /F (ExampleFile.pdf)
+>>
+>>
+endobj
+xref
+0 6
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000157 00000 n 
+0000000226 00000 n 
+0000000460 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 6
+>>
+startxref
+533
+%%EOF