| 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 45207a1c0a7de7bb4cc8afe044b905676e930f97..c621d8646ba7f5f3b369aefc720316f937644690 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,28 @@ 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(
|
| + bool at_user_gesture_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 limit before this navigation event, this is a navigation
|
| + // leading to the landing referrer page, otherwise it leads to landing page.
|
| + if (at_user_gesture_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
|
| @@ -122,6 +144,18 @@ void SafeBrowsingNavigationObserverManager::OnUserGestureConsumed(
|
| user_gesture_map_.erase(it);
|
| }
|
|
|
| +bool SafeBrowsingNavigationObserverManager::HasUserGesture(
|
| + content::WebContents* web_contents) {
|
| + if (!web_contents)
|
| + return false;
|
| + auto it = user_gesture_map_.find(web_contents);
|
| + if (it != user_gesture_map_.end() &&
|
| + !IsEventExpired(it->second, kUserGestureTTLInSecond)) {
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| void SafeBrowsingNavigationObserverManager::RecordHostToIpMapping(
|
| const std::string& host,
|
| const std::string& ip) {
|
| @@ -156,7 +190,7 @@ void SafeBrowsingNavigationObserverManager::CleanUpStaleNavigationFootprints() {
|
| }
|
|
|
| SafeBrowsingNavigationObserverManager::AttributionResult
|
| -SafeBrowsingNavigationObserverManager::IdentifyReferrerChain(
|
| +SafeBrowsingNavigationObserverManager::IdentifyReferrerChainForDownload(
|
| const GURL& target_url,
|
| int target_tab_id,
|
| int user_gesture_count_limit,
|
| @@ -172,65 +206,60 @@ 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_main_frame_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,
|
| + int tab_id,
|
| + bool has_user_gesture,
|
| + 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;
|
| - }
|
| + NavigationEvent* nav_event =
|
| + FindNavigationEvent(initiating_frame_url, GURL(), tab_id);
|
| + if (!nav_event) {
|
| + // We cannot find a single navigation event related to this download.
|
| + return NAVIGATION_EVENT_NOT_FOUND;
|
| + }
|
|
|
| - nav_event =
|
| - FindNavigationEvent(nav_event->source_url,
|
| - nav_event->source_main_frame_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();
|
| - }
|
| + AttributionResult result = SUCCESS;
|
| +
|
| + 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;
|
| }
|
|
|
| @@ -358,17 +387,17 @@ NavigationEvent* SafeBrowsingNavigationObserverManager::FindNavigationEvent(
|
|
|
| // If target_url is empty, we should back trace navigation based on its
|
| // main frame URL instead.
|
| - const GURL& search_url =
|
| + GURL search_url =
|
| target_url.is_empty() ? target_main_frame_url : target_url;
|
| -
|
| auto it = navigation_map_.find(search_url);
|
| - if (it == navigation_map_.end()) {
|
| + if (it == navigation_map_.end())
|
| return nullptr;
|
| - }
|
| +
|
| // Since navigation events are recorded in chronological order, we traverse
|
| // the vector in reverse order to get the latest match.
|
| for (auto rit = it->second.rbegin(); rit != it->second.rend(); ++rit) {
|
| // If tab id is not valid, we only compare url, otherwise we compare both.
|
| + if (rit->destination_url == search_url)
|
| if (rit->destination_url == search_url &&
|
| (target_tab_id == -1 || rit->target_tab_id == target_tab_id)) {
|
| // If both source_url and source_main_frame_url are empty, and this
|
| @@ -377,7 +406,20 @@ NavigationEvent* SafeBrowsingNavigationObserverManager::FindNavigationEvent(
|
| // looks for the retargeting navigation event.
|
| if (rit->source_url.is_empty() && rit->source_main_frame_url.is_empty() &&
|
| !rit->is_user_initiated) {
|
| - continue;
|
| + // If there is a server redirection immediately after retargeting, we
|
| + // need to adjust our search url to the original request.
|
| + if (rit->has_server_redirect){
|
| + NavigationEvent* retargeting_nav_event =
|
| + FindNavigationEvent(rit->original_request_url,
|
| + GURL(),
|
| + rit->target_tab_id);
|
| + // Adjust retargeting navigation event's attributes.
|
| + retargeting_nav_event->has_server_redirect = true;
|
| + retargeting_nav_event->destination_url = search_url;
|
| + return retargeting_nav_event;
|
| + } else {
|
| + continue;
|
| + }
|
| } else {
|
| return &*rit;
|
| }
|
| @@ -413,4 +455,54 @@ 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_main_frame_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() &&
|
| + 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_main_frame_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
|
|
|