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/redirect_info.h"
16 #include "net/url_request/url_request.h"
17 #include "ui/base/page_transition_types.h"
19 using content::BrowserThread
;
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.
27 FILTERING_BEHAVIOR_ALLOW
= 1,
28 FILTERING_BEHAVIOR_ALLOW_UNCERTAIN
,
29 FILTERING_BEHAVIOR_BLOCK_BLACKLIST
,
30 FILTERING_BEHAVIOR_BLOCK_SAFESITES
,
31 FILTERING_BEHAVIOR_MAX
= FILTERING_BEHAVIOR_BLOCK_SAFESITES
33 const int kHistogramFilteringBehaviorSpacing
= 100;
34 const int kHistogramPageTransitionMaxKnownValue
=
35 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED
);
36 const int kHistogramPageTransitionFallbackValue
=
37 kHistogramFilteringBehaviorSpacing
- 1;
38 const int kHistogramMax
= 500;
40 static_assert(kHistogramPageTransitionMaxKnownValue
<
41 kHistogramPageTransitionFallbackValue
,
42 "HistogramPageTransition MaxKnownValue must be < FallbackValue");
43 static_assert(FILTERING_BEHAVIOR_MAX
* kHistogramFilteringBehaviorSpacing
+
44 kHistogramPageTransitionFallbackValue
< kHistogramMax
,
45 "Invalid HistogramMax value");
47 int GetHistogramValueForFilteringBehavior(
48 SupervisedUserURLFilter::FilteringBehavior behavior
,
49 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
51 // Since we're only interested in statistics about the blacklist and
52 // SafeSites, count everything that got through to the default fallback
53 // behavior as ALLOW (made it through all the filters!).
54 if (reason
== SupervisedUserURLFilter::DEFAULT
)
55 behavior
= SupervisedUserURLFilter::ALLOW
;
58 case SupervisedUserURLFilter::ALLOW
:
59 return uncertain
? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN
60 : FILTERING_BEHAVIOR_ALLOW
;
61 case SupervisedUserURLFilter::BLOCK
:
62 if (reason
== SupervisedUserURLFilter::BLACKLIST
)
63 return FILTERING_BEHAVIOR_BLOCK_BLACKLIST
;
64 else if (reason
== SupervisedUserURLFilter::ASYNC_CHECKER
)
65 return FILTERING_BEHAVIOR_BLOCK_SAFESITES
;
73 int GetHistogramValueForTransitionType(ui::PageTransition transition_type
) {
75 static_cast<int>(ui::PageTransitionStripQualifier(transition_type
));
76 if (0 <= value
&& value
<= kHistogramPageTransitionMaxKnownValue
)
79 return kHistogramPageTransitionFallbackValue
;
82 void RecordFilterResultEvent(
83 SupervisedUserURLFilter::FilteringBehavior behavior
,
84 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
86 ui::PageTransition transition_type
) {
87 DCHECK(reason
!= SupervisedUserURLFilter::MANUAL
);
89 GetHistogramValueForFilteringBehavior(behavior
, reason
, uncertain
) *
90 kHistogramFilteringBehaviorSpacing
+
91 GetHistogramValueForTransitionType(transition_type
);
92 DCHECK_LT(value
, kHistogramMax
);
93 UMA_HISTOGRAM_ENUMERATION("ManagedUsers.SafetyFilter",
94 value
, kHistogramMax
);
99 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle(
100 const net::URLRequest
* request
,
102 const SupervisedUserURLFilter
* url_filter
)
104 is_main_frame_(is_main_frame
),
105 url_filter_(url_filter
),
107 behavior_(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE
),
108 weak_ptr_factory_(this) {}
110 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {}
112 void SupervisedUserResourceThrottle::ShowInterstitialIfNeeded(bool is_redirect
,
115 // Only treat main frame requests for now (ignoring subresources).
120 DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE
, behavior_
);
121 bool got_result
= url_filter_
->GetFilteringBehaviorForURLWithAsyncChecks(
123 base::Bind(&SupervisedUserResourceThrottle::OnCheckDone
,
124 weak_ptr_factory_
.GetWeakPtr(), url
));
125 DCHECK_EQ(got_result
,
126 (behavior_
!= SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE
));
127 // If we got a "not blocked" result synchronously, don't defer.
128 *defer
= deferred_
= !got_result
||
129 (behavior_
== SupervisedUserURLFilter::BLOCK
);
131 behavior_
= SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE
;
134 void SupervisedUserResourceThrottle::ShowInterstitial(
136 SupervisedUserURLFilter::FilteringBehaviorReason reason
) {
137 const content::ResourceRequestInfo
* info
=
138 content::ResourceRequestInfo::ForRequest(request_
);
139 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
140 base::Bind(&SupervisedUserNavigationObserver::OnRequestBlocked
,
141 info
->GetChildID(), info
->GetRouteID(), url
, reason
,
143 &SupervisedUserResourceThrottle::OnInterstitialResult
,
144 weak_ptr_factory_
.GetWeakPtr())));
147 void SupervisedUserResourceThrottle::WillStartRequest(bool* defer
) {
148 ShowInterstitialIfNeeded(false, request_
->url(), defer
);
151 void SupervisedUserResourceThrottle::WillRedirectRequest(
152 const net::RedirectInfo
& redirect_info
,
154 ShowInterstitialIfNeeded(true, redirect_info
.new_url
, defer
);
157 const char* SupervisedUserResourceThrottle::GetNameForLogging() const {
158 return "SupervisedUserResourceThrottle";
161 void SupervisedUserResourceThrottle::OnCheckDone(
163 SupervisedUserURLFilter::FilteringBehavior behavior
,
164 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
166 DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE
, behavior_
);
167 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded.
169 behavior_
= behavior
;
171 // If both the static blacklist and SafeSites are enabled, record UMA events.
172 if (url_filter_
->HasBlacklist() && url_filter_
->HasAsyncURLChecker() &&
173 reason
< SupervisedUserURLFilter::MANUAL
) {
174 const content::ResourceRequestInfo
* info
=
175 content::ResourceRequestInfo::ForRequest(request_
);
176 RecordFilterResultEvent(behavior
, reason
, uncertain
,
177 info
->GetPageTransition());
180 if (behavior
== SupervisedUserURLFilter::BLOCK
)
181 ShowInterstitial(url
, reason
);
183 controller()->Resume();
186 void SupervisedUserResourceThrottle::OnInterstitialResult(
187 bool continue_request
) {
188 if (continue_request
)
189 controller()->Resume();
191 controller()->Cancel();