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.
5 #include "chrome/browser/supervised_user/supervised_user_resource_throttle.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/browser/supervised_user/supervised_user_interstitial.h"
10 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
11 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/resource_controller.h"
14 #include "content/public/browser/resource_request_info.h"
15 #include "net/url_request/url_request.h"
16 #include "ui/base/page_transition_types.h"
18 using content::BrowserThread;
22 // These values corresponds to SupervisedUserSafetyFilterResult in
23 // tools/metrics/histograms/histograms.xml. If you change anything here, make
24 // sure to also update histograms.xml accordingly.
26 FILTERING_BEHAVIOR_ALLOW = 1,
27 FILTERING_BEHAVIOR_ALLOW_UNCERTAIN,
28 FILTERING_BEHAVIOR_BLOCK_BLACKLIST,
29 FILTERING_BEHAVIOR_BLOCK_SAFESITES,
30 FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_BLOCK_SAFESITES
32 const int kHistogramFilteringBehaviorSpacing = 100;
33 const int kHistogramPageTransitionMaxKnownValue =
34 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED);
35 const int kHistogramPageTransitionFallbackValue =
36 kHistogramFilteringBehaviorSpacing - 1;
37 const int kHistogramMax = 500;
39 static_assert(kHistogramPageTransitionMaxKnownValue <
40 kHistogramPageTransitionFallbackValue,
41 "HistogramPageTransition MaxKnownValue must be < FallbackValue");
42 static_assert(FILTERING_BEHAVIOR_MAX * kHistogramFilteringBehaviorSpacing +
43 kHistogramPageTransitionFallbackValue < kHistogramMax,
44 "Invalid HistogramMax value");
46 int GetHistogramValueForFilteringBehavior(
47 SupervisedUserURLFilter::FilteringBehavior behavior,
48 SupervisedUserURLFilter::FilteringBehaviorSource source,
50 // Since we're only interested in statistics about the blacklist and
51 // SafeSites, count everything that got through to the default fallback
52 // behavior as ALLOW (made it through all the filters!).
53 if (source == SupervisedUserURLFilter::DEFAULT)
54 behavior = SupervisedUserURLFilter::ALLOW;
57 case SupervisedUserURLFilter::ALLOW:
58 return uncertain ? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN
59 : FILTERING_BEHAVIOR_ALLOW;
60 case SupervisedUserURLFilter::BLOCK:
61 if (source == SupervisedUserURLFilter::BLACKLIST)
62 return FILTERING_BEHAVIOR_BLOCK_BLACKLIST;
63 else if (source == SupervisedUserURLFilter::ASYNC_CHECKER)
64 return FILTERING_BEHAVIOR_BLOCK_SAFESITES;
72 int GetHistogramValueForTransitionType(ui::PageTransition transition_type) {
74 static_cast<int>(ui::PageTransitionStripQualifier(transition_type));
75 if (0 <= value && value <= kHistogramPageTransitionMaxKnownValue)
78 return kHistogramPageTransitionFallbackValue;
81 void RecordFilterResultEvent(
82 SupervisedUserURLFilter::FilteringBehavior behavior,
83 SupervisedUserURLFilter::FilteringBehaviorSource source,
85 ui::PageTransition transition_type) {
86 DCHECK(source != SupervisedUserURLFilter::MANUAL);
88 GetHistogramValueForFilteringBehavior(behavior, source, uncertain) *
89 kHistogramFilteringBehaviorSpacing +
90 GetHistogramValueForTransitionType(transition_type);
91 DCHECK_LT(value, kHistogramMax);
92 UMA_HISTOGRAM_ENUMERATION("ManagedUsers.SafetyFilter",
93 value, kHistogramMax);
98 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle(
99 const net::URLRequest* request,
101 const SupervisedUserURLFilter* url_filter)
103 is_main_frame_(is_main_frame),
104 url_filter_(url_filter),
106 behavior_(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE),
107 weak_ptr_factory_(this) {}
109 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {}
111 void SupervisedUserResourceThrottle::ShowInterstitialIfNeeded(bool is_redirect,
114 // Only treat main frame requests for now (ignoring subresources).
119 DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE, behavior_);
120 bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks(
122 base::Bind(&SupervisedUserResourceThrottle::OnCheckDone,
123 weak_ptr_factory_.GetWeakPtr(), url));
124 DCHECK_EQ(got_result,
125 (behavior_ != SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE));
126 // If we got a "not blocked" result synchronously, don't defer.
127 *defer = deferred_ = !got_result ||
128 (behavior_ == SupervisedUserURLFilter::BLOCK);
130 behavior_ = SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE;
133 void SupervisedUserResourceThrottle::ShowInterstitial(const GURL& url) {
134 const content::ResourceRequestInfo* info =
135 content::ResourceRequestInfo::ForRequest(request_);
136 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
137 base::Bind(&SupervisedUserNavigationObserver::OnRequestBlocked,
138 info->GetChildID(), info->GetRouteID(), url,
140 &SupervisedUserResourceThrottle::OnInterstitialResult,
141 weak_ptr_factory_.GetWeakPtr())));
144 void SupervisedUserResourceThrottle::WillStartRequest(bool* defer) {
145 ShowInterstitialIfNeeded(false, request_->url(), defer);
148 void SupervisedUserResourceThrottle::WillRedirectRequest(const GURL& new_url,
150 ShowInterstitialIfNeeded(true, new_url, defer);
153 const char* SupervisedUserResourceThrottle::GetNameForLogging() const {
154 return "SupervisedUserResourceThrottle";
157 void SupervisedUserResourceThrottle::OnCheckDone(
159 SupervisedUserURLFilter::FilteringBehavior behavior,
160 SupervisedUserURLFilter::FilteringBehaviorSource source,
162 DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE, behavior_);
163 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded.
165 behavior_ = behavior;
167 // If both the static blacklist and SafeSites are enabled, record UMA events.
168 if (url_filter_->HasBlacklist() && url_filter_->HasAsyncURLChecker() &&
169 source < SupervisedUserURLFilter::MANUAL) {
170 const content::ResourceRequestInfo* info =
171 content::ResourceRequestInfo::ForRequest(request_);
172 RecordFilterResultEvent(behavior, source, uncertain,
173 info->GetPageTransition());
176 if (behavior == SupervisedUserURLFilter::BLOCK)
177 ShowInterstitial(url);
179 controller()->Resume();
182 void SupervisedUserResourceThrottle::OnInterstitialResult(
183 bool continue_request) {
184 if (continue_request)
185 controller()->Resume();
187 controller()->Cancel();