OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/subresource_filter/content/browser/content_subresource_filt
er_driver_factory.h" | 5 #include "components/subresource_filter/content/browser/content_subresource_filt
er_driver_factory.h" |
6 | 6 |
7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
| 10 #include "components/subresource_filter/content/browser/content_activation_list_
utils.h" |
10 #include "components/subresource_filter/content/browser/subresource_filter_clien
t.h" | 11 #include "components/subresource_filter/content/browser/subresource_filter_clien
t.h" |
11 #include "components/subresource_filter/content/common/subresource_filter_messag
es.h" | 12 #include "components/subresource_filter/content/common/subresource_filter_messag
es.h" |
12 #include "components/subresource_filter/core/browser/subresource_filter_features
.h" | 13 #include "components/subresource_filter/core/browser/subresource_filter_features
.h" |
13 #include "components/subresource_filter/core/common/activation_list.h" | 14 #include "components/subresource_filter/core/common/activation_list.h" |
14 #include "components/subresource_filter/core/common/time_measurements.h" | 15 #include "components/subresource_filter/core/common/time_measurements.h" |
15 #include "content/public/browser/navigation_handle.h" | 16 #include "content/public/browser/navigation_handle.h" |
16 #include "content/public/browser/render_frame_host.h" | 17 #include "content/public/browser/render_frame_host.h" |
17 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
18 #include "ipc/ipc_message_macros.h" | 19 #include "ipc/ipc_message_macros.h" |
19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
(...skipping 14 matching lines...) Expand all Loading... |
34 // ThreadTicks is supported, otherwise returns false. | 35 // ThreadTicks is supported, otherwise returns false. |
35 bool ShouldMeasurePerformanceForPageLoad() { | 36 bool ShouldMeasurePerformanceForPageLoad() { |
36 if (!base::ThreadTicks::IsSupported()) | 37 if (!base::ThreadTicks::IsSupported()) |
37 return false; | 38 return false; |
38 // TODO(pkalinnikov): Cache |rate| and other variation params in | 39 // TODO(pkalinnikov): Cache |rate| and other variation params in |
39 // ContentSubresourceFilterDriverFactory. | 40 // ContentSubresourceFilterDriverFactory. |
40 const double rate = GetPerformanceMeasurementRate(); | 41 const double rate = GetPerformanceMeasurementRate(); |
41 return rate == 1 || (rate > 0 && base::RandDouble() < rate); | 42 return rate == 1 || (rate > 0 && base::RandDouble() < rate); |
42 } | 43 } |
43 | 44 |
| 45 // Records histograms about the length of redirect chains, and about the pattern |
| 46 // of whether each URL in the chain matched the activation list. |
| 47 #define REPORT_REDIRECT_PATTERN_FOR_SUFFIX(suffix, hits_pattern, chain_size) \ |
| 48 do { \ |
| 49 UMA_HISTOGRAM_ENUMERATION( \ |
| 50 "SubresourceFilter.PageLoad.RedirectChainMatchPattern." suffix, \ |
| 51 hits_pattern, 0x10); \ |
| 52 UMA_HISTOGRAM_COUNTS( \ |
| 53 "SubresourceFilter.PageLoad.RedirectChainLength." suffix, chain_size); \ |
| 54 } while (0) |
| 55 |
44 } // namespace | 56 } // namespace |
45 | 57 |
46 // static | 58 // static |
47 void ContentSubresourceFilterDriverFactory::CreateForWebContents( | 59 void ContentSubresourceFilterDriverFactory::CreateForWebContents( |
48 content::WebContents* web_contents, | 60 content::WebContents* web_contents, |
49 std::unique_ptr<SubresourceFilterClient> client) { | 61 std::unique_ptr<SubresourceFilterClient> client) { |
50 if (FromWebContents(web_contents)) | 62 if (FromWebContents(web_contents)) |
51 return; | 63 return; |
52 web_contents->SetUserData(kWebContentsUserDataKey, | 64 web_contents->SetUserData(kWebContentsUserDataKey, |
53 new ContentSubresourceFilterDriverFactory( | 65 new ContentSubresourceFilterDriverFactory( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 const GURL& url) const { | 125 const GURL& url) const { |
114 return whitelisted_hosts_.find(url.host()) != whitelisted_hosts_.end(); | 126 return whitelisted_hosts_.find(url.host()) != whitelisted_hosts_.end(); |
115 } | 127 } |
116 | 128 |
117 void ContentSubresourceFilterDriverFactory:: | 129 void ContentSubresourceFilterDriverFactory:: |
118 OnMainResourceMatchedSafeBrowsingBlacklist( | 130 OnMainResourceMatchedSafeBrowsingBlacklist( |
119 const GURL& url, | 131 const GURL& url, |
120 const std::vector<GURL>& redirect_urls, | 132 const std::vector<GURL>& redirect_urls, |
121 safe_browsing::SBThreatType threat_type, | 133 safe_browsing::SBThreatType threat_type, |
122 safe_browsing::ThreatPatternType threat_type_metadata) { | 134 safe_browsing::ThreatPatternType threat_type_metadata) { |
123 bool is_phishing_interstitial = | 135 AddActivationListMatch( |
124 (threat_type == safe_browsing::SB_THREAT_TYPE_URL_PHISHING); | 136 url, GetListForThreatTypeAndMetadata(threat_type, threat_type_metadata)); |
125 bool is_soc_engineering_ads_interstitial = | |
126 threat_type_metadata == | |
127 safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS; | |
128 | |
129 if (is_phishing_interstitial) { | |
130 if (is_soc_engineering_ads_interstitial) { | |
131 AddActivationListMatch(url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); | |
132 } | |
133 AddActivationListMatch(url, ActivationList::PHISHING_INTERSTITIAL); | |
134 } | |
135 } | 137 } |
136 | 138 |
137 void ContentSubresourceFilterDriverFactory::AddHostOfURLToWhitelistSet( | 139 void ContentSubresourceFilterDriverFactory::AddHostOfURLToWhitelistSet( |
138 const GURL& url) { | 140 const GURL& url) { |
139 if (url.has_host() && url.SchemeIsHTTPOrHTTPS()) | 141 if (url.has_host() && url.SchemeIsHTTPOrHTTPS()) |
140 whitelisted_hosts_.insert(url.host()); | 142 whitelisted_hosts_.insert(url.host()); |
141 } | 143 } |
142 | 144 |
143 ContentSubresourceFilterDriverFactory::ActivationDecision | 145 ContentSubresourceFilterDriverFactory::ActivationDecision |
144 ContentSubresourceFilterDriverFactory::ComputeActivationDecisionForMainFrameURL( | 146 ContentSubresourceFilterDriverFactory::ComputeActivationDecisionForMainFrameURL( |
145 const GURL& url) const { | 147 const GURL& url) const { |
146 if (GetMaximumActivationLevel() == ActivationLevel::DISABLED) | 148 if (GetMaximumActivationLevel() == ActivationLevel::DISABLED) |
147 return ActivationDecision::ACTIVATION_DISABLED; | 149 return ActivationDecision::ACTIVATION_DISABLED; |
148 | 150 |
149 ActivationScope scope = GetCurrentActivationScope(); | 151 ActivationScope scope = GetCurrentActivationScope(); |
150 if (scope == ActivationScope::NO_SITES) | 152 if (scope == ActivationScope::NO_SITES) |
151 return ActivationDecision::ACTIVATION_DISABLED; | 153 return ActivationDecision::ACTIVATION_DISABLED; |
152 | 154 |
153 if (!url.SchemeIsHTTPOrHTTPS()) | 155 if (!url.SchemeIsHTTPOrHTTPS()) |
154 return ActivationDecision::UNSUPPORTED_SCHEME; | 156 return ActivationDecision::UNSUPPORTED_SCHEME; |
155 if (IsWhitelisted(url)) | 157 if (IsWhitelisted(url)) |
156 return ActivationDecision::URL_WHITELISTED; | 158 return ActivationDecision::URL_WHITELISTED; |
157 | 159 |
158 switch (scope) { | 160 switch (scope) { |
159 case ActivationScope::ALL_SITES: | 161 case ActivationScope::ALL_SITES: |
160 return ActivationDecision::ACTIVATED; | 162 return ActivationDecision::ACTIVATED; |
161 case ActivationScope::ACTIVATION_LIST: | 163 case ActivationScope::ACTIVATION_LIST: { |
162 // The logic to ensure only http/https URLs are activated lives in | 164 // The logic to ensure only http/https URLs are activated lives in |
163 // AddActivationListMatch to ensure the activation list only has relevant | 165 // AddActivationListMatch to ensure the activation list only has relevant |
164 // entries. | 166 // entries. |
165 DCHECK(url.SchemeIsHTTPOrHTTPS() || | 167 DCHECK(url.SchemeIsHTTPOrHTTPS() || |
166 !DidURLMatchCurrentActivationList(url)); | 168 !DidURLMatchActivationList(url, GetCurrentActivationList())); |
167 return DidURLMatchCurrentActivationList(url) | 169 bool should_activate = |
168 ? ActivationDecision::ACTIVATED | 170 DidURLMatchActivationList(url, GetCurrentActivationList()); |
169 : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; | 171 if (GetCurrentActivationList() == ActivationList::PHISHING_INTERSTITIAL) { |
| 172 // Handling special case, where activation on the phishing sites also |
| 173 // mean the activation on the sites with social engineering metadata. |
| 174 should_activate |= DidURLMatchActivationList( |
| 175 url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); |
| 176 } |
| 177 return should_activate ? ActivationDecision::ACTIVATED |
| 178 : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; |
| 179 } |
170 default: | 180 default: |
171 return ActivationDecision::ACTIVATION_DISABLED; | 181 return ActivationDecision::ACTIVATION_DISABLED; |
172 } | 182 } |
173 } | 183 } |
174 | 184 |
175 void ContentSubresourceFilterDriverFactory::ActivateForFrameHostIfNeeded( | 185 void ContentSubresourceFilterDriverFactory::ActivateForFrameHostIfNeeded( |
176 content::RenderFrameHost* render_frame_host, | 186 content::RenderFrameHost* render_frame_host, |
177 const GURL& url) { | 187 const GURL& url) { |
178 if (activation_level_ != ActivationLevel::DISABLED) { | 188 if (activation_level_ != ActivationLevel::DISABLED) { |
179 render_frame_host->Send( | 189 render_frame_host->Send( |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 ResetActivationState(); | 324 ResetActivationState(); |
315 return; | 325 return; |
316 } | 326 } |
317 | 327 |
318 activation_level_ = GetMaximumActivationLevel(); | 328 activation_level_ = GetMaximumActivationLevel(); |
319 measure_performance_ = activation_level_ != ActivationLevel::DISABLED && | 329 measure_performance_ = activation_level_ != ActivationLevel::DISABLED && |
320 ShouldMeasurePerformanceForPageLoad(); | 330 ShouldMeasurePerformanceForPageLoad(); |
321 ActivateForFrameHostIfNeeded(render_frame_host, url); | 331 ActivateForFrameHostIfNeeded(render_frame_host, url); |
322 } | 332 } |
323 | 333 |
324 bool ContentSubresourceFilterDriverFactory::DidURLMatchCurrentActivationList( | 334 bool ContentSubresourceFilterDriverFactory::DidURLMatchActivationList( |
325 const GURL& url) const { | 335 const GURL& url, |
| 336 ActivationList activation_list) const { |
326 auto match_types = | 337 auto match_types = |
327 activation_list_matches_.find(DistillURLToHostAndPath(url)); | 338 activation_list_matches_.find(DistillURLToHostAndPath(url)); |
328 return match_types != activation_list_matches_.end() && | 339 return match_types != activation_list_matches_.end() && |
329 match_types->second.find(GetCurrentActivationList()) != | 340 match_types->second.find(activation_list) != match_types->second.end(); |
330 match_types->second.end(); | |
331 } | 341 } |
332 | 342 |
333 void ContentSubresourceFilterDriverFactory::AddActivationListMatch( | 343 void ContentSubresourceFilterDriverFactory::AddActivationListMatch( |
334 const GURL& url, | 344 const GURL& url, |
335 ActivationList match_type) { | 345 ActivationList match_type) { |
| 346 if (match_type == ActivationList::NONE) |
| 347 return; |
336 if (url.has_host() && url.SchemeIsHTTPOrHTTPS()) | 348 if (url.has_host() && url.SchemeIsHTTPOrHTTPS()) |
337 activation_list_matches_[DistillURLToHostAndPath(url)].insert(match_type); | 349 activation_list_matches_[DistillURLToHostAndPath(url)].insert(match_type); |
338 } | 350 } |
339 | 351 |
340 void ContentSubresourceFilterDriverFactory::RecordRedirectChainMatchPattern() | 352 int ContentSubresourceFilterDriverFactory::CalculateHitPatternForActivationList( |
341 const { | 353 ActivationList activation_list) const { |
342 int hits_pattern = 0; | 354 int hits_pattern = 0; |
343 const int kInitialURLHitMask = 0x4; | 355 const int kInitialURLHitMask = 0x4; |
344 const int kRedirectURLHitMask = 0x2; | 356 const int kRedirectURLHitMask = 0x2; |
345 const int kFinalURLHitMask = 0x1; | 357 const int kFinalURLHitMask = 0x1; |
346 if (navigation_chain_.size() > 1) { | 358 if (navigation_chain_.size() > 1) { |
347 if (DidURLMatchCurrentActivationList(navigation_chain_.back())) | 359 if (DidURLMatchActivationList(navigation_chain_.back(), activation_list)) |
348 hits_pattern |= kFinalURLHitMask; | 360 hits_pattern |= kFinalURLHitMask; |
349 if (DidURLMatchCurrentActivationList(navigation_chain_.front())) | 361 if (DidURLMatchActivationList(navigation_chain_.front(), activation_list)) |
350 hits_pattern |= kInitialURLHitMask; | 362 hits_pattern |= kInitialURLHitMask; |
351 | 363 |
352 // Examine redirects. | 364 // Examine redirects. |
353 for (size_t i = 1; i < navigation_chain_.size() - 1; ++i) { | 365 for (size_t i = 1; i < navigation_chain_.size() - 1; ++i) { |
354 if (DidURLMatchCurrentActivationList(navigation_chain_[i])) { | 366 if (DidURLMatchActivationList(navigation_chain_[i], activation_list)) { |
355 hits_pattern |= kRedirectURLHitMask; | 367 hits_pattern |= kRedirectURLHitMask; |
356 break; | 368 break; |
357 } | 369 } |
358 } | 370 } |
359 } else { | 371 } else { |
360 if (navigation_chain_.size() && | 372 if (navigation_chain_.size() && |
361 DidURLMatchCurrentActivationList(navigation_chain_.front())) { | 373 DidURLMatchActivationList(navigation_chain_.front(), activation_list)) { |
362 hits_pattern = 0x8; // One url hit. | 374 hits_pattern = 0x8; // One url hit. |
363 } | 375 } |
364 } | 376 } |
| 377 return hits_pattern; |
| 378 } |
| 379 |
| 380 void ContentSubresourceFilterDriverFactory::RecordRedirectChainMatchPattern() |
| 381 const { |
| 382 RecordRedirectChainMatchPatternForList( |
| 383 ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); |
| 384 RecordRedirectChainMatchPatternForList(ActivationList::PHISHING_INTERSTITIAL); |
| 385 } |
| 386 |
| 387 void ContentSubresourceFilterDriverFactory:: |
| 388 RecordRedirectChainMatchPatternForList( |
| 389 ActivationList activation_list) const { |
| 390 int hits_pattern = CalculateHitPatternForActivationList(activation_list); |
365 if (!hits_pattern) | 391 if (!hits_pattern) |
366 return; | 392 return; |
367 UMA_HISTOGRAM_ENUMERATION( | 393 size_t chain_size = navigation_chain_.size(); |
368 "SubresourceFilter.PageLoad.RedirectChainMatchPattern", hits_pattern, | 394 switch (activation_list) { |
369 0x10 /* max value */); | 395 case ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL: |
370 UMA_HISTOGRAM_COUNTS("SubresourceFilter.PageLoad.RedirectChainLength", | 396 REPORT_REDIRECT_PATTERN_FOR_SUFFIX("SocialEngineeringAdsInterstitial", |
371 navigation_chain_.size()); | 397 hits_pattern, chain_size); |
| 398 break; |
| 399 case ActivationList::PHISHING_INTERSTITIAL: |
| 400 REPORT_REDIRECT_PATTERN_FOR_SUFFIX("PhishingInterstital", hits_pattern, |
| 401 chain_size); |
| 402 break; |
| 403 default: |
| 404 NOTREACHED(); |
| 405 break; |
| 406 } |
372 } | 407 } |
373 | 408 |
374 } // namespace subresource_filter | 409 } // namespace subresource_filter |
OLD | NEW |