Index: chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc |
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc |
index 2ebc790a511a410e938f005d73fd73cf0619906c..120a27e952fc53f1704461cc7c3343cadfb528a7 100644 |
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc |
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc |
@@ -42,6 +42,30 @@ bool IsEventExpired(const base::Time& event_time, double ttl_in_second) { |
return current_time_in_second - event_time_in_second > ttl_in_second; |
} |
+// Helper function to determine if the URL type should be LANDING_REFERRER or |
+// LANDING_PAGE, and modify AttributionResult accordingly. |
+ReferrerChainEntry::URLType GetURLTypeAndAdjustAttributionResult( |
+ int current_user_gesture_count, |
Nathan Parker
2017/01/04 19:49:12
What is current_user_gesture_count? Is that how ma
Jialiu Lin
2017/01/04 21:53:35
Good suggestion. Thanks!
|
+ int user_gesture_count_limit, |
+ SafeBrowsingNavigationObserverManager::AttributionResult* out_result) { |
+ // Landing page of a download refers to the page user directly interacts |
+ // with to trigger this download (e.g. clicking on download button). Landing |
+ // referrer page is the one user interacts with right before navigating to |
+ // the landing page. |
+ // Since we are tracing navigations backwards, if we've reached |
+ // |user_gesture_count_limit| number of user gesture before this navigation |
+ // event, this is a navigation leading to the landing referrer page, |
+ // otherwise it leads to landing page. |
+ if (current_user_gesture_count == user_gesture_count_limit) { |
+ *out_result = |
+ SafeBrowsingNavigationObserverManager::SUCCESS_LANDING_REFERRER; |
+ return ReferrerChainEntry::LANDING_REFERRER; |
+ } else { |
+ *out_result = SafeBrowsingNavigationObserverManager::SUCCESS_LANDING_PAGE; |
+ return ReferrerChainEntry::LANDING_PAGE; |
+ } |
+} |
+ |
} // namespace |
// The expiration period of a user gesture. Any user gesture that happened 1.0 |
@@ -156,7 +180,7 @@ void SafeBrowsingNavigationObserverManager::CleanUpStaleNavigationFootprints() { |
} |
SafeBrowsingNavigationObserverManager::AttributionResult |
-SafeBrowsingNavigationObserverManager::IdentifyReferrerChain( |
+SafeBrowsingNavigationObserverManager::IdentifyReferrerChainForDownload( |
const GURL& target_url, |
int target_tab_id, |
int user_gesture_count_limit, |
@@ -169,61 +193,72 @@ SafeBrowsingNavigationObserverManager::IdentifyReferrerChain( |
// We cannot find a single navigation event related to this download. |
return NAVIGATION_EVENT_NOT_FOUND; |
} |
- |
+ AttributionResult result = SUCCESS; |
AddToReferrerChain(out_referrer_chain, nav_event, |
ReferrerChainEntry::DOWNLOAD_URL); |
- AttributionResult result = SUCCESS; |
int user_gesture_count = 0; |
- while (user_gesture_count < user_gesture_count_limit) { |
- // Back trace to the next nav_event that was initiated by the user. |
- while (!nav_event->is_user_initiated) { |
- nav_event = |
- FindNavigationEvent(nav_event->source_url, nav_event->source_tab_id); |
- if (!nav_event) |
- return result; |
- AddToReferrerChain(out_referrer_chain, nav_event, |
- nav_event->has_server_redirect |
- ? ReferrerChainEntry::SERVER_REDIRECT |
- : ReferrerChainEntry::CLIENT_REDIRECT); |
- } |
+ GetRemainingReferrerChain( |
+ nav_event, |
+ user_gesture_count, |
+ user_gesture_count_limit, |
+ out_referrer_chain, |
+ &result); |
+ return result; |
+} |
- user_gesture_count++; |
+SafeBrowsingNavigationObserverManager::AttributionResult |
+SafeBrowsingNavigationObserverManager::IdentifyReferrerChainForPPAPIDownload( |
+ const GURL& initiating_frame_url, |
+ content::WebContents* web_contents, |
+ int user_gesture_count_limit, |
+ std::vector<ReferrerChainEntry>* out_referrer_chain) { |
+ if (!initiating_frame_url.is_valid()) |
+ return INVALID_URL; |
- // If the source_url and source_main_frame_url of current navigation event |
- // are empty, and is_user_initiated is true, this is a browser initiated |
- // navigation (e.g. trigged by typing in address bar, clicking on bookmark, |
- // etc). We reached the end of the referrer chain. |
- if (nav_event->source_url.is_empty() && |
- nav_event->source_main_frame_url.is_empty()) { |
- DCHECK(nav_event->is_user_initiated); |
- return result; |
- } |
+ int tab_id = SessionTabHelper::IdForTab(web_contents); |
+ UMA_HISTOGRAM_BOOLEAN( |
+ "SafeBrowsing.ReferrerHasInvalidTabID.PPAPIDownloadAttribution", |
+ tab_id == -1); |
- nav_event = |
- FindNavigationEvent(nav_event->source_url, nav_event->source_tab_id); |
- if (!nav_event) |
- return result; |
- |
- // Landing page of a download refers to the page user directly interacts |
- // with to trigger this download (e.g. clicking on download button). Landing |
- // referrer page is the one user interacts with right before navigating to |
- // the landing page. |
- // Since we are tracing navigations backwards, if we've encountered 1 user |
- // gesture before this navigation event, this is a navigation leading to the |
- // landing page. If we've encountered 2 user gestures, it leads to landing |
- // referrer page. |
- if (user_gesture_count == 1) { |
- AddToReferrerChain(out_referrer_chain, nav_event, |
- ReferrerChainEntry::LANDING_PAGE); |
- result = SUCCESS_LANDING_PAGE; |
- } else if (user_gesture_count == 2) { |
- AddToReferrerChain(out_referrer_chain, nav_event, |
- ReferrerChainEntry::LANDING_REFERRER); |
- result = SUCCESS_LANDING_REFERRER; |
- } else { |
- NOTREACHED(); |
- } |
+ NavigationEvent* nav_event = FindNavigationEvent(initiating_frame_url, |
+ tab_id); |
+ if (!nav_event) { |
+ // We cannot find a single navigation event related to this download. |
+ return NAVIGATION_EVENT_NOT_FOUND; |
+ } |
+ |
+ AttributionResult result = SUCCESS; |
+ bool has_user_gesture = false; |
+ auto it = user_gesture_map_.find(web_contents); |
+ if (it != user_gesture_map_.end() && |
+ !IsEventExpired(it->second, kUserGestureTTLInSecond)) { |
+ has_user_gesture = true; |
+ user_gesture_map_.erase(it); |
} |
+ |
+ int user_gesture_count = 0; |
+ // If this initiating_frame has user gesture, we consider this as the landing |
+ // page of the PPAPI download. |
+ if (has_user_gesture) { |
+ user_gesture_count = 1; |
+ AddToReferrerChain(out_referrer_chain, nav_event, |
+ GetURLTypeAndAdjustAttributionResult( |
+ user_gesture_count, |
+ user_gesture_count_limit, |
+ &result)); |
+ } else { |
+ AddToReferrerChain(out_referrer_chain, nav_event, |
+ nav_event->has_server_redirect |
+ ? ReferrerChainEntry::SERVER_REDIRECT |
+ : ReferrerChainEntry::CLIENT_REDIRECT); |
+ } |
+ |
+ GetRemainingReferrerChain( |
+ nav_event, |
+ user_gesture_count, |
+ user_gesture_count_limit, |
+ out_referrer_chain, |
+ &result); |
return result; |
} |
@@ -397,4 +432,52 @@ void SafeBrowsingNavigationObserverManager::AddToReferrerChain( |
referrer_chain->push_back(std::move(referrer_chain_entry)); |
} |
+void SafeBrowsingNavigationObserverManager::GetRemainingReferrerChain( |
+ NavigationEvent* last_nav_event_traced, |
+ int current_user_gesture_count, |
+ int user_gesture_count_limit, |
+ std::vector<ReferrerChainEntry>* out_referrer_chain, |
+ SafeBrowsingNavigationObserverManager::AttributionResult* out_result) { |
+ |
+ while (current_user_gesture_count < user_gesture_count_limit) { |
+ // Back trace to the next nav_event that was initiated by the user. |
+ while (!last_nav_event_traced->is_user_initiated) { |
+ last_nav_event_traced = |
+ FindNavigationEvent(last_nav_event_traced->source_url, |
+ last_nav_event_traced->source_tab_id); |
+ if (!last_nav_event_traced) |
+ return; |
+ AddToReferrerChain(out_referrer_chain, last_nav_event_traced, |
+ last_nav_event_traced->has_server_redirect |
+ ? ReferrerChainEntry::SERVER_REDIRECT |
+ : ReferrerChainEntry::CLIENT_REDIRECT); |
+ } |
+ |
+ current_user_gesture_count++; |
+ |
+ |
+ // If the source_url and source_main_frame_url of current navigation event |
+ // are empty, and is_user_initiated is true, this is a browser initiated |
+ // navigation (e.g. trigged by typing in address bar, clicking on bookmark, |
+ // etc). We reached the end of the referrer chain. |
+ if (last_nav_event_traced->source_url.is_empty() && |
Nathan Parker
2017/01/04 19:49:12
q: Up above in a few places is_valid() is used. I
Jialiu Lin
2017/01/04 21:53:35
invalid url could be empty or malformatted. Here I
|
+ last_nav_event_traced->source_main_frame_url.is_empty()) { |
+ DCHECK(last_nav_event_traced->is_user_initiated); |
+ return; |
+ } |
+ |
+ last_nav_event_traced = |
+ FindNavigationEvent(last_nav_event_traced->source_url, |
+ last_nav_event_traced->source_tab_id); |
+ if (!last_nav_event_traced) |
+ return; |
+ |
+ AddToReferrerChain(out_referrer_chain, last_nav_event_traced, |
+ GetURLTypeAndAdjustAttributionResult( |
+ current_user_gesture_count, |
+ user_gesture_count_limit, |
+ out_result)); |
+ } |
+} |
+ |
} // namespace safe_browsing |