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

Side by Side Diff: chrome/browser/safe_browsing/safe_browsing_navigation_observer.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 unified diff | Download patch
OLDNEW
(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_main_frame_url(),
30 original_request_url(),
31 destination_url(),
32 source_tab_id(-1),
33 target_tab_id(-1),
34 frame_id(-1),
35 last_updated(base::Time::Now()),
36 is_user_initiated(false),
37 has_committed(false),
38 has_server_redirect(false) {}
39
40 NavigationEvent::NavigationEvent(NavigationEvent&& nav_event)
41 : source_url(std::move(nav_event.source_url)),
42 source_main_frame_url(std::move(nav_event.source_main_frame_url)),
43 original_request_url(std::move(nav_event.original_request_url)),
44 destination_url(std::move(nav_event.destination_url)),
45 source_tab_id(std::move(nav_event.source_tab_id)),
46 target_tab_id(std::move(nav_event.target_tab_id)),
47 frame_id(nav_event.frame_id),
48 last_updated(nav_event.last_updated),
49 is_user_initiated(nav_event.is_user_initiated),
50 has_committed(nav_event.has_committed),
51 has_server_redirect(nav_event.has_server_redirect) {}
52
53 NavigationEvent& NavigationEvent::operator=(NavigationEvent&& nav_event) {
54 source_url = std::move(nav_event.source_url);
55 source_main_frame_url = std::move(nav_event.source_main_frame_url);
56 original_request_url = std::move(nav_event.original_request_url);
57 destination_url = std::move(nav_event.destination_url);
58 source_tab_id = nav_event.source_tab_id;
59 target_tab_id = nav_event.target_tab_id;
60 frame_id = nav_event.frame_id;
61 last_updated = nav_event.last_updated;
62 is_user_initiated = nav_event.is_user_initiated;
63 has_committed = nav_event.has_committed;
64 has_server_redirect = nav_event.has_server_redirect;
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 // TODO(jialiul): This method will be called by TabHelpers::AttachTabHelpers.
78 // Complete this method when the entire class is ready.
79 NOTIMPLEMENTED();
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 starts in the WebContents. |navigation_handle|
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 NavigationEvent nav_event;
105 auto it = navigation_handle_map_.find(navigation_handle);
106 // It is possible to see multiple DidStartNavigation(..) with the same
107 // navigation_handle (e.g. cross-process transfer). If that's the case,
108 // we need to copy the is_user_initiated field.
109 if (it != navigation_handle_map_.end()) {
110 nav_event.is_user_initiated = it->second.is_user_initiated;
111 } else {
112 // If this is the first time we see this navigation_handle, create a new
113 // NavigationEvent, and decide if it is triggered by user.
114 if ((has_user_gesture_ &&
115 !SafeBrowsingNavigationObserverManager::IsUserGestureExpired(
116 last_user_gesture_timestamp_)) ||
117 !navigation_handle->IsRendererInitiated()) {
118 nav_event.is_user_initiated = has_user_gesture_;
119 manager_->OnUserGestureConsumed(web_contents(),
120 last_user_gesture_timestamp_);
121 }
122 has_user_gesture_ = false;
123 }
124
125 // All the other fields are reconstructed based on current content of
126 // navigation_handle.
127 nav_event.frame_id = navigation_handle->GetFrameTreeNodeId();
128
129 // If there was a URL previously committed in the current RenderFrameHost,
130 // set it as the source url of this navigation. Otherwise, this is the
131 // first url going to commit in this frame. We set navigation_handle's URL as
132 // the source url.
133 // TODO(jialiul): source_url, source_tab_id, and source_main_frame_url may be
134 // incorrect when another frame is targeting this frame. Need to refine this
135 // logic after the true initiator details are added to NavigationHandle
136 // (https://crbug.com/651895).
137 content::RenderFrameHost* current_frame_host =
138 navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId(
139 nav_event.frame_id);
140 if (current_frame_host &&
141 current_frame_host->GetLastCommittedURL().is_valid()) {
142 nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef(
143 current_frame_host->GetLastCommittedURL());
144 }
145 nav_event.original_request_url =
146 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
147 navigation_handle->GetURL());
148 nav_event.destination_url = nav_event.original_request_url;
149
150 nav_event.source_tab_id =
151 SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
152
153 if (navigation_handle->IsInMainFrame()) {
154 nav_event.source_main_frame_url = nav_event.source_url;
155 } else {
156 nav_event.source_main_frame_url =
157 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
158 navigation_handle->GetWebContents()->GetLastCommittedURL());
159 }
160 navigation_handle_map_[navigation_handle] = std::move(nav_event);
161 }
162
163 void SafeBrowsingNavigationObserver::DidRedirectNavigation(
164 content::NavigationHandle* navigation_handle) {
165 // We should have already seen this navigation_handle in DidStartNavigation.
166 if (navigation_handle_map_.find(navigation_handle) ==
167 navigation_handle_map_.end()) {
168 NOTREACHED();
169 return;
170 }
171
172 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
173 nav_event->has_server_redirect = true;
174 nav_event->destination_url =
175 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
176 navigation_handle->GetURL());
177 nav_event->last_updated = base::Time::Now();
178 }
179
180 void SafeBrowsingNavigationObserver::DidFinishNavigation(
181 content::NavigationHandle* navigation_handle) {
182 if (navigation_handle_map_.find(navigation_handle) ==
183 navigation_handle_map_.end()) {
184 NOTREACHED();
185 return;
186 }
187
188 // If it is an error page, we ignore this navigation.
189 if (navigation_handle->IsErrorPage()) {
190 navigation_handle_map_.erase(navigation_handle);
191 return;
192 }
193 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
194
195 nav_event->has_committed = navigation_handle->HasCommitted();
196 nav_event->target_tab_id =
197 SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
198 nav_event->last_updated = base::Time::Now();
199
200 manager_->RecordNavigationEvent(nav_event->destination_url, nav_event);
201 navigation_handle_map_.erase(navigation_handle);
202 }
203
204 void SafeBrowsingNavigationObserver::DidGetResourceResponseStart(
205 const content::ResourceRequestDetails& details) {
206 // We only care about main frame and sub frame.
207 if (details.resource_type != content::RESOURCE_TYPE_MAIN_FRAME &&
208 details.resource_type != content::RESOURCE_TYPE_SUB_FRAME) {
209 return;
210 }
211 if (!details.url.is_valid() || details.socket_address.IsEmpty())
212 return;
213
214 manager_->RecordHostToIpMapping(details.url.host(),
215 details.socket_address.host());
216 }
217
218 void SafeBrowsingNavigationObserver::DidGetUserInteraction(
219 const blink::WebInputEvent::Type type) {
220 last_user_gesture_timestamp_ = base::Time::Now();
221 has_user_gesture_ = true;
222 // TODO (jialiul): Refine user gesture logic when DidOpenRequestedURL
223 // covers all retargetting cases.
224 manager_->RecordUserGestureForWebContents(web_contents(),
225 last_user_gesture_timestamp_);
226 }
227
228 void SafeBrowsingNavigationObserver::WebContentsDestroyed() {
229 manager_->OnWebContentDestroyed(web_contents());
230 web_contents()->RemoveUserData(kWebContentsUserDataKey);
231 // web_contents is null after this function.
232 }
233
234 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698