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 {
TestThreatDetailsFactory() : details_() {}
~TestThreatDetailsFactory() override {}
scoped_refptr<ThreatDetails> CreateThreatDetails(
std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* delegate,
WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource,
......@@ -244,7 +244,7 @@ class TestThreatDetailsFactory : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags,
ThreatDetailsDoneCallback done_callback) override {
auto details = base::WrapRefCounted(new ThreatDetails(
auto details = base::WrapUnique(new ThreatDetails(
delegate, web_contents, unsafe_resource, url_loader_factory,
history_service, referrer_chain_provider, trim_to_ad_tags,
done_callback));
......
......@@ -126,17 +126,19 @@ class ThreatDetailsWrap : public ThreatDetails {
run_loop_(nullptr),
done_callback_count_(0) {}
~ThreatDetailsWrap() override {}
void ThreatDetailsDone(content::WebContents* web_contents) {
++done_callback_count_;
run_loop_->Quit();
run_loop_ = NULL;
run_loop_ = nullptr;
}
// Used to synchronize ThreatDetailsDone() with WaitForThreatDetailsDone().
// RunLoop::RunUntilIdle() is not sufficient because the MessageLoop task
// queue completely drains at some point between the send and the wait.
void SetRunLoopToQuit(base::RunLoop* run_loop) {
DCHECK(run_loop_ == NULL);
DCHECK(run_loop_ == nullptr);
run_loop_ = run_loop;
}
......@@ -145,7 +147,6 @@ class ThreatDetailsWrap : public ThreatDetails {
void StartCollection() { ThreatDetails::StartCollection(); }
private:
~ThreatDetailsWrap() override {}
base::RunLoop* run_loop_;
size_t done_callback_count_;
......@@ -155,7 +156,7 @@ class MockSafeBrowsingUIManager : public SafeBrowsingUIManager {
public:
// The safe browsing UI manager does not need a service for this test.
MockSafeBrowsingUIManager()
: SafeBrowsingUIManager(NULL), report_sent_(false) {}
: SafeBrowsingUIManager(nullptr), report_sent_(false) {}
// When the serialized report is sent, this is called.
void SendSerializedThreatDetails(const std::string& serialized) override {
......@@ -406,9 +407,9 @@ TEST_F(ThreatDetailsTest, ThreatSubResource) {
InitResource(SB_THREAT_TYPE_URL_MALWARE, ThreatSource::CLIENT_SIDE_DETECTION,
true /* is_subresource */, GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -462,9 +463,9 @@ TEST_F(ThreatDetailsTest, SuspiciousSiteWithReferrerChain) {
.WillOnce(DoAll(SetArgPointee<2>(returned_referrer_chain),
Return(ReferrerChainProvider::SUCCESS)));
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -513,9 +514,9 @@ TEST_F(ThreatDetailsTest, ThreatSubResourceWithOriginalUrl) {
true /* is_subresource */, GURL(kThreatURL), &resource);
resource.original_url = GURL(kOriginalLandingURL);
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -562,9 +563,9 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails) {
InitResource(SB_THREAT_TYPE_URL_UNWANTED, ThreatSource::LOCAL_PVER3,
true /* is_subresource */, GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
// Send a message from the DOM, with 2 nodes, a parent and a child.
......@@ -785,8 +786,8 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
// Send both sets of nodes, from different render frames.
{
scoped_refptr<ThreatDetailsWrap> report = new ThreatDetailsWrap(
ui_manager_.get(), web_contents(), resource, NULL, history_service(),
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
......@@ -842,8 +843,8 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
elem_dom_outer_iframe->add_child_ids(0);
elem_dom_outer_iframe->add_child_ids(1);
scoped_refptr<ThreatDetailsWrap> report = new ThreatDetailsWrap(
ui_manager_.get(), web_contents(), resource, NULL, history_service(),
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
......@@ -969,9 +970,9 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_AmbiguousDOM) {
InitResource(SB_THREAT_TYPE_URL_UNWANTED,
ThreatSource::PASSWORD_PROTECTION_SERVICE,
true /* is_subresource */, GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
base::HistogramTester histograms;
......@@ -1225,9 +1226,9 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_TrimToAdTags) {
true /* is_subresource */, GURL(kThreatURL), &resource);
// Send both sets of nodes, from different render frames.
scoped_refptr<ThreatDetailsWrap> trimmed_report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get(),
auto trimmed_report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get(),
/*trim_to_ad_tags=*/true);
trimmed_report->StartCollection();
......@@ -1299,9 +1300,9 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_EmptyReportNotSent) {
true /* is_subresource */, GURL(kThreatURL), &resource);
// Send both sets of nodes, from different render frames.
scoped_refptr<ThreatDetailsWrap> trimmed_report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get(),
auto trimmed_report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get(),
/*trim_to_ad_tags=*/true);
trimmed_report->StartCollection();
......@@ -1332,9 +1333,9 @@ TEST_F(ThreatDetailsTest, ThreatWithRedirectUrl) {
resource.redirect_urls.push_back(GURL(kSecondRedirectURL));
resource.redirect_urls.push_back(GURL(kThreatURL));
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -1405,9 +1406,9 @@ TEST_F(ThreatDetailsTest, ThreatOnMainPageLoadBlocked) {
false /* is_subresource */, GURL(kLandingURL), &resource);
// Start ThreatDetails collection.
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
// Simulate clicking don't proceed.
......@@ -1466,9 +1467,9 @@ TEST_F(ThreatDetailsTest, ThreatWithPendingLoad) {
ui::PAGE_TRANSITION_TYPED, std::string());
// Do ThreatDetails collection.
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -1516,9 +1517,9 @@ TEST_F(ThreatDetailsTest, ThreatOnFreshTab) {
true /* is_subresource */, GURL(kThreatURL), &resource);
// Do ThreatDetails collection.
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
std::string serialized = WaitForThreatDetailsDone(
......@@ -1551,7 +1552,7 @@ TEST_F(ThreatDetailsTest, HTTPCache) {
ThreatSource::CLIENT_SIDE_DETECTION, true /* is_subresource */,
GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report = new ThreatDetailsWrap(
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, test_shared_loader_factory_,
history_service(), referrer_chain_provider_.get());
report->StartCollection();
......@@ -1630,7 +1631,7 @@ TEST_F(ThreatDetailsTest, HttpsResourceSanitization) {
ThreatSource::CLIENT_SIDE_DETECTION, true /* is_subresource */,
GURL(kThreatURLHttps), &resource);
scoped_refptr<ThreatDetailsWrap> report = new ThreatDetailsWrap(
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, test_shared_loader_factory_,
history_service(), referrer_chain_provider_.get());
report->StartCollection();
......@@ -1706,7 +1707,7 @@ TEST_F(ThreatDetailsTest, HTTPCacheNoEntries) {
ThreatSource::LOCAL_PVER3, true /* is_subresource */,
GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report = new ThreatDetailsWrap(
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, test_shared_loader_factory_,
history_service(), referrer_chain_provider_.get());
report->StartCollection();
......@@ -1772,9 +1773,9 @@ TEST_F(ThreatDetailsTest, HistoryServiceUrls) {
UnsafeResource resource;
InitResource(SB_THREAT_TYPE_URL_MALWARE, ThreatSource::LOCAL_PVER3,
true /* is_subresource */, GURL(kThreatURL), &resource);
scoped_refptr<ThreatDetailsWrap> report =
new ThreatDetailsWrap(ui_manager_.get(), web_contents(), resource, NULL,
history_service(), referrer_chain_provider_.get());
auto report = std::make_unique<ThreatDetailsWrap>(
ui_manager_.get(), web_contents(), resource, nullptr, history_service(),
referrer_chain_provider_.get());
report->StartCollection();
// The redirects collection starts after the IPC from the DOM is fired.
......
......@@ -271,7 +271,7 @@ void TrimElements(const std::set<int> target_ids,
// don't leak it.
class ThreatDetailsFactoryImpl : public ThreatDetailsFactory {
public:
scoped_refptr<ThreatDetails> CreateThreatDetails(
std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager,
WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource,
......@@ -280,7 +280,10 @@ class ThreatDetailsFactoryImpl : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags,
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,
history_service, referrer_chain_provider, trim_to_ad_tags,
done_callback));
......@@ -301,7 +304,7 @@ static base::LazyInstance<ThreatDetailsFactoryImpl>::DestructorAtExit
// Create a ThreatDetails for the given tab.
/* static */
scoped_refptr<ThreatDetails> ThreatDetails::NewThreatDetails(
std::unique_ptr<ThreatDetails> ThreatDetails::NewThreatDetails(
BaseUIManager* ui_manager,
WebContents* web_contents,
const UnsafeResource& resource,
......@@ -342,7 +345,8 @@ ThreatDetails::ThreatDetails(
cache_collector_(new ThreatDetailsCacheCollector),
done_callback_(done_callback),
all_done_expected_(false),
is_all_done_(false) {
is_all_done_(false),
weak_factory_(this) {
redirects_collector_ = new ThreatDetailsRedirectsCollector(
history_service ? history_service->AsWeakPtr()
: base::WeakPtr<history::HistoryService>());
......@@ -357,7 +361,8 @@ ThreatDetails::ThreatDetails()
ambiguous_dom_(false),
trim_to_ad_tags_(false),
all_done_expected_(false),
is_all_done_(false) {}
is_all_done_(false),
weak_factory_(this) {}
ThreatDetails::~ThreatDetails() {
DCHECK(all_done_expected_ == is_all_done_);
......@@ -570,8 +575,8 @@ void ThreatDetails::StartCollection() {
// OnReceivedThreatDOMDetails will be called when the renderer replies.
// TODO(mattm): In theory, if the user proceeds through the warning DOM
// detail collection could be started once the page loads.
web_contents()->ForEachFrame(
base::BindRepeating(&ThreatDetails::RequestThreatDOMDetails, this));
web_contents()->ForEachFrame(base::BindRepeating(
&ThreatDetails::RequestThreatDOMDetails, GetWeakPtr()));
}
}
......@@ -582,7 +587,7 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
threat_reporter.get();
pending_render_frame_hosts_.push_back(frame);
raw_threat_report->GetThreatDOMDetails(
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, this,
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, GetWeakPtr(),
std::move(threat_reporter), frame));
}
......@@ -704,7 +709,8 @@ void ThreatDetails::FinishCollection(bool did_proceed, int num_visit) {
urls.push_back(GURL(it->first));
}
redirects_collector_->StartHistoryCollection(
urls, base::Bind(&ThreatDetails::OnRedirectionCollectionReady, this));
urls,
base::Bind(&ThreatDetails::OnRedirectionCollectionReady, GetWeakPtr()));
}
void ThreatDetails::OnRedirectionCollectionReady() {
......@@ -718,7 +724,7 @@ void ThreatDetails::OnRedirectionCollectionReady() {
// Call the cache collector
cache_collector_->StartCacheCollection(
url_loader_factory_, &resources_, &cache_result_,
base::Bind(&ThreatDetails::OnCacheCollectionReady, this));
base::Bind(&ThreatDetails::OnCacheCollectionReady, GetWeakPtr()));
}
void ThreatDetails::AddRedirectUrlList(const std::vector<GURL>& urls) {
......@@ -833,4 +839,8 @@ void ThreatDetails::RenderFrameHostChanged(RenderFrameHost* old_host,
FrameDeleted(old_host);
}
base::WeakPtr<ThreatDetails> ThreatDetails::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
} // namespace safe_browsing
......@@ -67,13 +67,14 @@ using FrameTreeIdToChildIdsMap = base::hash_map<int, std::unordered_set<int>>;
// sending a report.
using ThreatDetailsDoneCallback = base::Callback<void(content::WebContents*)>;
class ThreatDetails : public base::RefCounted<ThreatDetails>,
public content::WebContentsObserver {
class ThreatDetails : public content::WebContentsObserver {
public:
typedef security_interstitials::UnsafeResource UnsafeResource;
~ThreatDetails() override;
// Constructs a new ThreatDetails instance, using the factory.
static scoped_refptr<ThreatDetails> NewThreatDetails(
static std::unique_ptr<ThreatDetails> NewThreatDetails(
BaseUIManager* ui_manager,
content::WebContents* web_contents,
const UnsafeResource& resource,
......@@ -106,6 +107,8 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
void RenderFrameHostChanged(content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) override;
base::WeakPtr<ThreatDetails> GetWeakPtr();
protected:
friend class ThreatDetailsFactoryImpl;
friend class TestThreatDetailsFactory;
......@@ -124,8 +127,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
// Default constructor for testing only.
ThreatDetails();
~ThreatDetails() override;
virtual void AddDOMDetails(const int frame_tree_node_id,
std::vector<mojom::ThreatDOMDetailsNodePtr> params,
const KeyToFrameTreeIdMap& child_frame_tree_map);
......@@ -140,8 +141,6 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
void StartCollection();
private:
friend class base::RefCounted<ThreatDetails>;
// Whether the url is "public" so we can add it to the report.
bool IsReportableUrl(const GURL& url) const;
......@@ -270,6 +269,9 @@ class ThreatDetails : public base::RefCounted<ThreatDetails>,
// deleted.
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, HttpsResourceSanitization);
FRIEND_TEST_ALL_PREFIXES(ThreatDetailsTest, HTTPCacheNoEntries);
......@@ -289,7 +291,7 @@ class ThreatDetailsFactory {
public:
virtual ~ThreatDetailsFactory() {}
virtual scoped_refptr<ThreatDetails> CreateThreatDetails(
virtual std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager,
content::WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource,
......
......@@ -186,12 +186,11 @@ bool TriggerManager::StartCollectingThreatDetailsWithReason(
return false;
bool should_trim_threat_details = trigger_type == TriggerType::AD_SAMPLE;
collectors->threat_details =
scoped_refptr<ThreatDetails>(ThreatDetails::NewThreatDetails(
ui_manager_, web_contents, resource, url_loader_factory,
history_service, referrer_chain_provider_, should_trim_threat_details,
collectors->threat_details = ThreatDetails::NewThreatDetails(
ui_manager_, web_contents, resource, url_loader_factory, history_service,
referrer_chain_provider_, should_trim_threat_details,
base::Bind(&TriggerManager::ThreatDetailsDone,
weak_factory_.GetWeakPtr())));
weak_factory_.GetWeakPtr()));
return true;
}
......@@ -220,7 +219,8 @@ bool TriggerManager::FinishCollectingThreatDetails(
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&ThreatDetails::FinishCollection,
collectors->threat_details, did_proceed, num_visits),
collectors->threat_details->GetWeakPtr(), did_proceed,
num_visits),
delay);
// Record that this trigger fired and collected data.
......
......@@ -43,7 +43,7 @@ struct DataCollectorsContainer {
// Note: new data collection types should be added below as additional fields.
// Collects ThreatDetails which contains resource URLs and partial DOM.
scoped_refptr<ThreatDetails> threat_details;
std::unique_ptr<ThreatDetails> threat_details;
private:
DISALLOW_COPY_AND_ASSIGN(DataCollectorsContainer);
......
......@@ -29,10 +29,10 @@ namespace safe_browsing {
class MockThreatDetails : public ThreatDetails {
public:
MockThreatDetails() {}
~MockThreatDetails() override {}
MOCK_METHOD2(FinishCollection, void(bool did_proceed, int num_visits));
private:
~MockThreatDetails() override {}
DISALLOW_COPY_AND_ASSIGN(MockThreatDetails);
};
......@@ -40,7 +40,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory {
public:
~MockThreatDetailsFactory() override {}
scoped_refptr<ThreatDetails> CreateThreatDetails(
std::unique_ptr<ThreatDetails> CreateThreatDetails(
BaseUIManager* ui_manager,
content::WebContents* web_contents,
const security_interstitials::UnsafeResource& unsafe_resource,
......@@ -49,7 +49,7 @@ class MockThreatDetailsFactory : public ThreatDetailsFactory {
ReferrerChainProvider* referrer_chain_provider,
bool trim_to_ad_tags,
ThreatDetailsDoneCallback done_callback) override {
return base::MakeRefCounted<MockThreatDetails>();
return std::make_unique<MockThreatDetails>();
}
};
......@@ -135,8 +135,11 @@ class TriggerManagerTest : public ::testing::Test {
trigger_type, web_contents, base::TimeDelta(), false, 0, options);
// 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);
}
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