Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_resource_throttle.cc
blob55b329f497d00531b9c1facf2eebafaeff3efc45
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"
7 #include "base/bind.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;
21 namespace {
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_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,
52 bool uncertain) {
53 switch (behavior) {
54 case SupervisedUserURLFilter::ALLOW:
55 case SupervisedUserURLFilter::WARN:
56 return uncertain ? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN
57 : FILTERING_BEHAVIOR_ALLOW;
58 case SupervisedUserURLFilter::BLOCK:
59 switch (reason) {
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:
70 NOTREACHED();
72 return 0;
75 int GetHistogramValueForTransitionType(ui::PageTransition transition_type) {
76 int value =
77 static_cast<int>(ui::PageTransitionStripQualifier(transition_type));
78 if (0 <= value && value <= kHistogramPageTransitionMaxKnownValue)
79 return value;
80 NOTREACHED();
81 return kHistogramPageTransitionFallbackValue;
84 void RecordFilterResultEvent(
85 bool safesites_histogram,
86 SupervisedUserURLFilter::FilteringBehavior behavior,
87 SupervisedUserURLFilter::FilteringBehaviorReason reason,
88 bool uncertain,
89 ui::PageTransition transition_type) {
90 int value =
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);
100 else
101 UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value);
104 } // namespace
106 SupervisedUserResourceThrottle::SupervisedUserResourceThrottle(
107 const net::URLRequest* request,
108 bool is_main_frame,
109 const SupervisedUserURLFilter* url_filter)
110 : request_(request),
111 is_main_frame_(is_main_frame),
112 url_filter_(url_filter),
113 deferred_(false),
114 behavior_(SupervisedUserURLFilter::INVALID),
115 weak_ptr_factory_(this) {}
117 SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {}
119 void SupervisedUserResourceThrottle::ShowInterstitialIfNeeded(bool is_redirect,
120 const GURL& url,
121 bool* defer) {
122 // Only treat main frame requests for now (ignoring subresources).
123 if (!is_main_frame_)
124 return;
126 deferred_ = false;
127 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_);
128 bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks(
129 url,
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);
136 if (got_result)
137 behavior_ = SupervisedUserURLFilter::INVALID;
140 void SupervisedUserResourceThrottle::ShowInterstitial(
141 const GURL& url,
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,
148 base::Bind(
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,
159 bool* defer) {
160 ShowInterstitialIfNeeded(true, redirect_info.new_url, defer);
163 const char* SupervisedUserResourceThrottle::GetNameForLogging() const {
164 return "SupervisedUserResourceThrottle";
167 void SupervisedUserResourceThrottle::OnCheckDone(
168 const GURL& url,
169 SupervisedUserURLFilter::FilteringBehavior behavior,
170 SupervisedUserURLFilter::FilteringBehaviorReason reason,
171 bool uncertain) {
172 DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_);
173 // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded.
174 if (!deferred_)
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);
192 else if (deferred_)
193 controller()->Resume();
196 void SupervisedUserResourceThrottle::OnInterstitialResult(
197 bool continue_request) {
198 if (continue_request)
199 controller()->Resume();
200 else
201 controller()->Cancel();