Encapsulate CPDF_StructElement::m_pDict

Return durable values to caller where possible.

Change-Id: I5cb60429c70dc35df3684e0ef6989b24bdfe6d20
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98953
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfdoc/cpdf_structelement.cpp b/core/fpdfdoc/cpdf_structelement.cpp
index 34370f3..59a3969 100644
--- a/core/fpdfdoc/cpdf_structelement.cpp
+++ b/core/fpdfdoc/cpdf_structelement.cpp
@@ -41,19 +41,41 @@
 }
 
 ByteString CPDF_StructElement::GetObjType() const {
-  return GetDict()->GetByteStringFor("Type");
+  return m_pDict->GetByteStringFor("Type");
 }
 
 WideString CPDF_StructElement::GetAltText() const {
-  return GetDict()->GetUnicodeTextFor("Alt");
+  return m_pDict->GetUnicodeTextFor("Alt");
 }
 
 WideString CPDF_StructElement::GetActualText() const {
-  return GetDict()->GetUnicodeTextFor("ActualText");
+  return m_pDict->GetUnicodeTextFor("ActualText");
 }
 
 WideString CPDF_StructElement::GetTitle() const {
-  return GetDict()->GetUnicodeTextFor("T");
+  return m_pDict->GetUnicodeTextFor("T");
+}
+
+absl::optional<WideString> CPDF_StructElement::GetID() const {
+  RetainPtr<const CPDF_Object> obj = m_pDict->GetObjectFor("ID");
+  if (!obj || !obj->IsString())
+    return absl::nullopt;
+  return obj->GetUnicodeText();
+}
+
+absl::optional<WideString> CPDF_StructElement::GetLang() const {
+  RetainPtr<const CPDF_Object> obj = m_pDict->GetObjectFor("Lang");
+  if (!obj || !obj->IsString())
+    return absl::nullopt;
+  return obj->GetUnicodeText();
+}
+
+RetainPtr<const CPDF_Object> CPDF_StructElement::GetA() const {
+  return m_pDict->GetObjectFor("A");
+}
+
+RetainPtr<const CPDF_Object> CPDF_StructElement::GetK() const {
+  return m_pDict->GetObjectFor("K");
 }
 
 size_t CPDF_StructElement::CountKids() const {
diff --git a/core/fpdfdoc/cpdf_structelement.h b/core/fpdfdoc/cpdf_structelement.h
index 5ab976f..11e4d75 100644
--- a/core/fpdfdoc/cpdf_structelement.h
+++ b/core/fpdfdoc/cpdf_structelement.h
@@ -12,6 +12,7 @@
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class CPDF_Dictionary;
 class CPDF_Object;
@@ -26,9 +27,10 @@
   WideString GetAltText() const;
   WideString GetActualText() const;
   WideString GetTitle() const;
-
-  // Never returns nullptr.
-  const CPDF_Dictionary* GetDict() const { return m_pDict.Get(); }
+  absl::optional<WideString> GetID() const;
+  absl::optional<WideString> GetLang() const;
+  RetainPtr<const CPDF_Object> GetA() const;
+  RetainPtr<const CPDF_Object> GetK() const;
 
   size_t CountKids() const;
   CPDF_StructElement* GetKidIfElement(size_t index) const;
diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp
index ed408bb..4c67474 100644
--- a/fpdfsdk/fpdf_structtree.cpp
+++ b/fpdfsdk/fpdf_structtree.cpp
@@ -106,14 +106,12 @@
                          unsigned long buflen) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  if (!dict)
+  if (!elem)
     return 0;
-  RetainPtr<const CPDF_Object> obj = dict->GetObjectFor("ID");
-  if (!obj || !obj->IsString())
+  absl::optional<WideString> id = elem->GetID();
+  if (!id.has_value())
     return 0;
-  return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer,
-                                             buflen);
+  return Utf16EncodeMaybeCopyAndReturnLength(id.value(), buffer, buflen);
 }
 
 FPDF_EXPORT unsigned long FPDF_CALLCONV
@@ -122,26 +120,23 @@
                            unsigned long buflen) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  if (!dict)
+  if (!elem)
     return 0;
-  RetainPtr<const CPDF_Object> obj = dict->GetObjectFor("Lang");
-  if (!obj || !obj->IsString())
+  absl::optional<WideString> lang = elem->GetLang();
+  if (!lang.has_value())
     return 0;
-  return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer,
-                                             buflen);
+  return Utf16EncodeMaybeCopyAndReturnLength(lang.value(), buffer, buflen);
 }
 
 FPDF_EXPORT int FPDF_CALLCONV
 FPDF_StructElement_GetAttributeCount(FPDF_STRUCTELEMENT struct_element) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  RetainPtr<const CPDF_Object> attr_obj =
-      dict ? dict->GetObjectFor("A") : nullptr;
+  if (!elem)
+    return -1;
+  RetainPtr<const CPDF_Object> attr_obj = elem->GetA();
   if (!attr_obj)
     return -1;
-
   if (attr_obj->IsArray())
     return fxcrt::CollectionSize<int>(*attr_obj->AsArray());
   return attr_obj->IsDictionary() ? 1 : -1;
@@ -152,9 +147,10 @@
                                        int index) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  RetainPtr<const CPDF_Object> attr_obj =
-      dict ? dict->GetObjectFor("A") : nullptr;
+  if (!elem)
+    return nullptr;
+
+  RetainPtr<const CPDF_Object> attr_obj = elem->GetA();
   if (!attr_obj)
     return nullptr;
 
@@ -163,7 +159,6 @@
                             attr_obj->AsDictionary())
                       : nullptr;
   }
-
   if (attr_obj->IsArray()) {
     const CPDF_Array* array = attr_obj->AsArray();
     if (index < 0 || static_cast<size_t>(index) >= array->size())
@@ -172,7 +167,6 @@
     return FPDFStructElementAttrFromCPDFDictionary(
         array->GetDictAt(index).Get());
   }
-
   return nullptr;
 }
 
@@ -183,8 +177,9 @@
                                       unsigned long buflen) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  RetainPtr<const CPDF_Array> array = dict ? dict->GetArrayFor("A") : nullptr;
+  if (!elem)
+    return 0;
+  RetainPtr<const CPDF_Array> array = ToArray(elem->GetA());
   if (!array)
     return 0;
   CPDF_ArrayLocker locker(array);
@@ -205,8 +200,9 @@
 FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  RetainPtr<const CPDF_Object> p =
-      elem ? elem->GetDict()->GetObjectFor("K") : nullptr;
+  if (!elem)
+    return -1;
+  RetainPtr<const CPDF_Object> p = elem->GetK();
   return p && p->IsNumber() ? p->GetInteger() : -1;
 }
 
@@ -418,8 +414,9 @@
 FPDF_StructElement_GetMarkedContentIdCount(FPDF_STRUCTELEMENT struct_element) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  RetainPtr<const CPDF_Object> p = dict ? dict->GetObjectFor("K") : nullptr;
+  if (!elem)
+    return -1;
+  RetainPtr<const CPDF_Object> p = elem->GetK();
   if (!p)
     return -1;
 
@@ -434,8 +431,9 @@
                                              int index) {
   CPDF_StructElement* elem =
       CPDFStructElementFromFPDFStructElement(struct_element);
-  const CPDF_Dictionary* dict = elem ? elem->GetDict() : nullptr;
-  RetainPtr<const CPDF_Object> p = dict ? dict->GetObjectFor("K") : nullptr;
+  if (!elem)
+    return -1;
+  RetainPtr<const CPDF_Object> p = elem->GetK();
   if (!p)
     return -1;