Add RetainPtr<>::BackPointer() method.
Return an UnownedPtr from a RetainPtr. Prefered over calls to Get(),
since calls to Get() are almost always avoidable except in this one
circumstance where we would otherwise have a cycle of RetainPtr.
Use it in one place and remove some Get() calls along the way. In turn,
keep a RetainPtr in one class where we didn't really need a backpointer.
Change-Id: I89bb6291dc71a62d6aa989858c6e62aaa599ee17
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53617
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
index e5cdb70..6dc8d00 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
@@ -40,7 +40,7 @@
if (current_status_ == CPDF_DataAvail::DataAvailable)
return CPDF_DataAvail::DataAvailable;
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
while (true) {
bool check_result = false;
switch (current_state_) {
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index d276fc1..d80feef 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -174,7 +174,7 @@
bool CPDF_DataAvail::CheckAndLoadAllXref() {
if (!m_pCrossRefAvail) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
const FX_FILESIZE last_xref_offset = m_parser.ParseStartXRef();
if (GetValidator()->has_read_problems())
return false;
@@ -222,7 +222,7 @@
std::unique_ptr<CPDF_Object> pRet;
if (pParser) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
pRet = pParser->ParseIndirectObject(objnum);
if (GetValidator()->has_read_problems())
return nullptr;
@@ -241,7 +241,7 @@
return true;
}
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
m_parser.ParseIndirectObject(dwInfoObjNum);
if (GetValidator()->has_read_problems())
return false;
@@ -257,7 +257,7 @@
return true;
}
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
m_pRoot = ToDictionary(m_parser.ParseIndirectObject(dwRootObjNum));
if (GetValidator()->has_read_problems())
return false;
@@ -436,7 +436,7 @@
}
bool CPDF_DataAvail::CheckHintTables() {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
m_pHintTables =
CPDF_HintTables::Parse(GetSyntaxParser(), m_pLinearized.get());
@@ -484,7 +484,7 @@
if (m_bHeaderAvail)
return DocAvailStatus::DataAvailable;
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
const Optional<FX_FILESIZE> header_offset = GetHeaderOffset(GetValidator());
if (GetValidator()->has_read_problems())
return DocAvailStatus::DataNotAvailable;
@@ -813,7 +813,7 @@
auto page_num_obj = std::make_pair(
dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>(
- GetValidator().Get(), m_pDocument.Get(), pPageDict));
+ GetValidator(), m_pDocument.Get(), pPageDict));
CPDF_PageObjectAvail* page_obj_avail =
m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get();
@@ -865,7 +865,7 @@
{
auto page_num_obj = std::make_pair(
dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>(
- GetValidator().Get(), m_pDocument.Get(), pPageDict));
+ GetValidator(), m_pDocument.Get(), pPageDict));
CPDF_PageObjectAvail* page_obj_avail =
m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get();
const DocAvailStatus status = page_obj_avail->CheckAvail();
@@ -886,7 +886,7 @@
CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckResources(
const CPDF_Dictionary* page) {
ASSERT(page);
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
const CPDF_Object* resources = GetResourceObject(page);
if (GetValidator()->has_read_problems())
return DocAvailStatus::DataNotAvailable;
@@ -897,9 +897,8 @@
CPDF_PageObjectAvail* resource_avail =
m_PagesResourcesAvail
.insert(std::make_pair(
- resources,
- pdfium::MakeUnique<CPDF_PageObjectAvail>(
- GetValidator().Get(), m_pDocument.Get(), resources)))
+ resources, pdfium::MakeUnique<CPDF_PageObjectAvail>(
+ GetValidator(), m_pDocument.Get(), resources)))
.first->second.get();
return resource_avail->CheckAvail();
}
@@ -978,7 +977,7 @@
return FormNotExist;
m_pFormAvail = pdfium::MakeUnique<CPDF_PageObjectAvail>(
- GetValidator().Get(), m_pDocument.Get(), pAcroForm);
+ GetValidator(), m_pDocument.Get(), pAcroForm);
}
switch (m_pFormAvail->CheckAvail()) {
case DocAvailStatus::DataError:
@@ -998,8 +997,7 @@
auto* pPageDict = m_pDocument->GetPageDictionary(safePage.ValueOrDie());
if (!pPageDict)
return false;
- CPDF_PageObjectAvail obj_avail(GetValidator().Get(), m_pDocument.Get(),
- pPageDict);
+ CPDF_PageObjectAvail obj_avail(GetValidator(), m_pDocument.Get(), pPageDict);
return obj_avail.CheckAvail() == DocAvailStatus::DataAvailable;
}
@@ -1012,7 +1010,7 @@
auto document = pdfium::MakeUnique<CPDF_Document>();
document->AddObserver(this);
- CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ CPDF_ReadValidator::Session read_session(GetValidator());
CPDF_Parser::Error error =
document->LoadLinearizedDoc(GetValidator(), password);
diff --git a/core/fpdfapi/parser/cpdf_object_avail.cpp b/core/fpdfapi/parser/cpdf_object_avail.cpp
index e1b9b3f..5beb7a0 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail.cpp
@@ -13,9 +13,10 @@
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "third_party/base/ptr_util.h"
-CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator,
- CPDF_IndirectObjectHolder* holder,
- const CPDF_Object* root)
+CPDF_ObjectAvail::CPDF_ObjectAvail(
+ const RetainPtr<CPDF_ReadValidator>& validator,
+ CPDF_IndirectObjectHolder* holder,
+ const CPDF_Object* root)
: validator_(validator), holder_(holder), root_(root) {
ASSERT(validator_);
ASSERT(holder);
@@ -24,9 +25,10 @@
parsed_objnums_.insert(root_->GetObjNum());
}
-CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator,
- CPDF_IndirectObjectHolder* holder,
- uint32_t obj_num)
+CPDF_ObjectAvail::CPDF_ObjectAvail(
+ const RetainPtr<CPDF_ReadValidator>& validator,
+ CPDF_IndirectObjectHolder* holder,
+ uint32_t obj_num)
: validator_(validator),
holder_(holder),
root_(pdfium::MakeUnique<CPDF_Reference>(holder, obj_num)) {
@@ -58,7 +60,7 @@
return true;
}
- const CPDF_ReadValidator::Session parse_session(validator_.Get());
+ const CPDF_ReadValidator::Session parse_session(validator_);
const CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num);
if (validator_->has_read_problems())
return false;
@@ -88,7 +90,7 @@
if (!checked_objects.insert(obj_num).second)
continue;
- const CPDF_ReadValidator::Session parse_session(validator_.Get());
+ const CPDF_ReadValidator::Session parse_session(validator_);
const CPDF_Object* direct = holder_->GetOrParseIndirectObject(obj_num);
if (direct == root_.Get())
continue;
@@ -111,7 +113,7 @@
CPDF_ObjectWalker walker(object);
while (const CPDF_Object* obj = walker.GetNext()) {
- const CPDF_ReadValidator::Session parse_session(validator_.Get());
+ const CPDF_ReadValidator::Session parse_session(validator_);
// Skip if this object if it's an inlined root, the parent object or
// explicitily excluded.
diff --git a/core/fpdfapi/parser/cpdf_object_avail.h b/core/fpdfapi/parser/cpdf_object_avail.h
index ea4d449..017ea9a 100644
--- a/core/fpdfapi/parser/cpdf_object_avail.h
+++ b/core/fpdfapi/parser/cpdf_object_avail.h
@@ -10,6 +10,7 @@
#include "core/fpdfapi/parser/cpdf_data_avail.h"
#include "core/fxcrt/maybe_owned.h"
+#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
class CPDF_Object;
@@ -20,10 +21,10 @@
// Helper for check availability of object tree.
class CPDF_ObjectAvail {
public:
- CPDF_ObjectAvail(CPDF_ReadValidator* validator,
+ CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
CPDF_IndirectObjectHolder* holder,
const CPDF_Object* root);
- CPDF_ObjectAvail(CPDF_ReadValidator* validator,
+ CPDF_ObjectAvail(const RetainPtr<CPDF_ReadValidator>& validator,
CPDF_IndirectObjectHolder* holder,
uint32_t obj_num);
virtual ~CPDF_ObjectAvail();
@@ -41,7 +42,7 @@
void CleanMemory();
bool HasObjectParsed(uint32_t obj_num) const;
- UnownedPtr<CPDF_ReadValidator> validator_;
+ RetainPtr<CPDF_ReadValidator> validator_;
UnownedPtr<CPDF_IndirectObjectHolder> holder_;
MaybeOwned<const CPDF_Object> root_;
std::set<uint32_t> parsed_objnums_;
diff --git a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
index 9bbc8f4..f7e0cad 100644
--- a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp
@@ -132,7 +132,7 @@
TestHolder holder;
holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
holder.SetObjectState(1, TestHolder::ObjectState::Available);
@@ -145,7 +145,7 @@
TestHolder::ObjectState::Unavailable);
holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
@@ -166,7 +166,7 @@
holder.AddObject(3, pdfium::MakeUnique<CPDF_Reference>(&holder, 1),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
@@ -192,7 +192,7 @@
holder.GetTestObject(2)->GetDict()->SetNewFor<CPDF_Reference>("Parent",
&holder, 1);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 2);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 2);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
@@ -215,8 +215,7 @@
holder.AddObject(kDepth, pdfium::MakeUnique<CPDF_Dictionary>(),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
-
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
for (uint32_t i = 1; i <= kDepth; ++i) {
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
@@ -229,7 +228,7 @@
TestHolder holder;
holder.AddObject(1, pdfium::MakeUnique<CPDF_Dictionary>(),
TestHolder::ObjectState::Available);
- CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
}
@@ -239,7 +238,7 @@
TestHolder::ObjectState::Available);
holder.AddObject(2, pdfium::MakeUnique<CPDF_Dictionary>(),
TestHolder::ObjectState::Available);
- CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
}
@@ -258,7 +257,7 @@
3,
pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvailExcludeArray avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvailExcludeArray avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
}
@@ -287,7 +286,7 @@
pdfium::MakeUnique<CPDF_String>(nullptr, "Not available string", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
@@ -306,7 +305,7 @@
TestHolder::ObjectState::Available);
holder.GetTestObject(1)->GetDict()->SetNewFor<CPDF_Reference>(
"NotExistsObjRef", &holder, 2);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
// Now object should be available, although the object '2' is not exists. But
// all exists in file related data are checked.
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
@@ -317,7 +316,7 @@
holder.AddObject(1, pdfium::MakeUnique<CPDF_String>(nullptr, "string", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, 1);
EXPECT_EQ(avail.CheckAvail(), avail.CheckAvail());
holder.SetObjectState(1, TestHolder::ObjectState::Available);
@@ -339,7 +338,7 @@
holder.AddObject(2, pdfium::MakeUnique<CPDF_String>(nullptr, "Data", false),
TestHolder::ObjectState::Unavailable);
- CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, root);
+ CPDF_ObjectAvail avail(holder.GetValidator(), &holder, root);
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable,
avail.CheckAvail());
diff --git a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
index e3f97df..18a973b 100644
--- a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp
@@ -116,7 +116,7 @@
4, pdfium::MakeUnique<CPDF_String>(nullptr, "Other page data", false),
TestHolder::ObjectState::Unavailable);
- CPDF_PageObjectAvail avail(holder.GetValidator().Get(), &holder, 1);
+ CPDF_PageObjectAvail avail(holder.GetValidator(), &holder, 1);
// Now object should be available, although the object '4' is not available,
// because it is in skipped other page.
EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail());
diff --git a/core/fpdfapi/parser/cpdf_read_validator.cpp b/core/fpdfapi/parser/cpdf_read_validator.cpp
index 37f17ce..426e06f 100644
--- a/core/fpdfapi/parser/cpdf_read_validator.cpp
+++ b/core/fpdfapi/parser/cpdf_read_validator.cpp
@@ -27,8 +27,9 @@
} // namespace
-CPDF_ReadValidator::Session::Session(CPDF_ReadValidator* validator)
- : validator_(validator) {
+CPDF_ReadValidator::Session::Session(
+ const RetainPtr<CPDF_ReadValidator>& validator)
+ : validator_(validator.BackPointer()) {
ASSERT(validator_);
saved_read_error_ = validator_->read_error_;
saved_has_unavailable_data_ = validator_->has_unavailable_data_;
diff --git a/core/fpdfapi/parser/cpdf_read_validator.h b/core/fpdfapi/parser/cpdf_read_validator.h
index 23cc4d0..6adde02 100644
--- a/core/fpdfapi/parser/cpdf_read_validator.h
+++ b/core/fpdfapi/parser/cpdf_read_validator.h
@@ -12,7 +12,7 @@
public:
class Session {
public:
- explicit Session(CPDF_ReadValidator* validator);
+ explicit Session(const RetainPtr<CPDF_ReadValidator>& validator);
~Session();
private:
@@ -21,16 +21,14 @@
bool saved_has_unavailable_data_;
};
- void SetDownloadHints(CPDF_DataAvail::DownloadHints* hints) {
- hints_ = hints;
- }
-
template <typename T, typename... Args>
friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+ void SetDownloadHints(CPDF_DataAvail::DownloadHints* hints) {
+ hints_ = hints;
+ }
bool read_error() const { return read_error_; }
bool has_unavailable_data() const { return has_unavailable_data_; }
-
bool has_read_problems() const {
return read_error() || has_unavailable_data();
}
diff --git a/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
index 97390bc..38b4bf9 100644
--- a/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp
@@ -169,7 +169,7 @@
auto validator = pdfium::MakeRetain<CPDF_ReadValidator>(file, &file_avail);
validator->SetDownloadHints(&hints);
- const CPDF_ReadValidator::Session read_session(validator.Get());
+ const CPDF_ReadValidator::Session read_session(validator);
ASSERT_FALSE(validator->has_read_problems());
// Data is unavailable
@@ -180,7 +180,7 @@
EXPECT_FALSE(validator->read_error());
{
- const CPDF_ReadValidator::Session read_subsession(validator.Get());
+ const CPDF_ReadValidator::Session read_subsession(validator);
// The read problems should be hidden.
EXPECT_FALSE(validator->has_read_problems());
@@ -207,7 +207,7 @@
auto validator = pdfium::MakeRetain<CPDF_ReadValidator>(file, &file_avail);
validator->SetDownloadHints(&hints);
- const CPDF_ReadValidator::Session read_session(validator.Get());
+ const CPDF_ReadValidator::Session read_session(validator);
ASSERT_FALSE(validator->has_read_problems());
// Data is unavailable
@@ -218,7 +218,7 @@
EXPECT_FALSE(validator->read_error());
{
- const CPDF_ReadValidator::Session read_subsession(validator.Get());
+ const CPDF_ReadValidator::Session read_subsession(validator);
// The read problems should be hidden.
EXPECT_FALSE(validator->has_read_problems());
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index 18d4b0a..ae844bd 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -389,7 +389,7 @@
}
ByteString CPDF_SyntaxParser::GetNextWord(bool* bIsNumber) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
GetNextWordInternal(bIsNumber);
ByteString ret;
if (!GetValidator()->has_read_problems())
@@ -412,7 +412,7 @@
std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetObjectBody(
CPDF_IndirectObjectHolder* pObjList) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
auto result = GetObjectBodyInternal(pObjList, ParseType::kLoose);
if (GetValidator()->has_read_problems())
return nullptr;
@@ -533,7 +533,7 @@
std::unique_ptr<CPDF_Object> CPDF_SyntaxParser::GetIndirectObject(
CPDF_IndirectObjectHolder* pObjList,
ParseType parse_type) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
const FX_FILESIZE saved_pos = GetPos();
bool is_number = false;
ByteString word = GetNextWord(&is_number);
@@ -667,7 +667,7 @@
// Note, we allow zero length streams as we need to pass them through when we
// are importing pages into a new document.
if (len >= 0) {
- const CPDF_ReadValidator::Session read_session(GetValidator().Get());
+ const CPDF_ReadValidator::Session read_session(GetValidator());
m_Pos += ReadEOLMarkers(GetPos());
memset(m_WordBuffer, 0, kEndStreamStr.GetLength() + 1);
GetNextWordInternal(nullptr);
diff --git a/core/fxcrt/retain_ptr.h b/core/fxcrt/retain_ptr.h
index edd2663..e6b8ac7 100644
--- a/core/fxcrt/retain_ptr.h
+++ b/core/fxcrt/retain_ptr.h
@@ -10,6 +10,7 @@
#include <utility>
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/unowned_ptr.h"
namespace fxcrt {
@@ -51,6 +52,7 @@
}
T* Get() const { return m_pObj.get(); }
+ UnownedPtr<T> BackPointer() const { return UnownedPtr<T>(Get()); }
void Swap(RetainPtr& that) { m_pObj.swap(that.m_pObj); }
// Useful for passing notion of object ownership across a C API.