 Chromium Code Reviews
 Chromium Code Reviews Issue 2302913003:
  Add SafeBrowsingNavigationObserver to listen to navigation events  (Closed)
    
  
    Issue 2302913003:
  Add SafeBrowsingNavigationObserver to listen to navigation events  (Closed) 
  | Index: chrome/browser/safe_browsing/safe_browsing_navigation_observer.h | 
| diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..1ab41d13bbbf9671ffa114cd3bb26e3b1f2fe6b9 | 
| --- /dev/null | 
| +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h | 
| @@ -0,0 +1,161 @@ | 
| +// 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. | 
| + | 
| +#ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_NAVIGATION_OBSERVER_H_ | 
| +#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_NAVIGATION_OBSERVER_H_ | 
| + | 
| +#include "base/supports_user_data.h" | 
| +#include "content/public/browser/navigation_handle.h" | 
| +#include "content/public/browser/notification_observer.h" | 
| +#include "content/public/browser/notification_registrar.h" | 
| +#include "content/public/browser/web_contents_observer.h" | 
| +#include "url/gurl.h" | 
| + | 
| +namespace content { | 
| +class NavigationHandle; | 
| +class NotificationRegistrar; | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: You're including NavigationHandle and Notific
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| +class RenderFrameHost; | 
| +struct ResourceRedirectDetails; | 
| +} | 
| + | 
| +namespace safe_browsing { | 
| + | 
| +// Struct to record the details of a navigation event for all frames. | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: for any frame.
(A single struct won't record
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| +// This information will be used to fill |url_chain| field in safe browsing | 
| +// download pings. | 
| +struct NavigationEvent { | 
| + NavigationEvent(); | 
| + NavigationEvent(NavigationEvent&& nav_event); | 
| + NavigationEvent& operator=(NavigationEvent&& nav_event); | 
| + ~NavigationEvent(); | 
| + GURL source_url; | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: Add blank line before, and add a comment sayi
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| + int source_tab_id; // Tab ID of the source WebContents returned by | 
| + // SessionTabHelper. It is immutable for a given tab | 
| + // and unique across Chrome within the current session. | 
| + | 
| + GURL target_url; | 
| 
Charlie Reis
2016/09/23 23:14:14
Let's be clear about whether this is the original
 
Jialiu Lin
2016/09/27 17:50:59
This is the original request URL. But NavigationMa
 | 
| + int target_tab_id; | 
| + | 
| + int frame_id; // Frame tree node id. | 
| + GURL main_frame_url; // Main frame url of the source. | 
| + | 
| + base::Time timestamp; // Timestamp of last time this object is updated. | 
| + | 
| + bool is_user_initiated; // browser_initiated || has_user_gesture. | 
| + bool has_committed; | 
| + bool is_server_redirect; | 
| + GURL server_redirect_url; // Last server redirect url in redirect chain. | 
| 
Charlie Reis
2016/09/23 23:14:14
Please clarify in the comment whether this is alwa
 
Jialiu Lin
2016/09/27 17:51:00
Yes, in case no server redirect, this field will b
 | 
| +}; | 
| + | 
| +// Manager class for SafeBrowsingNavigationObserver. | 
| 
Charlie Reis
2016/09/23 23:14:14
Can you say more about what this class manages?  T
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| +// TODO(jialiul): Remove base class content::NotificationObserver when | 
| +// WebContentsObserver::DidOpenRequestedURL() covers all retargeting cases. | 
| +class SBNavigationObserverManager | 
| 
Charlie Reis
2016/09/23 23:14:14
Is declaring a top-level class in the same file ok
 
Jialiu Lin
2016/09/27 17:51:00
Moved this manager class into a separate file. Don
 | 
| + : public content::NotificationObserver, | 
| + public base::RefCountedThreadSafe<SBNavigationObserverManager> { | 
| + public: | 
| + struct GurlHash { | 
| + std::size_t operator()(const GURL& url) const { | 
| + return std::hash<std::string>()(url.spec()); | 
| + } | 
| + }; | 
| + typedef std::unordered_map<GURL, std::vector<NavigationEvent>, GurlHash> | 
| + NavigationMap; | 
| + SBNavigationObserverManager(); | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: Blank line before (after typedefs).
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| + void RecordNavigationEvent(const GURL& nav_event_key, | 
| + NavigationEvent* nav_event); | 
| + void RecordUserGestureForWebContents(content::WebContents* web_contents, | 
| + const base::Time& timestamp); | 
| + void OnUserGestureConsumed(content::WebContents* web_contents, | 
| + const base::Time& timestamp); | 
| + // Clean-ups need to be done when a WebContents gets destroyed. | 
| + void OnWebContentDestroyed(content::WebContents* web_contents); | 
| + | 
| + // TODO(jialiul): more functions coming for managing navigation_map_. | 
| + | 
| + private: | 
| + friend class base::RefCountedThreadSafe<SBNavigationObserverManager>; | 
| + friend class TestNavigationObserverManager; | 
| + friend class SBNavigationObserverBrowserTest; | 
| + friend class SBNavigationObserverTest; | 
| + | 
| + typedef std::unordered_map<content::WebContents*, base::Time> UserGestureMap; | 
| + | 
| + ~SBNavigationObserverManager() override; | 
| + | 
| + // content::NotificationObserver: | 
| + void Observe(int type, | 
| + const content::NotificationSource& source, | 
| + const content::NotificationDetails& details) override; | 
| + | 
| + void RecordRetargeting(const content::NotificationDetails& details); | 
| + | 
| + NavigationMap* navigation_map() { return &navigation_map_; } | 
| + | 
| + // navigation_map_ keeps track of all the observed navigations. This map is | 
| + // keyed on target url. Since the same url can be requested multiple times | 
| 
Charlie Reis
2016/09/23 23:14:14
Is it correct to key this on the pre-redirect URL?
 
Jialiu Lin
2016/09/27 17:50:59
Fixed this comments. Map actually keyed on post-re
 | 
| + // across different tabs and frames, the value of this map is a vector of | 
| + // NavigationEvent ordered by navigation finish time. Entries in | 
| + // navigation_map_ will be removed if they are older than 2 minutes since | 
| + // their corresponding navigations finish. | 
| 
Charlie Reis
2016/09/23 23:14:14
Is this timer implemented yet?  I'm curious how it
 
Jialiu Lin
2016/09/27 17:50:59
Not yet. It will be in my next CL.
 | 
| + NavigationMap navigation_map_; | 
| + | 
| + // user_gesture_map_ keeps track of the timestamp of last user gesture in | 
| + // in each WebContents. This is used to determin if any retargeting navigation | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: determine
This seems like it won't be accura
 
Jialiu Lin
2016/09/27 17:51:00
Safe browsing backend will aggregate download ping
 | 
| + // is user_initiated. | 
| + UserGestureMap user_gesture_map_; | 
| + | 
| + content::NotificationRegistrar registrar_; | 
| + DISALLOW_COPY_AND_ASSIGN(SBNavigationObserverManager); | 
| +}; | 
| + | 
| +// Observes the navigation events for a single WebContents (both main-frame | 
| +// and sub-frame navigations) | 
| +class SafeBrowsingNavigationObserver : public base::SupportsUserData::Data, | 
| + public content::WebContentsObserver { | 
| + public: | 
| + static void MaybeCreateForWebContents(content::WebContents* web_contents); | 
| + static SafeBrowsingNavigationObserver* FromWebContents( | 
| + content::WebContents* web_contents); | 
| + | 
| + SafeBrowsingNavigationObserver( | 
| + content::WebContents* contents, | 
| + const scoped_refptr<SBNavigationObserverManager>& manager); | 
| + | 
| + ~SafeBrowsingNavigationObserver() override; | 
| + | 
| + private: | 
| + static const char kWebContentsUserDataKey[]; | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: Let's just declare this in an anonymous names
 
Jialiu Lin
2016/09/27 17:51:00
Done.
 | 
| + void RecordNavigationPendingEntry( | 
| 
Charlie Reis
2016/09/23 23:14:14
I don't see this implemented anywhere.
 
Jialiu Lin
2016/09/27 17:50:59
Oops, forgot to delete this one.
 | 
| + const content::NotificationSource& source, | 
| + const content::NotificationDetails& details); | 
| + | 
| + // content::WebContentsObserver: | 
| + void DidStartNavigation( | 
| + content::NavigationHandle* navigation_handle) override; | 
| + void DidRedirectNavigation( | 
| + content::NavigationHandle* navigation_handle) override; | 
| + void DidFinishNavigation( | 
| + content::NavigationHandle* navigation_handle) override; | 
| + void DidGetUserInteraction(const blink::WebInputEvent::Type type) override; | 
| + void WebContentsDestroyed() override; | 
| + | 
| + // Map keyed on NavigationHandle* to keep track of all the ongoing navigation | 
| + // events. NavigationHandle pointers are owned by RenderFrameHost. Since a | 
| + // NavigationHandle object will be destructed after navigation is done, | 
| + // corresponding entry in this map will be removed from navigation_handle_map_ | 
| + // and added to navigation_map_ at the end of DidFinishNavigation(...). | 
| + typedef std::unordered_map<content::NavigationHandle*, NavigationEvent> | 
| + NavigationHandleMap; | 
| 
Charlie Reis
2016/09/23 23:14:14
nit: Typedefs should be declared at the beginning
 
Jialiu Lin
2016/09/27 17:50:59
Done
 | 
| + NavigationHandleMap navigation_handle_map_; | 
| + scoped_refptr<SBNavigationObserverManager> manager_; | 
| + // If current on-going navigation triggered by a user gesture. | 
| + bool has_user_gesture_; | 
| 
Charlie Reis
2016/09/23 23:14:14
I don't think we can track this on a per-tab basis
 
Jialiu Lin
2016/09/27 17:51:00
Oh, sorry for the misleading comment. 
This field
 | 
| + base::Time last_user_gesture_timestamp_; | 
| + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingNavigationObserver); | 
| +}; | 
| + | 
| +} // namespace safe_browsing | 
| + | 
| +#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_NAVIGATION_OBSERVER_H_ |