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" | |
| 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 |