OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/supervised_user/supervised_user_resource_throttle.h" | 5 #include "chrome/browser/supervised_user/supervised_user_navigation_throttle.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | |
9 #include "base/logging.h" | |
8 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
9 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
12 #include "base/single_thread_task_runner.h" | |
13 #include "base/threading/thread_task_runner_handle.h" | |
10 #include "chrome/browser/supervised_user/supervised_user_interstitial.h" | 14 #include "chrome/browser/supervised_user/supervised_user_interstitial.h" |
11 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" | 15 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" |
16 #include "chrome/browser/supervised_user/supervised_user_service.h" | |
17 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" | |
12 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" | 18 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" |
13 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/navigation_handle.h" |
14 #include "content/public/browser/resource_request_info.h" | |
15 #include "net/url_request/redirect_info.h" | |
16 #include "net/url_request/url_request.h" | |
17 #include "ui/base/page_transition_types.h" | 20 #include "ui/base/page_transition_types.h" |
18 | 21 #include "url/gurl.h" |
19 using content::BrowserThread; | |
20 | 22 |
21 namespace { | 23 namespace { |
22 | 24 |
23 // These values corresponds to SupervisedUserSafetyFilterResult in | 25 // These values corresponds to SupervisedUserSafetyFilterResult in |
24 // tools/metrics/histograms/histograms.xml. If you change anything here, make | 26 // tools/metrics/histograms/histograms.xml. If you change anything here, make |
25 // sure to also update histograms.xml accordingly. | 27 // sure to also update histograms.xml accordingly. |
26 enum { | 28 enum { |
27 FILTERING_BEHAVIOR_ALLOW = 1, | 29 FILTERING_BEHAVIOR_ALLOW = 1, |
28 FILTERING_BEHAVIOR_ALLOW_UNCERTAIN, | 30 FILTERING_BEHAVIOR_ALLOW_UNCERTAIN, |
29 FILTERING_BEHAVIOR_BLOCK_BLACKLIST, | 31 FILTERING_BEHAVIOR_BLOCK_BLACKLIST, |
30 FILTERING_BEHAVIOR_BLOCK_SAFESITES, | 32 FILTERING_BEHAVIOR_BLOCK_SAFESITES, |
31 FILTERING_BEHAVIOR_BLOCK_MANUAL, | 33 FILTERING_BEHAVIOR_BLOCK_MANUAL, |
32 FILTERING_BEHAVIOR_BLOCK_DEFAULT, | 34 FILTERING_BEHAVIOR_BLOCK_DEFAULT, |
33 FILTERING_BEHAVIOR_ALLOW_WHITELIST, | 35 FILTERING_BEHAVIOR_ALLOW_WHITELIST, |
34 FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_ALLOW_WHITELIST | 36 FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_ALLOW_WHITELIST |
35 }; | 37 }; |
36 const int kHistogramFilteringBehaviorSpacing = 100; | 38 const int kHistogramFilteringBehaviorSpacing = 100; |
37 const int kHistogramPageTransitionMaxKnownValue = | 39 const int kHistogramPageTransitionMaxKnownValue = |
38 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED); | 40 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED); |
39 const int kHistogramPageTransitionFallbackValue = | 41 const int kHistogramPageTransitionFallbackValue = |
40 kHistogramFilteringBehaviorSpacing - 1; | 42 kHistogramFilteringBehaviorSpacing - 1; |
41 const int kHistogramMax = 800; | 43 const int kHistogramMax = 800; |
42 | 44 |
43 static_assert(kHistogramPageTransitionMaxKnownValue < | 45 static_assert(kHistogramPageTransitionMaxKnownValue < |
44 kHistogramPageTransitionFallbackValue, | 46 kHistogramPageTransitionFallbackValue, |
45 "HistogramPageTransition MaxKnownValue must be < FallbackValue"); | 47 "HistogramPageTransition MaxKnownValue must be < FallbackValue"); |
46 static_assert(FILTERING_BEHAVIOR_MAX * kHistogramFilteringBehaviorSpacing + | 48 static_assert(FILTERING_BEHAVIOR_MAX * kHistogramFilteringBehaviorSpacing + |
47 kHistogramPageTransitionFallbackValue < kHistogramMax, | 49 kHistogramPageTransitionFallbackValue < |
50 kHistogramMax, | |
48 "Invalid HistogramMax value"); | 51 "Invalid HistogramMax value"); |
49 | 52 |
50 int GetHistogramValueForFilteringBehavior( | 53 int GetHistogramValueForFilteringBehavior( |
51 SupervisedUserURLFilter::FilteringBehavior behavior, | 54 SupervisedUserURLFilter::FilteringBehavior behavior, |
52 supervised_user_error_page::FilteringBehaviorReason reason, | 55 supervised_user_error_page::FilteringBehaviorReason reason, |
53 bool uncertain) { | 56 bool uncertain) { |
54 switch (behavior) { | 57 switch (behavior) { |
55 case SupervisedUserURLFilter::ALLOW: | 58 case SupervisedUserURLFilter::ALLOW: |
56 case SupervisedUserURLFilter::WARN: | 59 case SupervisedUserURLFilter::WARN: |
57 if (reason == supervised_user_error_page::WHITELIST) | 60 if (reason == supervised_user_error_page::WHITELIST) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 DCHECK_LT(value, kHistogramMax); | 106 DCHECK_LT(value, kHistogramMax); |
104 // Note: We can't pass in the histogram name as a parameter to this function | 107 // Note: We can't pass in the histogram name as a parameter to this function |
105 // because of how the macro works (look up the histogram on the first | 108 // because of how the macro works (look up the histogram on the first |
106 // invocation and cache it in a static variable). | 109 // invocation and cache it in a static variable). |
107 if (safesites_histogram) | 110 if (safesites_histogram) |
108 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.SafetyFilter", value); | 111 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.SafetyFilter", value); |
109 else | 112 else |
110 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value); | 113 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value); |
111 } | 114 } |
112 | 115 |
113 // Helper function to wrap a given callback in one that will post it to the | |
114 // IO thread. | |
115 base::Callback<void(bool)> ResultTrampoline( | |
116 const base::Callback<void(bool)>& callback) { | |
117 return base::Bind( | |
118 [](const base::Callback<void(bool)>& callback, bool result) { | |
119 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
120 base::Bind(callback, result)); | |
121 }, | |
122 callback); | |
123 } | |
124 | |
125 } // namespace | 116 } // namespace |
126 | 117 |
127 // static | 118 // static |
128 std::unique_ptr<SupervisedUserResourceThrottle> | 119 std::unique_ptr<SupervisedUserNavigationThrottle> |
129 SupervisedUserResourceThrottle::MaybeCreate( | 120 SupervisedUserNavigationThrottle::MaybeCreateThrottleFor( |
130 const net::URLRequest* request, | 121 content::NavigationHandle* navigation_handle) { |
131 content::ResourceType resource_type, | 122 if (!navigation_handle->IsInMainFrame()) |
132 const SupervisedUserURLFilter* url_filter) { | |
133 // Only treat main frame requests (ignoring subframes and subresources). | |
134 bool is_main_frame = resource_type == content::RESOURCE_TYPE_MAIN_FRAME; | |
135 if (!is_main_frame) | |
136 return nullptr; | 123 return nullptr; |
137 | |
138 // Can't use base::MakeUnique because the constructor is private. | |
Marc Treib
2017/03/28 10:22:58
nit: Leave the comment?
mmenke
2017/03/28 17:55:05
Thanks for catching this, done.
| |
139 return base::WrapUnique( | 124 return base::WrapUnique( |
140 new SupervisedUserResourceThrottle(request, url_filter)); | 125 new SupervisedUserNavigationThrottle(navigation_handle)); |
141 } | 126 } |
142 | 127 |
143 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle( | 128 SupervisedUserNavigationThrottle::SupervisedUserNavigationThrottle( |
144 const net::URLRequest* request, | 129 content::NavigationHandle* navigation_handle) |
145 const SupervisedUserURLFilter* url_filter) | 130 : NavigationThrottle(navigation_handle), |
146 : request_(request), | 131 url_filter_(SupervisedUserServiceFactory::GetForProfile( |
147 url_filter_(url_filter), | 132 navigation_handle->GetWebContents()->GetBrowserContext()) |
133 ->GetURLFilter()), | |
148 deferred_(false), | 134 deferred_(false), |
149 behavior_(SupervisedUserURLFilter::INVALID), | 135 behavior_(SupervisedUserURLFilter::INVALID), |
150 weak_ptr_factory_(this) {} | 136 weak_ptr_factory_(this) {} |
151 | 137 |
152 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {} | 138 SupervisedUserNavigationThrottle::~SupervisedUserNavigationThrottle() {} |
153 | 139 |
154 void SupervisedUserResourceThrottle::CheckURL(const GURL& url, bool* defer) { | 140 content::NavigationThrottle::ThrottleCheckResult |
141 SupervisedUserNavigationThrottle::CheckURL() { | |
155 deferred_ = false; | 142 deferred_ = false; |
156 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); | 143 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); |
144 GURL url = navigation_handle()->GetURL(); | |
157 bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( | 145 bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( |
158 url, | 146 url, base::Bind(&SupervisedUserNavigationThrottle::OnCheckDone, |
159 base::Bind(&SupervisedUserResourceThrottle::OnCheckDone, | 147 weak_ptr_factory_.GetWeakPtr(), url)); |
160 weak_ptr_factory_.GetWeakPtr(), url)); | |
161 DCHECK_EQ(got_result, behavior_ != SupervisedUserURLFilter::INVALID); | 148 DCHECK_EQ(got_result, behavior_ != SupervisedUserURLFilter::INVALID); |
162 // If we got a "not blocked" result synchronously, don't defer. | 149 // If we got a "not blocked" result synchronously, don't defer. |
163 *defer = deferred_ = !got_result || | 150 deferred_ = !got_result || (behavior_ == SupervisedUserURLFilter::BLOCK); |
164 (behavior_ == SupervisedUserURLFilter::BLOCK); | |
165 if (got_result) | 151 if (got_result) |
166 behavior_ = SupervisedUserURLFilter::INVALID; | 152 behavior_ = SupervisedUserURLFilter::INVALID; |
153 if (deferred_) | |
154 return ThrottleCheckResult::DEFER; | |
155 return ThrottleCheckResult::PROCEED; | |
167 } | 156 } |
168 | 157 |
169 void SupervisedUserResourceThrottle::ShowInterstitial( | 158 void SupervisedUserNavigationThrottle::ShowInterstitial( |
170 const GURL& url, | 159 const GURL& url, |
171 supervised_user_error_page::FilteringBehaviorReason reason) { | 160 supervised_user_error_page::FilteringBehaviorReason reason) { |
172 const content::ResourceRequestInfo* info = | 161 // Don't show interstitial synchronously - it doesn't seem like a good idea to |
173 content::ResourceRequestInfo::ForRequest(request_); | 162 // show an interstitial right in the middle of a call into a |
174 BrowserThread::PostTask( | 163 // NavigationThrottle. This also lets OnInterstitialResult to be invoked |
175 BrowserThread::UI, FROM_HERE, | 164 // synchronously, once a callback is passed into the |
176 base::Bind(&SupervisedUserNavigationObserver::OnRequestBlocked, | 165 // SupervisedUserNavigationObserver. |
177 info->GetWebContentsGetterForRequest(), url, reason, | 166 base::ThreadTaskRunnerHandle::Get()->PostTask( |
178 ResultTrampoline(base::Bind( | 167 FROM_HERE, |
179 &SupervisedUserResourceThrottle::OnInterstitialResult, | 168 base::Bind(&SupervisedUserNavigationThrottle::ShowInterstitialAsync, |
180 weak_ptr_factory_.GetWeakPtr())))); | 169 weak_ptr_factory_.GetWeakPtr(), reason)); |
181 } | 170 } |
182 | 171 |
183 void SupervisedUserResourceThrottle::WillStartRequest(bool* defer) { | 172 void SupervisedUserNavigationThrottle::ShowInterstitialAsync( |
184 CheckURL(request_->url(), defer); | 173 supervised_user_error_page::FilteringBehaviorReason reason) { |
174 // May not yet have been set when ShowInterstitial was called, but should have | |
175 // been set by the time this is invoked. | |
176 DCHECK(deferred_); | |
177 | |
178 SupervisedUserNavigationObserver::OnRequestBlocked( | |
179 navigation_handle()->GetWebContents(), navigation_handle()->GetURL(), | |
180 reason, | |
181 base::Bind(&SupervisedUserNavigationThrottle::OnInterstitialResult, | |
182 weak_ptr_factory_.GetWeakPtr())); | |
185 } | 183 } |
186 | 184 |
187 void SupervisedUserResourceThrottle::WillRedirectRequest( | 185 content::NavigationThrottle::ThrottleCheckResult |
188 const net::RedirectInfo& redirect_info, | 186 SupervisedUserNavigationThrottle::WillStartRequest() { |
189 bool* defer) { | 187 return CheckURL(); |
190 CheckURL(redirect_info.new_url, defer); | |
191 } | 188 } |
192 | 189 |
193 const char* SupervisedUserResourceThrottle::GetNameForLogging() const { | 190 content::NavigationThrottle::ThrottleCheckResult |
194 return "SupervisedUserResourceThrottle"; | 191 SupervisedUserNavigationThrottle::WillRedirectRequest() { |
192 return CheckURL(); | |
195 } | 193 } |
196 | 194 |
197 void SupervisedUserResourceThrottle::OnCheckDone( | 195 void SupervisedUserNavigationThrottle::OnCheckDone( |
198 const GURL& url, | 196 const GURL& url, |
199 SupervisedUserURLFilter::FilteringBehavior behavior, | 197 SupervisedUserURLFilter::FilteringBehavior behavior, |
200 supervised_user_error_page::FilteringBehaviorReason reason, | 198 supervised_user_error_page::FilteringBehaviorReason reason, |
201 bool uncertain) { | 199 bool uncertain) { |
202 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); | 200 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); |
203 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded. | 201 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded. |
204 if (!deferred_) | 202 if (!deferred_) |
205 behavior_ = behavior; | 203 behavior_ = behavior; |
206 | 204 |
207 ui::PageTransition transition = | 205 ui::PageTransition transition = navigation_handle()->GetPageTransition(); |
208 content::ResourceRequestInfo::ForRequest(request_)->GetPageTransition(); | |
209 | 206 |
210 RecordFilterResultEvent(false, behavior, reason, uncertain, transition); | 207 RecordFilterResultEvent(false, behavior, reason, uncertain, transition); |
211 | 208 |
212 // If both the static blacklist and the async checker are enabled, also record | 209 // If both the static blacklist and the async checker are enabled, also record |
213 // SafeSites-only UMA events. | 210 // SafeSites-only UMA events. |
214 if (url_filter_->HasBlacklist() && url_filter_->HasAsyncURLChecker() && | 211 if (url_filter_->HasBlacklist() && url_filter_->HasAsyncURLChecker() && |
215 (reason == supervised_user_error_page::ASYNC_CHECKER || | 212 (reason == supervised_user_error_page::ASYNC_CHECKER || |
216 reason == supervised_user_error_page::BLACKLIST)) { | 213 reason == supervised_user_error_page::BLACKLIST)) { |
217 RecordFilterResultEvent(true, behavior, reason, uncertain, transition); | 214 RecordFilterResultEvent(true, behavior, reason, uncertain, transition); |
218 } | 215 } |
219 | 216 |
220 if (behavior == SupervisedUserURLFilter::BLOCK) | 217 if (behavior == SupervisedUserURLFilter::BLOCK) |
221 ShowInterstitial(url, reason); | 218 ShowInterstitial(url, reason); |
222 else if (deferred_) | 219 else if (deferred_) |
223 Resume(); | 220 Resume(); |
224 } | 221 } |
225 | 222 |
226 void SupervisedUserResourceThrottle::OnInterstitialResult( | 223 void SupervisedUserNavigationThrottle::OnInterstitialResult( |
227 bool continue_request) { | 224 bool continue_request) { |
228 if (continue_request) | 225 if (continue_request) |
229 Resume(); | 226 Resume(); |
230 else | 227 else |
231 Cancel(); | 228 Cancel(); |
232 } | 229 } |
230 | |
231 void SupervisedUserNavigationThrottle::Resume() { | |
232 DCHECK(deferred_); | |
233 deferred_ = false; | |
234 navigation_handle()->Resume(); | |
235 } | |
236 | |
237 void SupervisedUserNavigationThrottle::Cancel() { | |
238 DCHECK(deferred_); | |
239 deferred_ = false; | |
240 navigation_handle()->CancelDeferredNavigation(CANCEL); | |
241 } | |
OLD | NEW |