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