Commit 623815ca authored by Daniel Rubery's avatar Daniel Rubery Committed by Commit Bot

Change ThreatDetails to be uniquely owned

Looks like most of the work on this bug was already done. ThreatDetails
is only on the UI thread, and a callback is used after
FinishCollection. These mitigated the immediate problems with
ThreatDetails lifetime. This CL just does the final switch to owning
ThreatDetails with a unique_ptr.

Bug: 777915
Change-Id: Id89b34bb1ee2dbb7a5305822751780ee4ac2e862
Reviewed-on: https://chromium-review.googlesource.com/1183782Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Reviewed-by: default avatarNathan Parker <nparker@chromium.org>
Commit-Queue: Daniel Rubery <drubery@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585217}
parent 57d2a1b6
...@@ -235,7 +235,7 @@ class TestThreatDetailsFactory : public ThreatDetailsFactory { ...@@ -235,7 +235,7 @@ class TestThreatDetailsFactory : public ThreatDetailsFactory {
TestThreatDetailsFactory() : details_() {} TestThreatDetailsFactory() : details_() {}
~TestThreatDetailsFactory() override {} ~TestThreatDetailsFactory() override {}
scoped_refptr<ThreatDetails> CreateThreatDetails( std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* delegate, BaseUIManager* delegate,
WebContents* web_contents, WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource, const security_interstitials::UnsafeResource& unsafe_resource,
...@@ -244,7 +244,7 @@ class TestThreatDetailsFactory : public ThreatDetailsFactory { ...@@ -244,7 +244,7 @@ class TestThreatDetailsFactory : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider, ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags, bool trim_to_ad_tags,
ThreatDetailsDoneCallback done_callback) override { ThreatDetailsDoneCallback done_callback) override {
auto details = base::WrapRefCounted(new ThreatDetails( auto details = base::WrapUnique(new ThreatDetails(
delegate, web_contents, unsafe_resource, url_loader_factory, delegate, web_contents, unsafe_resource, url_loader_factory,
history_service, referrer_chain_provider, trim_to_ad_tags, history_service, referrer_chain_provider, trim_to_ad_tags,
done_callback)); done_callback));
......
...@@ -271,7 +271,7 @@ void TrimElements(const std::set<int> target_ids, ...@@ -271,7 +271,7 @@ void TrimElements(const std::set<int> target_ids,
// don't leak it. // don't leak it.
class ThreatDetailsFactoryImpl : public ThreatDetailsFactory { class ThreatDetailsFactoryImpl : public ThreatDetailsFactory {
public: public:
scoped_refptr<ThreatDetails> CreateThreatDetails( std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager, BaseUIManager* ui_manager,
WebContents* web_contents, WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource, const security_interstitials::UnsafeResource& unsafe_resource,
...@@ -280,7 +280,10 @@ class ThreatDetailsFactoryImpl : public ThreatDetailsFactory { ...@@ -280,7 +280,10 @@ class ThreatDetailsFactoryImpl : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider, ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags, bool trim_to_ad_tags,
ThreatDetailsDoneCallback done_callback) override { ThreatDetailsDoneCallback done_callback) override {
auto threat_details = base::WrapRefCounted(new ThreatDetails( // We can't use make_unique due to the protected constructor. We can't
// directly use std::unique_ptr<ThreatDetails>(new ThreatDetails(...))
// due to presubmit errors. So we use base::WrapUnique:
auto threat_details = base::WrapUnique(new ThreatDetails(
ui_manager, web_contents, unsafe_resource, url_loader_factory, ui_manager, web_contents, unsafe_resource, url_loader_factory,
history_service, referrer_chain_provider, trim_to_ad_tags, history_service, referrer_chain_provider, trim_to_ad_tags,
done_callback)); done_callback));
...@@ -301,7 +304,7 @@ static base::LazyInstance<ThreatDetailsFactoryImpl>::DestructorAtExit ...@@ -301,7 +304,7 @@ static base::LazyInstance<ThreatDetailsFactoryImpl>::DestructorAtExit
// Create a ThreatDetails for the given tab. // Create a ThreatDetails for the given tab.
/* static */ /* static */
scoped_refptr<ThreatDetails> ThreatDetails::NewThreatDetails( std::unique_ptr<ThreatDetails> ThreatDetails::NewThreatDetails(
BaseUIManager* ui_manager, BaseUIManager* ui_manager,
WebContents* web_contents, WebContents* web_contents,
const UnsafeResource& resource, const UnsafeResource& resource,
...@@ -342,7 +345,8 @@ ThreatDetails::ThreatDetails( ...@@ -342,7 +345,8 @@ ThreatDetails::ThreatDetails(
cache_collector_(new ThreatDetailsCacheCollector), cache_collector_(new ThreatDetailsCacheCollector),
done_callback_(done_callback), done_callback_(done_callback),
all_done_expected_(false), all_done_expected_(false),
is_all_done_(false) { is_all_done_(false),
weak_factory_(this) {
redirects_collector_ = new ThreatDetailsRedirectsCollector( redirects_collector_ = new ThreatDetailsRedirectsCollector(
history_service ? history_service->AsWeakPtr() history_service ? history_service->AsWeakPtr()
: base::WeakPtr<history::HistoryService>()); : base::WeakPtr<history::HistoryService>());
...@@ -357,7 +361,8 @@ ThreatDetails::ThreatDetails() ...@@ -357,7 +361,8 @@ ThreatDetails::ThreatDetails()
ambiguous_dom_(false), ambiguous_dom_(false),
trim_to_ad_tags_(false), trim_to_ad_tags_(false),
all_done_expected_(false), all_done_expected_(false),
is_all_done_(false) {} is_all_done_(false),
weak_factory_(this) {}
ThreatDetails::~ThreatDetails() { ThreatDetails::~ThreatDetails() {
DCHECK(all_done_expected_ == is_all_done_); DCHECK(all_done_expected_ == is_all_done_);
...@@ -570,8 +575,8 @@ void ThreatDetails::StartCollection() { ...@@ -570,8 +575,8 @@ void ThreatDetails::StartCollection() {
// OnReceivedThreatDOMDetails will be called when the renderer replies. // OnReceivedThreatDOMDetails will be called when the renderer replies.
// TODO(mattm): In theory, if the user proceeds through the warning DOM // TODO(mattm): In theory, if the user proceeds through the warning DOM
// detail collection could be started once the page loads. // detail collection could be started once the page loads.
web_contents()->ForEachFrame( web_contents()->ForEachFrame(base::BindRepeating(
base::BindRepeating(&ThreatDetails::RequestThreatDOMDetails, this)); &ThreatDetails::RequestThreatDOMDetails, GetWeakPtr()));
} }
} }
...@@ -582,7 +587,7 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) { ...@@ -582,7 +587,7 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
threat_reporter.get(); threat_reporter.get();
pending_render_frame_hosts_.push_back(frame); pending_render_frame_hosts_.push_back(frame);
raw_threat_report->GetThreatDOMDetails( raw_threat_report->GetThreatDOMDetails(
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, this, base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, GetWeakPtr(),
std::move(threat_reporter), frame)); std::move(threat_reporter), frame));
} }
...@@ -704,7 +709,8 @@ void ThreatDetails::FinishCollection(bool did_proceed, int num_visit) { ...@@ -704,7 +709,8 @@ void ThreatDetails::FinishCollection(bool did_proceed, int num_visit) {
urls.push_back(GURL(it->first)); urls.push_back(GURL(it->first));
} }
redirects_collector_->StartHistoryCollection( redirects_collector_->StartHistoryCollection(
urls, base::Bind(&ThreatDetails::OnRedirectionCollectionReady, this)); urls,
base::Bind(&ThreatDetails::OnRedirectionCollectionReady, GetWeakPtr()));
} }
void ThreatDetails::OnRedirectionCollectionReady() { void ThreatDetails::OnRedirectionCollectionReady() {
...@@ -718,7 +724,7 @@ void ThreatDetails::OnRedirectionCollectionReady() { ...@@ -718,7 +724,7 @@ void ThreatDetails::OnRedirectionCollectionReady() {
// Call the cache collector // Call the cache collector
cache_collector_->StartCacheCollection( cache_collector_->StartCacheCollection(
url_loader_factory_, &resources_, &cache_result_, url_loader_factory_, &resources_, &cache_result_,
base::Bind(&ThreatDetails::OnCacheCollectionReady, this)); base::Bind(&ThreatDetails::OnCacheCollectionReady, GetWeakPtr()));
} }
void ThreatDetails::AddRedirectUrlList(const std::vector<GURL>& urls) { void ThreatDetails::AddRedirectUrlList(const std::vector<GURL>& urls) {
...@@ -833,4 +839,8 @@ void ThreatDetails::RenderFrameHostChanged(RenderFrameHost* old_host, ...@@ -833,4 +839,8 @@ void ThreatDetails::RenderFrameHostChanged(RenderFrameHost* old_host,
FrameDeleted(old_host); FrameDeleted(old_host);
} }
base::WeakPtr<ThreatDetails> ThreatDetails::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
} // namespace safe_browsing } // namespace safe_browsing
...@@ -67,13 +67,14 @@ using FrameTreeIdToChildIdsMap = base::hash_map<int, std::unordered_set<int>>; ...@@ -67,13 +67,14 @@ using FrameTreeIdToChildIdsMap = base::hash_map<int, std::unordered_set<int>>;
// sending a report. // sending a report.
using ThreatDetailsDoneCallback = base::Callback<void(content::WebContents*)>; using ThreatDetailsDoneCallback = base::Callback<void(content::WebContents*)>;
class ThreatDetails : public base::RefCounted<ThreatDetails>, class ThreatDetails : public content::WebContentsObserver {
public content::WebContentsObserver {
public: public:
typedef security_interstitials::UnsafeResource UnsafeResource; typedef security_interstitials::UnsafeResource UnsafeResource;
~ThreatDetails() override;
// Constructs a new ThreatDetails instance, using the factory. // Constructs a new ThreatDetails instance, using the factory.
static scoped_refptr<ThreatDetails> NewThreatDetails( static std::unique_ptr<ThreatDetails> NewThreatDetails(
BaseUIManager* ui_manager, BaseUIManager* ui_manager,
content::WebContents* web_contents, content::WebContents* web_contents,
const UnsafeResource& resource, const UnsafeResource& resource,
...@@ -106,6 +107,8 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>, ...@@ -106,6 +107,8 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
void RenderFrameHostChanged(content::RenderFrameHost* old_host, void RenderFrameHostChanged(content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) override; content::RenderFrameHost* new_host) override;
base::WeakPtr<ThreatDetails> GetWeakPtr();
protected: protected:
friend class ThreatDetailsFactoryImpl; friend class ThreatDetailsFactoryImpl;
friend class TestThreatDetailsFactory; friend class TestThreatDetailsFactory;
...@@ -124,8 +127,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>, ...@@ -124,8 +127,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
// Default constructor for testing only. // Default constructor for testing only.
ThreatDetails(); ThreatDetails();
~ThreatDetails() override;
virtual void AddDOMDetails(const int frame_tree_node_id, virtual void AddDOMDetails(const int frame_tree_node_id,
std::vector<mojom::ThreatDOMDetailsNodePtr> params, std::vector<mojom::ThreatDOMDetailsNodePtr> params,
const KeyToFrameTreeIdMap& child_frame_tree_map); const KeyToFrameTreeIdMap& child_frame_tree_map);
...@@ -140,8 +141,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>, ...@@ -140,8 +141,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
void StartCollection(); void StartCollection();
private: private:
friend class base::RefCounted<ThreatDetails>;
// Whether the url is "public" so we can add it to the report. // Whether the url is "public" so we can add it to the report.
bool IsReportableUrl(const GURL& url) const; bool IsReportableUrl(const GURL& url) const;
...@@ -270,6 +269,9 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>, ...@@ -270,6 +269,9 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
// deleted. // deleted.
std::vector<content::RenderFrameHost*> pending_render_frame_hosts_; std::vector<content::RenderFrameHost*> pending_render_frame_hosts_;
// Used for references to |this| bound in callbacks.
base::WeakPtrFactory<ThreatDetails> weak_factory_;
FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HistoryServiceUrls); FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HistoryServiceUrls);
FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HttpsResourceSanitization); FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HttpsResourceSanitization);
FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HTTPCacheNoEntries); FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HTTPCacheNoEntries);
...@@ -289,7 +291,7 @@ class ThreatDetailsFactory { ...@@ -289,7 +291,7 @@ class ThreatDetailsFactory {
public: public:
virtual ~ThreatDetailsFactory() {} virtual ~ThreatDetailsFactory() {}
virtual scoped_refptr<ThreatDetails> CreateThreatDetails( virtual std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager, BaseUIManager* ui_manager,
content::WebContents* web_contents, content::WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource, const security_interstitials::UnsafeResource& unsafe_resource,
......
...@@ -186,12 +186,11 @@ bool TriggerManager::StartCollectingThreatDetailsWithReason( ...@@ -186,12 +186,11 @@ bool TriggerManager::StartCollectingThreatDetailsWithReason(
return false; return false;
bool should_trim_threat_details = trigger_type == TriggerType::AD_SAMPLE; bool should_trim_threat_details = trigger_type == TriggerType::AD_SAMPLE;
collectors->threat_details = collectors->threat_details = ThreatDetails::NewThreatDetails(
scoped_refptr<ThreatDetails>(ThreatDetails::NewThreatDetails( ui_manager_, web_contents, resource, url_loader_factory, history_service,
ui_manager_, web_contents, resource, url_loader_factory, referrer_chain_provider_, should_trim_threat_details,
history_service, referrer_chain_provider_, should_trim_threat_details, base::Bind(&TriggerManager::ThreatDetailsDone,
base::Bind(&TriggerManager::ThreatDetailsDone, weak_factory_.GetWeakPtr()));
weak_factory_.GetWeakPtr())));
return true; return true;
} }
...@@ -220,7 +219,8 @@ bool TriggerManager::FinishCollectingThreatDetails( ...@@ -220,7 +219,8 @@ bool TriggerManager::FinishCollectingThreatDetails(
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&ThreatDetails::FinishCollection, base::BindOnce(&ThreatDetails::FinishCollection,
collectors->threat_details, did_proceed, num_visits), collectors->threat_details->GetWeakPtr(), did_proceed,
num_visits),
delay); delay);
// Record that this trigger fired and collected data. // Record that this trigger fired and collected data.
......
...@@ -43,7 +43,7 @@ struct DataCollectorsContainer { ...@@ -43,7 +43,7 @@ struct DataCollectorsContainer {
// Note: new data collection types should be added below as additional fields. // Note: new data collection types should be added below as additional fields.
// Collects ThreatDetails which contains resource URLs and partial DOM. // Collects ThreatDetails which contains resource URLs and partial DOM.
scoped_refptr<ThreatDetails> threat_details; std::unique_ptr<ThreatDetails> threat_details;
private: private:
DISALLOW_COPY_AND_ASSIGN(DataCollectorsContainer); DISALLOW_COPY_AND_ASSIGN(DataCollectorsContainer);
......
...@@ -29,10 +29,10 @@ namespace safe_browsing { ...@@ -29,10 +29,10 @@ namespace safe_browsing {
class MockThreatDetails : public ThreatDetails { class MockThreatDetails : public ThreatDetails {
public: public:
MockThreatDetails() {} MockThreatDetails() {}
~MockThreatDetails() override {}
MOCK_METHOD2(FinishCollection, void(bool did_proceed, int num_visits)); MOCK_METHOD2(FinishCollection, void(bool did_proceed, int num_visits));
private: private:
~MockThreatDetails() override {}
DISALLOW_COPY_AND_ASSIGN(MockThreatDetails); DISALLOW_COPY_AND_ASSIGN(MockThreatDetails);
}; };
...@@ -40,7 +40,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory { ...@@ -40,7 +40,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory {
public: public:
~MockThreatDetailsFactory() override {} ~MockThreatDetailsFactory() override {}
scoped_refptr<ThreatDetails> CreateThreatDetails( std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager, BaseUIManager* ui_manager,
content::WebContents* web_contents, content::WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource, const security_interstitials::UnsafeResource& unsafe_resource,
...@@ -49,7 +49,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory { ...@@ -49,7 +49,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider, ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags, bool trim_to_ad_tags,
ThreatDetailsDoneCallback done_callback) override { ThreatDetailsDoneCallback done_callback) override {
return base::MakeRefCounted<MockThreatDetails>(); return std::make_unique<MockThreatDetails>();
} }
}; };
...@@ -135,8 +135,11 @@ class TriggerManagerTest : public ::testing::Test { ...@@ -135,8 +135,11 @@ class TriggerManagerTest : public ::testing::Test {
trigger_type, web_contents, base::TimeDelta(), false, 0, options); trigger_type, web_contents, base::TimeDelta(), false, 0, options);
// Invoke the callback if the report was to be sent. // Invoke the callback if the report was to be sent.
if (expect_report_sent) if (expect_report_sent) {
// Allow the ThreatDetails to complete, then remove it.
base::RunLoop().RunUntilIdle();
trigger_manager_.ThreatDetailsDone(web_contents); trigger_manager_.ThreatDetailsDone(web_contents);
}
return result; return result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment