| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/supervised_user/supervised_user_resource_throttle.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/memory/ptr_util.h" | |
| 9 #include "base/metrics/histogram_macros.h" | |
| 10 #include "chrome/browser/supervised_user/supervised_user_interstitial.h" | |
| 11 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" | |
| 12 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" | |
| 13 #include "content/public/browser/browser_thread.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" | |
| 18 | |
| 19 using content::BrowserThread; | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 // These values corresponds to SupervisedUserSafetyFilterResult in | |
| 24 // tools/metrics/histograms/histograms.xml. If you change anything here, make | |
| 25 // sure to also update histograms.xml accordingly. | |
| 26 enum { | |
| 27 FILTERING_BEHAVIOR_ALLOW = 1, | |
| 28 FILTERING_BEHAVIOR_ALLOW_UNCERTAIN, | |
| 29 FILTERING_BEHAVIOR_BLOCK_BLACKLIST, | |
| 30 FILTERING_BEHAVIOR_BLOCK_SAFESITES, | |
| 31 FILTERING_BEHAVIOR_BLOCK_MANUAL, | |
| 32 FILTERING_BEHAVIOR_BLOCK_DEFAULT, | |
| 33 FILTERING_BEHAVIOR_ALLOW_WHITELIST, | |
| 34 FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_ALLOW_WHITELIST | |
| 35 }; | |
| 36 const int kHistogramFilteringBehaviorSpacing = 100; | |
| 37 const int kHistogramPageTransitionMaxKnownValue = | |
| 38 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED); | |
| 39 const int kHistogramPageTransitionFallbackValue = | |
| 40 kHistogramFilteringBehaviorSpacing - 1; | |
| 41 const int kHistogramMax = 800; | |
| 42 | |
| 43 static_assert(kHistogramPageTransitionMaxKnownValue < | |
| 44 kHistogramPageTransitionFallbackValue, | |
| 45 "HistogramPageTransition MaxKnownValue must be < FallbackValue"); | |
| 46 static_assert(FILTERING_BEHAVIOR_MAX * kHistogramFilteringBehaviorSpacing + | |
| 47 kHistogramPageTransitionFallbackValue < kHistogramMax, | |
| 48 "Invalid HistogramMax value"); | |
| 49 | |
| 50 int GetHistogramValueForFilteringBehavior( | |
| 51 SupervisedUserURLFilter::FilteringBehavior behavior, | |
| 52 supervised_user_error_page::FilteringBehaviorReason reason, | |
| 53 bool uncertain) { | |
| 54 switch (behavior) { | |
| 55 case SupervisedUserURLFilter::ALLOW: | |
| 56 case SupervisedUserURLFilter::WARN: | |
| 57 if (reason == supervised_user_error_page::WHITELIST) | |
| 58 return FILTERING_BEHAVIOR_ALLOW_WHITELIST; | |
| 59 return uncertain ? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN | |
| 60 : FILTERING_BEHAVIOR_ALLOW; | |
| 61 case SupervisedUserURLFilter::BLOCK: | |
| 62 switch (reason) { | |
| 63 case supervised_user_error_page::BLACKLIST: | |
| 64 return FILTERING_BEHAVIOR_BLOCK_BLACKLIST; | |
| 65 case supervised_user_error_page::ASYNC_CHECKER: | |
| 66 return FILTERING_BEHAVIOR_BLOCK_SAFESITES; | |
| 67 case supervised_user_error_page::WHITELIST: | |
| 68 NOTREACHED(); | |
| 69 break; | |
| 70 case supervised_user_error_page::MANUAL: | |
| 71 return FILTERING_BEHAVIOR_BLOCK_MANUAL; | |
| 72 case supervised_user_error_page::DEFAULT: | |
| 73 return FILTERING_BEHAVIOR_BLOCK_DEFAULT; | |
| 74 case supervised_user_error_page::NOT_SIGNED_IN: | |
| 75 // Should never happen, only used for requests from Webview | |
| 76 NOTREACHED(); | |
| 77 } | |
| 78 case SupervisedUserURLFilter::INVALID: | |
| 79 NOTREACHED(); | |
| 80 } | |
| 81 return 0; | |
| 82 } | |
| 83 | |
| 84 int GetHistogramValueForTransitionType(ui::PageTransition transition_type) { | |
| 85 int value = | |
| 86 static_cast<int>(ui::PageTransitionStripQualifier(transition_type)); | |
| 87 if (0 <= value && value <= kHistogramPageTransitionMaxKnownValue) | |
| 88 return value; | |
| 89 NOTREACHED(); | |
| 90 return kHistogramPageTransitionFallbackValue; | |
| 91 } | |
| 92 | |
| 93 void RecordFilterResultEvent( | |
| 94 bool safesites_histogram, | |
| 95 SupervisedUserURLFilter::FilteringBehavior behavior, | |
| 96 supervised_user_error_page::FilteringBehaviorReason reason, | |
| 97 bool uncertain, | |
| 98 ui::PageTransition transition_type) { | |
| 99 int value = | |
| 100 GetHistogramValueForFilteringBehavior(behavior, reason, uncertain) * | |
| 101 kHistogramFilteringBehaviorSpacing + | |
| 102 GetHistogramValueForTransitionType(transition_type); | |
| 103 DCHECK_LT(value, kHistogramMax); | |
| 104 // 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 | |
| 106 // invocation and cache it in a static variable). | |
| 107 if (safesites_histogram) | |
| 108 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.SafetyFilter", value); | |
| 109 else | |
| 110 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value); | |
| 111 } | |
| 112 | |
| 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 | |
| 126 | |
| 127 // static | |
| 128 std::unique_ptr<SupervisedUserResourceThrottle> | |
| 129 SupervisedUserResourceThrottle::MaybeCreate( | |
| 130 const net::URLRequest* request, | |
| 131 content::ResourceType resource_type, | |
| 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; | |
| 137 | |
| 138 // Can't use base::MakeUnique because the constructor is private. | |
| 139 return base::WrapUnique( | |
| 140 new SupervisedUserResourceThrottle(request, url_filter)); | |
| 141 } | |
| 142 | |
| 143 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle( | |
| 144 const net::URLRequest* request, | |
| 145 const SupervisedUserURLFilter* url_filter) | |
| 146 : request_(request), | |
| 147 url_filter_(url_filter), | |
| 148 deferred_(false), | |
| 149 behavior_(SupervisedUserURLFilter::INVALID), | |
| 150 weak_ptr_factory_(this) {} | |
| 151 | |
| 152 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {} | |
| 153 | |
| 154 void SupervisedUserResourceThrottle::CheckURL(const GURL& url, bool* defer) { | |
| 155 deferred_ = false; | |
| 156 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); | |
| 157 bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( | |
| 158 url, | |
| 159 base::Bind(&SupervisedUserResourceThrottle::OnCheckDone, | |
| 160 weak_ptr_factory_.GetWeakPtr(), url)); | |
| 161 DCHECK_EQ(got_result, behavior_ != SupervisedUserURLFilter::INVALID); | |
| 162 // If we got a "not blocked" result synchronously, don't defer. | |
| 163 *defer = deferred_ = !got_result || | |
| 164 (behavior_ == SupervisedUserURLFilter::BLOCK); | |
| 165 if (got_result) | |
| 166 behavior_ = SupervisedUserURLFilter::INVALID; | |
| 167 } | |
| 168 | |
| 169 void SupervisedUserResourceThrottle::ShowInterstitial( | |
| 170 const GURL& url, | |
| 171 supervised_user_error_page::FilteringBehaviorReason reason) { | |
| 172 const content::ResourceRequestInfo* info = | |
| 173 content::ResourceRequestInfo::ForRequest(request_); | |
| 174 BrowserThread::PostTask( | |
| 175 BrowserThread::UI, FROM_HERE, | |
| 176 base::Bind(&SupervisedUserNavigationObserver::OnRequestBlocked, | |
| 177 info->GetWebContentsGetterForRequest(), url, reason, | |
| 178 ResultTrampoline(base::Bind( | |
| 179 &SupervisedUserResourceThrottle::OnInterstitialResult, | |
| 180 weak_ptr_factory_.GetWeakPtr())))); | |
| 181 } | |
| 182 | |
| 183 void SupervisedUserResourceThrottle::WillStartRequest(bool* defer) { | |
| 184 CheckURL(request_->url(), defer); | |
| 185 } | |
| 186 | |
| 187 void SupervisedUserResourceThrottle::WillRedirectRequest( | |
| 188 const net::RedirectInfo& redirect_info, | |
| 189 bool* defer) { | |
| 190 CheckURL(redirect_info.new_url, defer); | |
| 191 } | |
| 192 | |
| 193 const char* SupervisedUserResourceThrottle::GetNameForLogging() const { | |
| 194 return "SupervisedUserResourceThrottle"; | |
| 195 } | |
| 196 | |
| 197 void SupervisedUserResourceThrottle::OnCheckDone( | |
| 198 const GURL& url, | |
| 199 SupervisedUserURLFilter::FilteringBehavior behavior, | |
| 200 supervised_user_error_page::FilteringBehaviorReason reason, | |
| 201 bool uncertain) { | |
| 202 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); | |
| 203 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded. | |
| 204 if (!deferred_) | |
| 205 behavior_ = behavior; | |
| 206 | |
| 207 ui::PageTransition transition = | |
| 208 content::ResourceRequestInfo::ForRequest(request_)->GetPageTransition(); | |
| 209 | |
| 210 RecordFilterResultEvent(false, behavior, reason, uncertain, transition); | |
| 211 | |
| 212 // If both the static blacklist and the async checker are enabled, also record | |
| 213 // SafeSites-only UMA events. | |
| 214 if (url_filter_->HasBlacklist() && url_filter_->HasAsyncURLChecker() && | |
| 215 (reason == supervised_user_error_page::ASYNC_CHECKER || | |
| 216 reason == supervised_user_error_page::BLACKLIST)) { | |
| 217 RecordFilterResultEvent(true, behavior, reason, uncertain, transition); | |
| 218 } | |
| 219 | |
| 220 if (behavior == SupervisedUserURLFilter::BLOCK) | |
| 221 ShowInterstitial(url, reason); | |
| 222 else if (deferred_) | |
| 223 Resume(); | |
| 224 } | |
| 225 | |
| 226 void SupervisedUserResourceThrottle::OnInterstitialResult( | |
| 227 bool continue_request) { | |
| 228 if (continue_request) | |
| 229 Resume(); | |
| 230 else | |
| 231 Cancel(); | |
| 232 } | |
| OLD | NEW |