Chromium Code Reviews| 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 |