Commit e6e17b9d authored by felt's avatar felt Committed by Commit bot

Update the Safe Browsing interstitial histograms

This organizes the Safe Browsing interstitial histograms in a way that
should scale better as new warnings or buttons are added.

Plus: all of the recording is done from within the command handling
method, instead of in the secondary methods like OnProceed.

BUG=

Review URL: https://codereview.chromium.org/576653002

Cr-Commit-Position: refs/heads/master@{#295294}
parent 83e3491e
......@@ -113,26 +113,6 @@ const char kEventNameOther[] = "safebrowsing_other_interstitial_";
base::LazyInstance<SafeBrowsingBlockingPage::UnsafeResourceMap>
g_unsafe_resource_map = LAZY_INSTANCE_INITIALIZER;
// This enum is used for a histogram. Don't reorder, delete, or insert
// elements. New elements should be added before MAX_ACTION only.
enum DetailedDecision {
MALWARE_SHOW_NEW_SITE = 0,
MALWARE_PROCEED_NEW_SITE,
MALWARE_SHOW_CROSS_SITE,
MALWARE_PROCEED_CROSS_SITE,
PHISHING_SHOW_NEW_SITE,
PHISHING_PROCEED_NEW_SITE,
PHISHING_SHOW_CROSS_SITE,
PHISHING_PROCEED_CROSS_SITE,
MAX_DETAILED_ACTION
};
void RecordDetailedUserAction(DetailedDecision decision) {
UMA_HISTOGRAM_ENUMERATION("SB2.InterstitialActionDetails",
decision,
MAX_DETAILED_ACTION);
}
} // namespace
// static
......@@ -201,7 +181,11 @@ SafeBrowsingBlockingPage::SafeBrowsingBlockingPage(
else
interstitial_type_ = TYPE_PHISHING;
RecordUserAction(SHOW);
RecordUserDecision(SHOW);
RecordUserInteraction(TOTAL_VISITS);
if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled))
RecordUserDecision(PROCEEDING_DISABLED);
HistoryService* history_service = HistoryServiceFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()),
Profile::EXPLICIT_ACCESS);
......@@ -284,10 +268,7 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
if (command == kLearnMoreCommand) {
// User pressed "Learn more".
#if defined(ENABLE_EXTENSIONS)
if (sampling_event_.get())
sampling_event_->set_has_viewed_learn_more(true);
#endif
RecordUserInteraction(SHOW_LEARN_MORE);
GURL learn_more_url(interstitial_type_ == TYPE_PHISHING ?
kLearnMorePhishingUrlV2 : kLearnMoreMalwareUrlV2);
learn_more_url = google_util::AppendGoogleLocaleParam(
......@@ -303,6 +284,7 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
if (command == kShowPrivacyCommand) {
// User pressed "Safe Browsing privacy policy".
RecordUserInteraction(SHOW_PRIVACY_POLICY);
GURL privacy_url(
l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_URL));
privacy_url = google_util::AppendGoogleLocaleParam(
......@@ -321,6 +303,7 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) {
proceed_blocked = true;
} else {
RecordUserDecision(PROCEED);
interstitial_page_->Proceed();
// |this| has been deleted after Proceed() returns.
return;
......@@ -328,6 +311,8 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
}
if (command == kTakeMeBackCommand || proceed_blocked) {
// Don't record the user action here because there are other ways of
// triggering DontProceed, like clicking the back button.
if (is_main_frame_load_blocked_) {
// If the load is blocked, we want to close the interstitial and discard
// the pending entry.
......@@ -374,6 +359,7 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
std::string bad_url_spec = unsafe_resources_[element_index].url.spec();
if (command == kShowDiagnosticCommand) {
// We're going to take the user to Google's SafeBrowsing diagnostic page.
RecordUserInteraction(SHOW_DIAGNOSTIC);
std::string diagnostic =
base::StringPrintf(kSbDiagnosticUrl,
net::EscapeQueryParamValue(bad_url_spec, true).c_str());
......@@ -392,11 +378,7 @@ void SafeBrowsingBlockingPage::CommandReceived(const std::string& cmd) {
}
if (command == kExpandedSeeMoreCommand) {
#if defined(ENABLE_EXTENSIONS)
// ExperienceSampling: We track that the user expanded the details.
if (sampling_event_.get())
sampling_event_->set_has_viewed_details(true);
#endif
RecordUserInteraction(SHOW_ADVANCED);
return;
}
......@@ -420,7 +402,6 @@ void SafeBrowsingBlockingPage::SetReportingPreference(bool report) {
void SafeBrowsingBlockingPage::OnProceed() {
proceeded_ = true;
RecordUserAction(PROCEED);
// Send the malware details, if we opted to.
FinishMalwareDetails(malware_details_proceed_delay_ms_);
......@@ -440,12 +421,6 @@ void SafeBrowsingBlockingPage::OnProceed() {
unsafe_resource_map->erase(iter);
}
#if defined(ENABLE_EXTENSIONS)
// ExperienceSampling: Notify that user decided to proceed.
if (sampling_event_.get())
sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed);
#endif
// Now that this interstitial is gone, we can show the new one.
if (blocking_page)
blocking_page->Show();
......@@ -470,7 +445,9 @@ void SafeBrowsingBlockingPage::OnDontProceed() {
if (proceeded_)
return;
RecordUserAction(DONT_PROCEED);
if (!IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled))
RecordUserDecision(DONT_PROCEED);
// Send the malware details, if we opted to.
FinishMalwareDetails(0); // No delay
......@@ -499,13 +476,6 @@ void SafeBrowsingBlockingPage::OnDontProceed() {
navigation_entry_index_to_remove_));
navigation_entry_index_to_remove_ = -1;
}
#if defined(ENABLE_EXTENSIONS)
// ExperienceSampling: Notify that user decided to go back.
// This also occurs if the user navigates away or closes the tab.
if (sampling_event_.get())
sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kDeny);
#endif
}
void SafeBrowsingBlockingPage::OnGotHistoryCount(bool success,
......@@ -515,108 +485,88 @@ void SafeBrowsingBlockingPage::OnGotHistoryCount(bool success,
num_visits_ = num_visits;
}
void SafeBrowsingBlockingPage::RecordUserAction(BlockingPageEvent event) {
// This enum is used for a histogram. Don't reorder, delete, or insert
// elements. New elements should be added before MAX_ACTION only.
enum {
MALWARE_SHOW = 0,
MALWARE_DONT_PROCEED,
MALWARE_FORCED_DONT_PROCEED,
MALWARE_PROCEED,
MULTIPLE_SHOW,
MULTIPLE_DONT_PROCEED,
MULTIPLE_FORCED_DONT_PROCEED,
MULTIPLE_PROCEED,
PHISHING_SHOW,
PHISHING_DONT_PROCEED,
PHISHING_FORCED_DONT_PROCEED,
PHISHING_PROCEED,
MALWARE_SHOW_ADVANCED,
MULTIPLE_SHOW_ADVANCED,
PHISHING_SHOW_ADVANCED,
MAX_ACTION
} histogram_action = MAX_ACTION;
switch (event) {
case SHOW:
switch (interstitial_type_) {
case TYPE_MALWARE:
histogram_action = MALWARE_SHOW;
break;
case TYPE_PHISHING:
histogram_action = PHISHING_SHOW;
break;
}
void SafeBrowsingBlockingPage::RecordUserDecision(Decision decision) {
switch (interstitial_type_) {
case TYPE_MALWARE:
UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision",
decision,
MAX_DECISION);
break;
case PROCEED:
switch (interstitial_type_) {
case TYPE_MALWARE:
histogram_action = MALWARE_PROCEED;
break;
case TYPE_PHISHING:
histogram_action = PHISHING_PROCEED;
break;
}
case TYPE_PHISHING:
UMA_HISTOGRAM_ENUMERATION("interstitial.phishing.decision",
decision,
MAX_DECISION);
break;
case DONT_PROCEED:
if (IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) {
switch (interstitial_type_) {
case TYPE_MALWARE:
histogram_action = MALWARE_FORCED_DONT_PROCEED;
break;
case TYPE_PHISHING:
histogram_action = PHISHING_FORCED_DONT_PROCEED;
break;
}
} else {
switch (interstitial_type_) {
case TYPE_MALWARE:
histogram_action = MALWARE_DONT_PROCEED;
break;
case TYPE_PHISHING:
histogram_action = PHISHING_DONT_PROCEED;
break;
}
}
default:
NOTREACHED();
}
#if defined(ENABLE_EXTENSIONS)
if (sampling_event_.get()) {
switch (decision) {
case PROCEED:
sampling_event_->CreateUserDecisionEvent(
ExperienceSamplingEvent::kProceed);
break;
case DONT_PROCEED:
sampling_event_->CreateUserDecisionEvent(
ExperienceSamplingEvent::kDeny);
break;
case SHOW:
case PROCEEDING_DISABLED:
case MAX_DECISION:
break;
}
}
#endif
// Record additional information about malware sites that users have
// visited before.
if (num_visits_ < 1 || interstitial_type_ != TYPE_MALWARE)
return;
if (decision == PROCEED || decision == DONT_PROCEED) {
UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision.repeat_visit",
SHOW,
MAX_DECISION);
UMA_HISTOGRAM_ENUMERATION("interstitial.malware.decision.repeat_visit",
decision,
MAX_DECISION);
}
}
void SafeBrowsingBlockingPage::RecordUserInteraction(Interaction interaction) {
switch (interstitial_type_) {
case TYPE_MALWARE:
UMA_HISTOGRAM_ENUMERATION("interstitial.malware.interaction",
interaction,
MAX_INTERACTION);
break;
case SHOW_ADVANCED:
switch (interstitial_type_) {
case TYPE_MALWARE:
histogram_action = MALWARE_SHOW_ADVANCED;
break;
case TYPE_PHISHING:
histogram_action = PHISHING_SHOW_ADVANCED;
break;
}
case TYPE_PHISHING:
UMA_HISTOGRAM_ENUMERATION("interstitial.phishing.interaction",
interaction,
MAX_INTERACTION);
break;
default:
NOTREACHED() << "Unexpected event: " << event;
}
if (histogram_action == MAX_ACTION) {
NOTREACHED();
} else {
UMA_HISTOGRAM_ENUMERATION("SB2.InterstitialAction", histogram_action,
MAX_ACTION);
NOTREACHED();
}
if (event == PROCEED || event == DONT_PROCEED) {
if (num_visits_ == 0) {
RecordDetailedUserAction((interstitial_type_ == TYPE_MALWARE) ?
MALWARE_SHOW_NEW_SITE : PHISHING_SHOW_NEW_SITE);
if (event == PROCEED) {
RecordDetailedUserAction((interstitial_type_ == TYPE_MALWARE) ?
MALWARE_PROCEED_NEW_SITE : PHISHING_PROCEED_NEW_SITE);
}
}
if (unsafe_resources_[0].is_subresource) {
RecordDetailedUserAction((interstitial_type_ == TYPE_MALWARE) ?
MALWARE_SHOW_CROSS_SITE : PHISHING_SHOW_CROSS_SITE);
if (event == PROCEED) {
RecordDetailedUserAction((interstitial_type_ == TYPE_MALWARE) ?
MALWARE_PROCEED_CROSS_SITE : PHISHING_PROCEED_CROSS_SITE);
}
}
#if defined(ENABLE_EXTENSIONS)
if (!sampling_event_.get())
return;
switch (interaction) {
case SHOW_LEARN_MORE:
sampling_event_->set_has_viewed_learn_more(true);
break;
case SHOW_ADVANCED:
sampling_event_->set_has_viewed_details(true);
break;
case SHOW_PRIVACY_POLICY:
case SHOW_DIAGNOSTIC:
case TOTAL_VISITS:
case MAX_INTERACTION:
break;
}
#endif
}
void SafeBrowsingBlockingPage::FinishMalwareDetails(int64 delay_ms) {
......
......@@ -125,16 +125,27 @@ class SafeBrowsingBlockingPage : public content::InterstitialPageDelegate {
FRIEND_TEST_ALL_PREFIXES(SafeBrowsingBlockingPageTest,
MalwareReportsToggling);
enum BlockingPageEvent {
// These enums are used for histograms. Don't reorder, delete, or insert
// elements. New elements should be added before MAX_ACTION only.
enum Decision {
SHOW,
PROCEED,
DONT_PROCEED,
PROCEEDING_DISABLED,
MAX_DECISION
};
enum Interaction {
TOTAL_VISITS,
SHOW_ADVANCED,
SHOW_PRIVACY_POLICY,
SHOW_DIAGNOSTIC,
SHOW_LEARN_MORE,
MAX_INTERACTION
};
// Records a user action for this interstitial, using the form
// SBInterstitial[Phishing|Malware|Multiple][Show|Proceed|DontProceed].
void RecordUserAction(BlockingPageEvent event);
// Record a user decision or interaction to the appropriate UMA histogram.
void RecordUserDecision(Decision decision);
void RecordUserInteraction(Interaction interaction);
// Used to query the HistoryService to see if the URL is in history. For UMA.
void OnGotHistoryCount(bool success, int num_visits, base::Time first_visit);
......
......@@ -10453,6 +10453,45 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary>
</histogram>
<histogram name="interstitial.malware.decision" enum="SB3InterstitialDecision">
<owner>felt@chromium.org</owner>
<summary>
User decision when presented with a Safe Browsing malware interstitial.
</summary>
</histogram>
<histogram name="interstitial.malware.decision.repeat_visit"
enum="SB3InterstitialDecision">
<owner>felt@chromium.org</owner>
<summary>
User decision when presented with a Safe Browsing malware interstitial for a
website that the user has visited before.
</summary>
</histogram>
<histogram name="interstitial.malware.interaction"
enum="SB3InterstitialInteraction">
<owner>felt@chromium.org</owner>
<summary>
User interactions with a Safe Browsing malware interstitial.
</summary>
</histogram>
<histogram name="interstitial.phishing.decision" enum="SB3InterstitialDecision">
<owner>felt@chromium.org</owner>
<summary>
User decision when presented with a Safe Browsing phishing interstitial.
</summary>
</histogram>
<histogram name="interstitial.phishing.interaction"
enum="SB3InterstitialInteraction">
<owner>felt@chromium.org</owner>
<summary>
User interactions with a Safe Browsing phishing interstitial.
</summary>
</histogram>
<histogram name="interstitial.ssl" enum="SSLResponseTypesV2">
<owner>felt@chromium.org</owner>
<summary>
......@@ -27537,6 +27576,9 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</histogram>
<histogram name="SB2.InterstitialAction" enum="SB2InterstitialAction">
<obsolete>
Deprecated, replaced by: interstitial.malware.* and interstitial.phishing.*.
</obsolete>
<owner>felt@chromium.org</owner>
<summary>
Track number of times Safe Browsing interstitials have been shown, and how
......@@ -27546,6 +27588,9 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<histogram name="SB2.InterstitialActionDetails"
enum="SB2InterstitialActionDetails">
<obsolete>
Deprecated, replaced by: interstitial.malware.* and interstitial.phishing.*.
</obsolete>
<owner>felt@chromium.org</owner>
<summary>
Tracks the click-through rate for specific cases of the interstitial.
......@@ -49410,6 +49455,9 @@ To add a new entry, add it with any value and run test to compute valid value.
</enum>
<enum name="SB2InterstitialAction" type="int">
<obsolete>
Deprecated 9/2014.
</obsolete>
<int value="0" label="MALWARE_SHOW"/>
<int value="1" label="MALWARE_DONT_PROCEED"/>
<int value="2" label="MALWARE_FORCED_DONT_PROCEED"/>
......@@ -49428,6 +49476,9 @@ To add a new entry, add it with any value and run test to compute valid value.
</enum>
<enum name="SB2InterstitialActionDetails" type="int">
<obsolete>
Deprecated 9/2014.
</obsolete>
<int value="0" label="MALWARE_SHOW_NEW_SITE"/>
<int value="1" label="MALWARE_PROCEED_NEW_SITE"/>
<int value="2" label="MALWARE_SHOW_CROSS_SITE"/>
......@@ -49480,6 +49531,21 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="7" label="BACKUP_NETWORK_SUCCESS"/>
</enum>
<enum name="SB3InterstitialDecision" type="int">
<int value="0" label="SHOW"/>
<int value="1" label="PROCEED"/>
<int value="2" label="DONT_PROCEED"/>
<int value="3" label="PROCEEDING_DISABLED"/>
</enum>
<enum name="SB3InterstitialInteraction" type="int">
<int value="0" label="TOTAL_VISITS"/>
<int value="1" label="SHOW_ADVANCED"/>
<int value="2" label="SHOW_PRIVACY"/>
<int value="3" label="SHOW_DIAGNOSTIC"/>
<int value="4" label="SHOW_LEARN_MORE"/>
</enum>
<enum name="SBClientDetectionPreClassificationCheckFail" type="int">
<int value="0" label="PROXY_FETCH"/>
<int value="1" label="PRIVATE_IP"/>
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