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/sparse_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_BLOCK_MANUAL
,
32 FILTERING_BEHAVIOR_BLOCK_DEFAULT
,
33 FILTERING_BEHAVIOR_MAX
= FILTERING_BEHAVIOR_BLOCK_DEFAULT
35 const int kHistogramFilteringBehaviorSpacing
= 100;
36 const int kHistogramPageTransitionMaxKnownValue
=
37 static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED
);
38 const int kHistogramPageTransitionFallbackValue
=
39 kHistogramFilteringBehaviorSpacing
- 1;
40 const int kHistogramMax
= 700;
42 static_assert(kHistogramPageTransitionMaxKnownValue
<
43 kHistogramPageTransitionFallbackValue
,
44 "HistogramPageTransition MaxKnownValue must be < FallbackValue");
45 static_assert(FILTERING_BEHAVIOR_MAX
* kHistogramFilteringBehaviorSpacing
+
46 kHistogramPageTransitionFallbackValue
< kHistogramMax
,
47 "Invalid HistogramMax value");
49 int GetHistogramValueForFilteringBehavior(
50 SupervisedUserURLFilter::FilteringBehavior behavior
,
51 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
54 case SupervisedUserURLFilter::ALLOW
:
55 case SupervisedUserURLFilter::WARN
:
56 return uncertain
? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN
57 : FILTERING_BEHAVIOR_ALLOW
;
58 case SupervisedUserURLFilter::BLOCK
:
60 case SupervisedUserURLFilter::BLACKLIST
:
61 return FILTERING_BEHAVIOR_BLOCK_BLACKLIST
;
62 case SupervisedUserURLFilter::ASYNC_CHECKER
:
63 return FILTERING_BEHAVIOR_BLOCK_SAFESITES
;
64 case SupervisedUserURLFilter::MANUAL
:
65 return FILTERING_BEHAVIOR_BLOCK_MANUAL
;
66 case SupervisedUserURLFilter::DEFAULT
:
67 return FILTERING_BEHAVIOR_BLOCK_DEFAULT
;
69 case SupervisedUserURLFilter::INVALID
:
75 int GetHistogramValueForTransitionType(ui::PageTransition transition_type
) {
77 static_cast<int>(ui::PageTransitionStripQualifier(transition_type
));
78 if (0 <= value
&& value
<= kHistogramPageTransitionMaxKnownValue
)
81 return kHistogramPageTransitionFallbackValue
;
84 void RecordFilterResultEvent(
85 bool safesites_histogram
,
86 SupervisedUserURLFilter::FilteringBehavior behavior
,
87 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
89 ui::PageTransition transition_type
) {
91 GetHistogramValueForFilteringBehavior(behavior
, reason
, uncertain
) *
92 kHistogramFilteringBehaviorSpacing
+
93 GetHistogramValueForTransitionType(transition_type
);
94 DCHECK_LT(value
, kHistogramMax
);
95 // Note: We can't pass in the histogram name as a parameter to this function
96 // because of how the macro works (look up the histogram on the first
97 // invocation and cache it in a static variable).
98 if (safesites_histogram
)
99 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.SafetyFilter", value
);
101 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value
);
106 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle(
107 const net::URLRequest
* request
,
109 const SupervisedUserURLFilter
* url_filter
)
111 is_main_frame_(is_main_frame
),
112 url_filter_(url_filter
),
114 behavior_(SupervisedUserURLFilter::INVALID
),
115 weak_ptr_factory_(this) {}
117 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {}
119 void SupervisedUserResourceThrottle::ShowInterstitialIfNeeded(bool is_redirect
,
122 // Only treat main frame requests for now (ignoring subresources).
127 DCHECK_EQ(SupervisedUserURLFilter::INVALID
, behavior_
);
128 bool got_result
= url_filter_
->GetFilteringBehaviorForURLWithAsyncChecks(
130 base::Bind(&SupervisedUserResourceThrottle::OnCheckDone
,
131 weak_ptr_factory_
.GetWeakPtr(), url
));
132 DCHECK_EQ(got_result
, behavior_
!= SupervisedUserURLFilter::INVALID
);
133 // If we got a "not blocked" result synchronously, don't defer.
134 *defer
= deferred_
= !got_result
||
135 (behavior_
== SupervisedUserURLFilter::BLOCK
);
137 behavior_
= SupervisedUserURLFilter::INVALID
;
140 void SupervisedUserResourceThrottle::ShowInterstitial(
142 SupervisedUserURLFilter::FilteringBehaviorReason reason
) {
143 const content::ResourceRequestInfo
* info
=
144 content::ResourceRequestInfo::ForRequest(request_
);
145 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
146 base::Bind(&SupervisedUserNavigationObserver::OnRequestBlocked
,
147 info
->GetChildID(), info
->GetRouteID(), url
, reason
,
149 &SupervisedUserResourceThrottle::OnInterstitialResult
,
150 weak_ptr_factory_
.GetWeakPtr())));
153 void SupervisedUserResourceThrottle::WillStartRequest(bool* defer
) {
154 ShowInterstitialIfNeeded(false, request_
->url(), defer
);
157 void SupervisedUserResourceThrottle::WillRedirectRequest(
158 const net::RedirectInfo
& redirect_info
,
160 ShowInterstitialIfNeeded(true, redirect_info
.new_url
, defer
);
163 const char* SupervisedUserResourceThrottle::GetNameForLogging() const {
164 return "SupervisedUserResourceThrottle";
167 void SupervisedUserResourceThrottle::OnCheckDone(
169 SupervisedUserURLFilter::FilteringBehavior behavior
,
170 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
172 DCHECK_EQ(SupervisedUserURLFilter::INVALID
, behavior_
);
173 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded.
175 behavior_
= behavior
;
177 ui::PageTransition transition
=
178 content::ResourceRequestInfo::ForRequest(request_
)->GetPageTransition();
180 RecordFilterResultEvent(false, behavior
, reason
, uncertain
, transition
);
182 // If both the static blacklist and the async checker are enabled, also record
183 // SafeSites-only UMA events.
184 if (url_filter_
->HasBlacklist() && url_filter_
->HasAsyncURLChecker() &&
185 (reason
== SupervisedUserURLFilter::ASYNC_CHECKER
||
186 reason
== SupervisedUserURLFilter::BLACKLIST
)) {
187 RecordFilterResultEvent(true, behavior
, reason
, uncertain
, transition
);
190 if (behavior
== SupervisedUserURLFilter::BLOCK
)
191 ShowInterstitial(url
, reason
);
193 controller()->Resume();
196 void SupervisedUserResourceThrottle::OnInterstitialResult(
197 bool continue_request
) {
198 if (continue_request
)
199 controller()->Resume();
201 controller()->Cancel();