Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h" | |
| 6 | |
| 7 #include "base/memory/ptr_util.h" | |
| 8 #include "base/time/time.h" | |
| 9 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager .h" | |
| 10 #include "chrome/browser/sessions/session_tab_helper.h" | |
| 11 #include "content/public/browser/navigation_handle.h" | |
| 12 #include "content/public/browser/render_frame_host.h" | |
| 13 #include "content/public/browser/resource_request_details.h" | |
| 14 #include "content/public/browser/web_contents.h" | |
| 15 #include "content/public/common/resource_type.h" | |
| 16 | |
| 17 using content::WebContents; | |
| 18 | |
| 19 namespace { | |
| 20 const char kWebContentsUserDataKey[] = | |
| 21 "web_contents_safe_browsing_navigation_observer"; | |
| 22 } // namespace | |
| 23 | |
| 24 namespace safe_browsing { | |
| 25 | |
| 26 // SafeBrowsingNavigationObserver::NavigationEvent----------------------------- | |
| 27 NavigationEvent::NavigationEvent() | |
| 28 : source_url(), | |
| 29 source_tab_id(-1), | |
| 30 source_main_frame_url(), | |
| 31 original_request_url(), | |
| 32 target_tab_id(-1), | |
| 33 frame_id(-1), | |
| 34 timestamp(base::Time::Now()), | |
| 35 is_user_initiated(false), | |
| 36 has_committed(false), | |
| 37 has_server_redirect(false), | |
| 38 actual_target_url() {} | |
| 39 | |
| 40 NavigationEvent::NavigationEvent(NavigationEvent&& nav_event) | |
| 41 : source_url(std::move(nav_event.source_url)), | |
| 42 source_tab_id(std::move(nav_event.source_tab_id)), | |
| 43 source_main_frame_url(std::move(nav_event.source_main_frame_url)), | |
| 44 original_request_url(std::move(nav_event.original_request_url)), | |
| 45 target_tab_id(std::move(nav_event.target_tab_id)), | |
| 46 frame_id(nav_event.frame_id), | |
| 47 timestamp(nav_event.timestamp), | |
| 48 is_user_initiated(nav_event.is_user_initiated), | |
| 49 has_committed(nav_event.has_committed), | |
| 50 has_server_redirect(nav_event.has_server_redirect), | |
| 51 actual_target_url(std::move(nav_event.actual_target_url)) {} | |
| 52 | |
| 53 NavigationEvent& NavigationEvent::operator=(NavigationEvent&& nav_event) { | |
| 54 source_url = std::move(nav_event.source_url); | |
| 55 source_tab_id = std::move(nav_event.source_tab_id); | |
| 56 source_main_frame_url = std::move(nav_event.source_main_frame_url); | |
| 57 original_request_url = std::move(nav_event.original_request_url); | |
| 58 target_tab_id = std::move(nav_event.target_tab_id); | |
| 59 frame_id = nav_event.frame_id; | |
| 60 timestamp = nav_event.timestamp; | |
| 61 is_user_initiated = nav_event.is_user_initiated; | |
| 62 has_committed = nav_event.has_committed; | |
| 63 has_server_redirect = nav_event.has_server_redirect; | |
| 64 actual_target_url = std::move(nav_event.actual_target_url); | |
| 65 return *this; | |
| 66 } | |
| 67 | |
| 68 NavigationEvent::~NavigationEvent() {} | |
| 69 | |
| 70 // SafeBrowsingNavigationObserver -------------------------------------------- | |
| 71 | |
| 72 // static | |
| 73 void SafeBrowsingNavigationObserver::MaybeCreateForWebContents( | |
| 74 content::WebContents* web_contents) { | |
| 75 if (FromWebContents(web_contents)) | |
| 76 return; | |
| 77 NOTIMPLEMENTED(); | |
| 78 // TODO(jialiul): This method will be called by TabHelpers::AttachTabHelpers. | |
| 79 // Complete this method when the entire class is ready. | |
| 80 } | |
| 81 | |
| 82 // static | |
| 83 SafeBrowsingNavigationObserver* SafeBrowsingNavigationObserver::FromWebContents( | |
| 84 content::WebContents* web_contents) { | |
| 85 return static_cast<SafeBrowsingNavigationObserver*>( | |
| 86 web_contents->GetUserData(kWebContentsUserDataKey)); | |
| 87 } | |
| 88 | |
| 89 SafeBrowsingNavigationObserver::SafeBrowsingNavigationObserver( | |
| 90 content::WebContents* contents, | |
| 91 const scoped_refptr<SafeBrowsingNavigationObserverManager>& manager) | |
| 92 : content::WebContentsObserver(contents), | |
| 93 manager_(manager), | |
| 94 has_user_gesture_(false), | |
| 95 last_user_gesture_timestamp_(base::Time()) {} | |
| 96 | |
| 97 SafeBrowsingNavigationObserver::~SafeBrowsingNavigationObserver() {} | |
| 98 | |
| 99 // Called when a navigation started in the WebContents. |navigation_handle| in | |
| 100 // parameter is unique to this navigation, which will appear in the following | |
| 101 // DidRedirectNavigation, and DidFinishNavigation too. | |
| 102 void SafeBrowsingNavigationObserver::DidStartNavigation( | |
| 103 content::NavigationHandle* navigation_handle) { | |
| 104 // If we already seen this navigation_handle before, no need to do anything. | |
| 105 // TODO(jialiul): Need to handle cases where two DidStartNavigation() called | |
| 106 // by the same navigation. | |
| 107 if (navigation_handle_map_.find(navigation_handle) != | |
| 108 navigation_handle_map_.end()) | |
| 109 return; | |
| 110 | |
| 111 // Construct a NavigationEvent based on available information in | |
| 112 // navigation_handle. | |
| 113 NavigationEvent nav_event; | |
| 114 content::RenderFrameHost* host = | |
| 115 navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId( | |
| 116 navigation_handle->GetFrameTreeNodeId()); | |
| 117 | |
| 118 // If there was URL previously committed in this render frame host, | |
|
Charlie Reis
2016/10/19 17:10:46
nit: in the current RenderFrameHost
Jialiu Lin
2016/10/21 02:38:38
Done.
| |
| 119 // set it as the source url of this navigation. Otherwise, this is the | |
| 120 // first url going to commit in this frame. We set navigation_handle's URL as | |
| 121 // the source url. | |
| 122 // TODO(jialiul): source_url will be inccorect when another frame is targeting | |
| 123 // this frame. Need to refine this logic after the true initiator details are | |
| 124 // added to NavigationHandle. | |
|
Charlie Reis
2016/10/19 17:10:45
Thanks. Can you add a reference to https://crbug.
Jialiu Lin
2016/10/21 02:38:38
Sure. Done.
| |
| 125 if (host && host->GetLastCommittedURL().is_valid()) { | |
| 126 nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef( | |
| 127 host->GetLastCommittedURL()); | |
| 128 } else { | |
| 129 nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef( | |
| 130 navigation_handle->GetURL()); | |
| 131 } | |
| 132 nav_event.original_request_url = | |
| 133 SafeBrowsingNavigationObserverManager::ClearEmptyRef( | |
| 134 navigation_handle->GetURL()); | |
| 135 nav_event.actual_target_url = nav_event.original_request_url; | |
| 136 | |
| 137 nav_event.source_tab_id = | |
| 138 SessionTabHelper::IdForTab(navigation_handle->GetWebContents()); | |
| 139 nav_event.timestamp = base::Time::Now(); | |
| 140 nav_event.frame_id = navigation_handle->GetFrameTreeNodeId(); | |
| 141 | |
| 142 if (navigation_handle->IsInMainFrame()) { | |
| 143 nav_event.source_main_frame_url = nav_event.source_url; | |
| 144 } else { | |
| 145 nav_event.source_main_frame_url = | |
| 146 SafeBrowsingNavigationObserverManager::ClearEmptyRef( | |
| 147 navigation_handle->GetWebContents()->GetLastCommittedURL()); | |
| 148 } | |
| 149 if ((has_user_gesture_ && | |
| 150 !SafeBrowsingNavigationObserverManager::IsUserGestureExpired( | |
| 151 last_user_gesture_timestamp_)) || | |
| 152 !navigation_handle->IsRendererInitiated()) { | |
| 153 nav_event.is_user_initiated = has_user_gesture_; | |
| 154 manager_->OnUserGestureConsumed(web_contents(), | |
| 155 last_user_gesture_timestamp_); | |
| 156 } | |
| 157 has_user_gesture_ = false; | |
| 158 navigation_handle_map_.insert( | |
| 159 std::make_pair(navigation_handle, std::move(nav_event))); | |
| 160 } | |
| 161 | |
| 162 void SafeBrowsingNavigationObserver::DidRedirectNavigation( | |
| 163 content::NavigationHandle* navigation_handle) { | |
| 164 // We should have already seen this navigation_handle in DidStartNavigation. | |
| 165 if (navigation_handle_map_.find(navigation_handle) == | |
|
Nathan Parker
2016/10/19 22:56:14
I'm not sure if this gets compiled out on release
Jialiu Lin
2016/10/21 02:38:38
Done.
| |
| 166 navigation_handle_map_.end()) | |
| 167 NOTREACHED(); | |
| 168 | |
| 169 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle]; | |
| 170 nav_event->has_server_redirect = true; | |
| 171 nav_event->actual_target_url = | |
| 172 SafeBrowsingNavigationObserverManager::ClearEmptyRef( | |
| 173 navigation_handle->GetURL()); | |
| 174 nav_event->timestamp = base::Time::Now(); | |
| 175 } | |
| 176 | |
| 177 void SafeBrowsingNavigationObserver::DidFinishNavigation( | |
| 178 content::NavigationHandle* navigation_handle) { | |
| 179 if (navigation_handle_map_.find(navigation_handle) == | |
| 180 navigation_handle_map_.end()) | |
| 181 NOTREACHED(); | |
| 182 | |
| 183 // If it is an error page, we ignore this navigation. | |
| 184 if (navigation_handle->IsErrorPage()) { | |
| 185 navigation_handle_map_.erase(navigation_handle); | |
| 186 return; | |
| 187 } | |
| 188 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle]; | |
| 189 | |
| 190 nav_event->has_committed = navigation_handle->HasCommitted(); | |
| 191 nav_event->target_tab_id = | |
| 192 SessionTabHelper::IdForTab(navigation_handle->GetWebContents()); | |
| 193 nav_event->timestamp = base::Time::Now(); | |
| 194 | |
| 195 GURL nav_event_key = nav_event->actual_target_url; | |
| 196 manager_->RecordNavigationEvent(nav_event_key, nav_event); | |
| 197 navigation_handle_map_.erase(navigation_handle); | |
| 198 } | |
| 199 | |
| 200 void SafeBrowsingNavigationObserver::DidGetResourceResponseStart( | |
| 201 const content::ResourceRequestDetails& details) { | |
| 202 // We only care about main frame and sub frame. | |
| 203 if (details.resource_type != content::RESOURCE_TYPE_MAIN_FRAME && | |
| 204 details.resource_type != content::RESOURCE_TYPE_SUB_FRAME) { | |
| 205 return; | |
| 206 } | |
| 207 if (!details.url.is_valid() || details.socket_address.IsEmpty()) | |
| 208 return; | |
| 209 | |
| 210 manager_->RecordHostToIpMapping(details.url.host(), | |
| 211 details.socket_address.host()); | |
| 212 } | |
| 213 | |
| 214 void SafeBrowsingNavigationObserver::DidGetUserInteraction( | |
| 215 const blink::WebInputEvent::Type type) { | |
| 216 last_user_gesture_timestamp_ = base::Time::Now(); | |
| 217 has_user_gesture_ = true; | |
| 218 // TODO (jialiul): Refine user gesture logic when DidOpenRequestedURL | |
| 219 // covers all retargetting cases. | |
| 220 manager_->RecordUserGestureForWebContents(web_contents(), | |
| 221 last_user_gesture_timestamp_); | |
| 222 } | |
| 223 | |
| 224 void SafeBrowsingNavigationObserver::WebContentsDestroyed() { | |
| 225 manager_->OnWebContentDestroyed(web_contents()); | |
| 226 web_contents()->RemoveUserData(kWebContentsUserDataKey); | |
| 227 // web_contents is null after this function. | |
| 228 } | |
| 229 | |
| 230 } // namespace safe_browsing | |
| OLD | NEW |