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

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: make all bots happy Created 4 years, 2 months 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_tab_id(-1),
30 source_main_frame_url(),
31 original_request_url(),
32 target_tab_id(-1),
33 frame_id(-1),
34 last_updated(base::Time::Now()),
35 is_user_initiated(false),
36 has_committed(false),
37 has_server_redirect(false),
38 destination_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 last_updated(nav_event.last_updated),
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 destination_url(std::move(nav_event.destination_url)) {}
52
53 NavigationEvent& NavigationEvent::operator=(NavigationEvent&& nav_event) {
54 source_url = std::move(nav_event.source_url);
55 source_tab_id = 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 = nav_event.target_tab_id;
59 frame_id = nav_event.frame_id;
60 last_updated = nav_event.last_updated;
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 destination_url = std::move(nav_event.destination_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.
Charlie Reis 2016/10/25 04:52:26 nit: TODO above NOTIMPLEMENTED
Jialiu Lin 2016/10/27 02:15:19 Done.
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
Charlie Reis 2016/10/25 04:52:26 nit: s/started/starts/ nit: s/in parameter/paramet
Jialiu Lin 2016/10/27 02:15:19 Done.
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 DidStartNaivgation(..) with the same
Charlie Reis 2016/10/25 04:52:26 nit: multiple DidStartNavigation calls (Note the "
Jialiu Lin 2016/10/27 02:15:19 Good eye!
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 content::RenderFrameHost* current_frame_host =
Charlie Reis 2016/10/25 04:52:26 nit: Move this declaration under the comment below
Jialiu Lin 2016/10/27 02:15:19 Done.
129 navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId(
130 nav_event.frame_id);
131
132 // If there was URL previously committed in the current RenderFrameHost,
Charlie Reis 2016/10/25 04:52:26 nit: a URL
Jialiu Lin 2016/10/27 02:15:19 Done.
133 // set it as the source url of this navigation. Otherwise, this is the
134 // first url going to commit in this frame. We set navigation_handle's URL as
135 // the source url.
136 // TODO(jialiul): source_url will be inccorect when another frame is targeting
Charlie Reis 2016/10/25 04:52:26 nit: incorrect Maybe also mention source_tab_id a
Jialiu Lin 2016/10/27 02:15:20 Yes, indeed. Comment refined.
137 // this frame. Need to refine this logic after the true initiator details are
138 // added to NavigationHandle (https://crbug.com/651895).
139 if (current_frame_host &&
140 current_frame_host->GetLastCommittedURL().is_valid()) {
141 nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef(
142 current_frame_host->GetLastCommittedURL());
143 } else {
144 nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearEmptyRef(
145 navigation_handle->GetURL());
Charlie Reis 2016/10/25 04:52:26 I'm curious, is there anything that depends on the
Jialiu Lin 2016/10/27 02:15:19 Make sense.
146 }
147 nav_event.original_request_url =
148 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
149 navigation_handle->GetURL());
150 nav_event.destination_url = nav_event.original_request_url;
151
152 nav_event.source_tab_id =
153 SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
154
155 if (navigation_handle->IsInMainFrame()) {
156 nav_event.source_main_frame_url = nav_event.source_url;
157 } else {
158 nav_event.source_main_frame_url =
159 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
160 navigation_handle->GetWebContents()->GetLastCommittedURL());
161 }
162 navigation_handle_map_[navigation_handle] = std::move(nav_event);
163 }
164
165 void SafeBrowsingNavigationObserver::DidRedirectNavigation(
166 content::NavigationHandle* navigation_handle) {
167 // We should have already seen this navigation_handle in DidStartNavigation.
168 DCHECK(navigation_handle_map_.find(navigation_handle) !=
169 navigation_handle_map_.end());
Charlie Reis 2016/10/25 04:52:26 You might want to rephrase this to a if (...) { NO
Jialiu Lin 2016/10/27 02:15:19 Done.
170
171 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
172 nav_event->has_server_redirect = true;
173 nav_event->destination_url =
174 SafeBrowsingNavigationObserverManager::ClearEmptyRef(
175 navigation_handle->GetURL());
176 nav_event->last_updated = base::Time::Now();
177 }
178
179 void SafeBrowsingNavigationObserver::DidFinishNavigation(
180 content::NavigationHandle* navigation_handle) {
181 DCHECK(navigation_handle_map_.find(navigation_handle) !=
182 navigation_handle_map_.end());
183
184 // If it is an error page, we ignore this navigation.
185 if (navigation_handle->IsErrorPage()) {
186 navigation_handle_map_.erase(navigation_handle);
187 return;
188 }
189 NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
190
191 nav_event->has_committed = navigation_handle->HasCommitted();
192 nav_event->target_tab_id =
193 SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
194 nav_event->last_updated = base::Time::Now();
195
196 manager_->RecordNavigationEvent(nav_event->destination_url, 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698