Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Unified Diff: chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc

Issue 2302913003: Add SafeBrowsingNavigationObserver to listen to navigation events (Closed)
Patch Set: resolve final nit Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
new file mode 100644
index 0000000000000000000000000000000000000000..14fdb02acfce05e181fb1fba65d93e5912671441
--- /dev/null
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
@@ -0,0 +1,169 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h"
+#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/tab_contents/retargeting_details.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+
+using content::WebContents;
+
+namespace safe_browsing {
+
+// The expiration period of a user gesture. Any user gesture that happened 1.0
+// second ago will be considered as expired and not relevant to upcoming
+// navigation events.
+static const double kUserGestureTTLInSecond = 1.0;
+
+// static
+bool SafeBrowsingNavigationObserverManager::IsUserGestureExpired(
+ const base::Time& timestamp) {
+ double now = base::Time::Now().ToDoubleT();
+ double timestamp_in_double = timestamp.ToDoubleT();
+
+ if (now <= timestamp_in_double)
+ return true;
+ return (now - timestamp_in_double) > kUserGestureTTLInSecond;
+}
+
+// static
+GURL SafeBrowsingNavigationObserverManager::ClearEmptyRef(const GURL& url) {
+ if (url.has_ref() && url.ref().empty()) {
+ url::Replacements<char> replacements;
+ replacements.ClearRef();
+ return url.ReplaceComponents(replacements);
+ }
+ return url;
+}
+
+SafeBrowsingNavigationObserverManager::SafeBrowsingNavigationObserverManager() {
+ registrar_.Add(this, chrome::NOTIFICATION_RETARGETING,
+ content::NotificationService::AllSources());
+}
+
+void SafeBrowsingNavigationObserverManager::RecordNavigationEvent(
+ const GURL& nav_event_key,
+ NavigationEvent* nav_event) {
+ auto insertion_result = navigation_map_.insert(
+ std::make_pair(nav_event_key, std::vector<NavigationEvent>()));
+
+ insertion_result.first->second.push_back(std::move(*nav_event));
+}
+
+void SafeBrowsingNavigationObserverManager::RecordUserGestureForWebContents(
+ content::WebContents* web_contents,
+ const base::Time& timestamp) {
+ auto insertion_result =
+ user_gesture_map_.insert(std::make_pair(web_contents, timestamp));
+ // Update the timestamp if entry already exists.
+ if (!insertion_result.second)
+ insertion_result.first->second = timestamp;
+}
+
+void SafeBrowsingNavigationObserverManager::OnUserGestureConsumed(
+ content::WebContents* web_contents,
+ const base::Time& timestamp) {
+ auto it = user_gesture_map_.find(web_contents);
+ // Remove entry from |user_gesture_map_| as a user_gesture is consumed by
+ // a navigation event.
+ if (it != user_gesture_map_.end() && timestamp >= it->second)
+ user_gesture_map_.erase(it);
+}
+
+void SafeBrowsingNavigationObserverManager::RecordHostToIpMapping(
+ const std::string& host,
+ const std::string& ip) {
+ auto insert_result = host_to_ip_map_.insert(
+ std::make_pair(host, std::vector<ResolvedIPAddress>()));
+ if (!insert_result.second) {
+ // host_to_ip_map already contains this key.
+ // If this IP is already in the vector, we update its timestamp.
+ for (auto& vector_entry : insert_result.first->second) {
+ if (vector_entry.ip == host) {
+ vector_entry.timestamp = base::Time::Now();
+ return;
+ }
+ }
+ }
+ // If this is a new IP of this host, and we added to the end of the vector.
+ insert_result.first->second.push_back(
+ ResolvedIPAddress(base::Time::Now(), ip));
+}
+
+void SafeBrowsingNavigationObserverManager::OnWebContentDestroyed(
+ content::WebContents* web_contents) {
+ user_gesture_map_.erase(web_contents);
+ // TODO (jialiul): Will add other clean up tasks shortly.
+}
+
+SafeBrowsingNavigationObserverManager::
+ ~SafeBrowsingNavigationObserverManager() {}
+
+void SafeBrowsingNavigationObserverManager::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_RETARGETING)
+ RecordRetargeting(details);
+}
+
+void SafeBrowsingNavigationObserverManager::RecordRetargeting(
+ const content::NotificationDetails& details) {
+ const RetargetingDetails* retargeting_detail =
+ content::Details<const RetargetingDetails>(details).ptr();
+ DCHECK(retargeting_detail);
+ content::WebContents* source_contents =
+ retargeting_detail->source_web_contents;
+ content::WebContents* target_contents =
+ retargeting_detail->target_web_contents;
+ DCHECK(source_contents);
+ DCHECK(target_contents);
+
+ content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
+ retargeting_detail->source_render_process_id,
+ retargeting_detail->source_render_frame_id);
+ // Remove the "#" at the end of URL, since it does not point to any actual
+ // page fragment ID.
+ GURL target_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef(
+ retargeting_detail->target_url);
+
+ NavigationEvent nav_event;
+ if (rfh) {
+ nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef(
+ rfh->GetLastCommittedURL());
+ }
+ nav_event.source_tab_id = SessionTabHelper::IdForTab(source_contents);
+ nav_event.source_main_frame_url =
+ SafeBrowsingNavigationObserverManager::ClearEmptyRef(
+ source_contents->GetLastCommittedURL());
+ nav_event.original_request_url = target_url;
+ nav_event.destination_url = target_url;
+ nav_event.target_tab_id = SessionTabHelper::IdForTab(target_contents);
+ nav_event.frame_id = rfh ? rfh->GetFrameTreeNodeId() : -1;
+ auto it = user_gesture_map_.find(source_contents);
+ if (it != user_gesture_map_.end() &&
+ !SafeBrowsingNavigationObserverManager::IsUserGestureExpired(
+ it->second)) {
+ nav_event.is_user_initiated = true;
+ OnUserGestureConsumed(it->first, it->second);
+ } else {
+ nav_event.is_user_initiated = false;
+ }
+
+ auto insertion_result = navigation_map_.insert(
+ std::make_pair(target_url, std::vector<NavigationEvent>()));
+ insertion_result.first->second.push_back(std::move(nav_event));
+}
+
+} // namespace safe_browsing

Powered by Google App Engine
This is Rietveld 408576698