Chromium Code Reviews| 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/feature_list.h" | 7 #include "base/feature_list.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 | 86 |
| 87 ContentSubresourceFilterDriverFactory::ContentSubresourceFilterDriverFactory( | 87 ContentSubresourceFilterDriverFactory::ContentSubresourceFilterDriverFactory( |
| 88 content::WebContents* web_contents, | 88 content::WebContents* web_contents, |
| 89 std::unique_ptr<SubresourceFilterClient> client) | 89 std::unique_ptr<SubresourceFilterClient> client) |
| 90 : content::WebContentsObserver(web_contents), | 90 : content::WebContentsObserver(web_contents), |
| 91 client_(std::move(client)), | 91 client_(std::move(client)), |
| 92 throttle_manager_( | 92 throttle_manager_( |
| 93 base::MakeUnique<ContentSubresourceFilterThrottleManager>( | 93 base::MakeUnique<ContentSubresourceFilterThrottleManager>( |
| 94 this, | 94 this, |
| 95 client_->GetRulesetDealer(), | 95 client_->GetRulesetDealer(), |
| 96 web_contents)), | 96 web_contents)) {} |
| 97 activation_level_(ActivationLevel::DISABLED), | |
| 98 activation_decision_(ActivationDecision::UNKNOWN), | |
| 99 measure_performance_(false) {} | |
| 100 | 97 |
| 101 ContentSubresourceFilterDriverFactory:: | 98 ContentSubresourceFilterDriverFactory:: |
| 102 ~ContentSubresourceFilterDriverFactory() {} | 99 ~ContentSubresourceFilterDriverFactory() {} |
| 103 | 100 |
| 104 void ContentSubresourceFilterDriverFactory:: | 101 void ContentSubresourceFilterDriverFactory:: |
| 105 OnMainResourceMatchedSafeBrowsingBlacklist( | 102 OnMainResourceMatchedSafeBrowsingBlacklist( |
| 106 const GURL& url, | 103 const GURL& url, |
| 107 const std::vector<GURL>& redirect_urls, | 104 const std::vector<GURL>& redirect_urls, |
| 108 safe_browsing::SBThreatType threat_type, | 105 safe_browsing::SBThreatType threat_type, |
| 109 safe_browsing::ThreatPatternType threat_type_metadata) { | 106 safe_browsing::ThreatPatternType threat_type_metadata) { |
| 110 AddActivationListMatch( | 107 AddActivationListMatch( |
| 111 url, GetListForThreatTypeAndMetadata(threat_type, threat_type_metadata)); | 108 url, GetListForThreatTypeAndMetadata(threat_type, threat_type_metadata)); |
| 112 } | 109 } |
| 113 | 110 |
| 111 void ContentSubresourceFilterDriverFactory:: | |
| 112 ComputeActivationForMainFrameNavigation( | |
| 113 content::NavigationHandle* navigation_handle) { | |
| 114 activation_decision_ = ActivationDecision::ACTIVATION_DISABLED; | |
| 115 activation_options_ = Configuration::ActivationOptions(); | |
| 116 const auto config_list = GetEnabledConfigurations(); | |
| 117 for (const auto& config : config_list->configs_by_decreasing_priority()) { | |
| 118 ActivationDecision decision = | |
| 119 ComputePerConfigActivationDecisionForMainFrameNavigation( | |
| 120 navigation_handle, config); | |
| 121 if (decision == ActivationDecision::ACTIVATED) { | |
| 122 activation_decision_ = ActivationDecision::ACTIVATED; | |
| 123 activation_options_ = config.activation_options; | |
| 124 return; | |
| 125 } | |
| 126 | |
| 127 // Remember a |decision| more specific that `ACTIVATION_DISABLED`, if any. | |
|
pkalinnikov
2017/05/04 12:04:22
g/that/than/
pkalinnikov
2017/05/04 12:04:22
If we have 2 configs, and both return different no
engedy
2017/05/05 12:25:41
Done.
engedy
2017/05/05 12:25:41
Yes and yes, but agreed that it's a bit hacky. Gla
pkalinnikov
2017/05/05 13:29:58
Maybe you could add a short explicit comment that
engedy
2017/05/05 19:24:10
I cleaned this up a bit, so this is no longer a co
| |
| 128 if (decision != ActivationDecision::ACTIVATION_DISABLED) | |
| 129 activation_decision_ = decision; | |
| 130 } | |
| 131 } | |
| 132 | |
| 114 ContentSubresourceFilterDriverFactory::ActivationDecision | 133 ContentSubresourceFilterDriverFactory::ActivationDecision |
| 115 ContentSubresourceFilterDriverFactory:: | 134 ContentSubresourceFilterDriverFactory:: |
| 116 ComputeActivationDecisionForMainFrameNavigation( | 135 ComputePerConfigActivationDecisionForMainFrameNavigation( |
| 117 content::NavigationHandle* navigation_handle) const { | 136 content::NavigationHandle* navigation_handle, |
| 137 const Configuration& configuration) const { | |
| 118 const GURL& url(navigation_handle->GetURL()); | 138 const GURL& url(navigation_handle->GetURL()); |
| 119 | 139 if (configuration.activation_options.activation_level == |
| 120 const auto configurations = GetActiveConfigurations(); | |
| 121 if (configurations->the_one_and_only().activation_level == | |
| 122 ActivationLevel::DISABLED) | 140 ActivationLevel::DISABLED) |
| 123 return ActivationDecision::ACTIVATION_DISABLED; | 141 return ActivationDecision::ACTIVATION_DISABLED; |
| 124 | 142 |
| 125 if (configurations->the_one_and_only().activation_scope == | 143 if (configuration.activation_conditions.activation_scope == |
| 126 ActivationScope::NO_SITES) | 144 ActivationScope::NO_SITES) |
| 127 return ActivationDecision::ACTIVATION_DISABLED; | 145 return ActivationDecision::ACTIVATION_DISABLED; |
| 128 | 146 |
| 129 if (!url.SchemeIsHTTPOrHTTPS()) | 147 if (!url.SchemeIsHTTPOrHTTPS()) |
| 130 return ActivationDecision::UNSUPPORTED_SCHEME; | 148 return ActivationDecision::UNSUPPORTED_SCHEME; |
| 149 | |
| 131 // TODO(csharrison): The throttle manager also performs this check. Remove | 150 // TODO(csharrison): The throttle manager also performs this check. Remove |
| 132 // this one when the activation decision is sent directly to the throttle | 151 // this one when the activation decision is sent directly to the throttle |
| 133 // manager. | 152 // manager. |
| 134 if (client_->ShouldSuppressActivation(navigation_handle)) | 153 if (client_->ShouldSuppressActivation(navigation_handle)) |
| 135 return ActivationDecision::URL_WHITELISTED; | 154 return ActivationDecision::URL_WHITELISTED; |
| 136 | 155 |
| 137 switch (configurations->the_one_and_only().activation_scope) { | 156 switch (configuration.activation_conditions.activation_scope) { |
| 138 case ActivationScope::ALL_SITES: | 157 case ActivationScope::ALL_SITES: |
| 139 return ActivationDecision::ACTIVATED; | 158 return ActivationDecision::ACTIVATED; |
| 140 case ActivationScope::ACTIVATION_LIST: { | 159 case ActivationScope::ACTIVATION_LIST: { |
| 141 // The logic to ensure only http/https URLs are activated lives in | 160 // The logic to ensure only http/https URLs are activated lives in |
| 142 // AddActivationListMatch to ensure the activation list only has relevant | 161 // AddActivationListMatch to ensure the activation list only has relevant |
| 143 // entries. | 162 // entries. |
| 144 DCHECK(url.SchemeIsHTTPOrHTTPS() || | 163 DCHECK(url.SchemeIsHTTPOrHTTPS() || |
| 145 !DidURLMatchActivationList( | 164 !DidURLMatchActivationList( |
| 146 url, configurations->the_one_and_only().activation_list)); | 165 url, configuration.activation_conditions.activation_list)); |
| 147 bool should_activate = DidURLMatchActivationList( | 166 bool should_activate = DidURLMatchActivationList( |
| 148 url, configurations->the_one_and_only().activation_list); | 167 url, configuration.activation_conditions.activation_list); |
| 149 if (configurations->the_one_and_only().activation_list == | 168 if (configuration.activation_conditions.activation_list == |
| 150 ActivationList::PHISHING_INTERSTITIAL) { | 169 ActivationList::PHISHING_INTERSTITIAL) { |
| 151 // Handling special case, where activation on the phishing sites also | 170 // Handling special case, where activation on the phishing sites also |
| 152 // mean the activation on the sites with social engineering metadata. | 171 // mean the activation on the sites with social engineering metadata. |
| 153 should_activate |= DidURLMatchActivationList( | 172 should_activate |= DidURLMatchActivationList( |
| 154 url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); | 173 url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); |
| 155 } | 174 } |
| 156 return should_activate ? ActivationDecision::ACTIVATED | 175 return should_activate ? ActivationDecision::ACTIVATED |
| 157 : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; | 176 : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; |
| 158 } | 177 } |
| 159 default: | 178 default: |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 184 navigation_handle->GetNetErrorCode() != net::OK) { | 203 navigation_handle->GetNetErrorCode() != net::OK) { |
| 185 return; | 204 return; |
| 186 } | 205 } |
| 187 | 206 |
| 188 const GURL& url = navigation_handle->GetURL(); | 207 const GURL& url = navigation_handle->GetURL(); |
| 189 const content::Referrer& referrer = navigation_handle->GetReferrer(); | 208 const content::Referrer& referrer = navigation_handle->GetReferrer(); |
| 190 ui::PageTransition transition = navigation_handle->GetPageTransition(); | 209 ui::PageTransition transition = navigation_handle->GetPageTransition(); |
| 191 | 210 |
| 192 RecordRedirectChainMatchPattern(); | 211 RecordRedirectChainMatchPattern(); |
| 193 | 212 |
| 194 const auto configurations = GetActiveConfigurations(); | 213 if (activation_options_.should_whitelist_site_on_reload && |
| 195 if (configurations->the_one_and_only().should_whitelist_site_on_reload && | |
| 196 NavigationIsPageReload(url, referrer, transition)) { | 214 NavigationIsPageReload(url, referrer, transition)) { |
| 197 // Whitelist this host for the current as well as subsequent navigations. | 215 // Whitelist this host for the current as well as subsequent navigations. |
| 198 client_->WhitelistInCurrentWebContents(url); | 216 client_->WhitelistInCurrentWebContents(url); |
| 199 } | 217 } |
| 200 | 218 |
| 201 activation_decision_ = | 219 ComputeActivationForMainFrameNavigation(navigation_handle); |
| 202 ComputeActivationDecisionForMainFrameNavigation(navigation_handle); | 220 DCHECK_NE(activation_decision_, ActivationDecision::UNKNOWN); |
| 203 DCHECK(activation_decision_ != ActivationDecision::UNKNOWN); | |
| 204 if (activation_decision_ != ActivationDecision::ACTIVATED) { | 221 if (activation_decision_ != ActivationDecision::ACTIVATED) { |
| 205 ResetActivationState(); | 222 DCHECK_EQ(activation_options_.activation_level, ActivationLevel::DISABLED); |
| 206 return; | 223 return; |
| 207 } | 224 } |
| 208 | 225 |
| 209 activation_level_ = configurations->the_one_and_only().activation_level; | 226 DCHECK_NE(activation_options_.activation_level, ActivationLevel::DISABLED); |
| 210 measure_performance_ = | 227 ActivationState state = ActivationState(activation_options_.activation_level); |
| 211 activation_level_ != ActivationLevel::DISABLED && | 228 state.measure_performance = ShouldMeasurePerformanceForPageLoad( |
| 212 ShouldMeasurePerformanceForPageLoad( | 229 activation_options_.performance_measurement_rate); |
| 213 configurations->the_one_and_only().performance_measurement_rate); | |
| 214 ActivationState state = ActivationState(activation_level_); | |
| 215 state.measure_performance = measure_performance_; | |
| 216 throttle_manager_->NotifyPageActivationComputed(navigation_handle, state); | 230 throttle_manager_->NotifyPageActivationComputed(navigation_handle, state); |
| 217 } | 231 } |
| 218 | 232 |
| 219 void ContentSubresourceFilterDriverFactory::OnFirstSubresourceLoadDisallowed() { | 233 void ContentSubresourceFilterDriverFactory::OnFirstSubresourceLoadDisallowed() { |
| 220 const auto configurations = GetActiveConfigurations(); | 234 if (activation_options_.should_suppress_notifications) |
| 221 if (configurations->the_one_and_only().should_suppress_notifications) | |
| 222 return; | 235 return; |
| 223 | 236 client_->ToggleNotificationVisibility(activation_options_.activation_level == |
| 224 client_->ToggleNotificationVisibility(activation_level_ == | |
| 225 ActivationLevel::ENABLED); | 237 ActivationLevel::ENABLED); |
| 226 } | 238 } |
| 227 | 239 |
| 228 bool ContentSubresourceFilterDriverFactory::ShouldSuppressActivation( | 240 bool ContentSubresourceFilterDriverFactory::ShouldSuppressActivation( |
| 229 content::NavigationHandle* navigation_handle) { | 241 content::NavigationHandle* navigation_handle) { |
| 230 return client_->ShouldSuppressActivation(navigation_handle); | 242 return client_->ShouldSuppressActivation(navigation_handle); |
| 231 } | 243 } |
| 232 | 244 |
| 233 void ContentSubresourceFilterDriverFactory::ResetActivationState() { | |
| 234 navigation_chain_.clear(); | |
| 235 activation_list_matches_.clear(); | |
| 236 activation_level_ = ActivationLevel::DISABLED; | |
| 237 measure_performance_ = false; | |
| 238 } | |
| 239 | |
| 240 void ContentSubresourceFilterDriverFactory::DidStartNavigation( | 245 void ContentSubresourceFilterDriverFactory::DidStartNavigation( |
| 241 content::NavigationHandle* navigation_handle) { | 246 content::NavigationHandle* navigation_handle) { |
| 242 if (navigation_handle->IsInMainFrame() && | 247 if (navigation_handle->IsInMainFrame() && |
| 243 !navigation_handle->IsSameDocument()) { | 248 !navigation_handle->IsSameDocument()) { |
| 244 activation_decision_ = ActivationDecision::UNKNOWN; | 249 activation_decision_ = ActivationDecision::UNKNOWN; |
| 245 ResetActivationState(); | 250 activation_list_matches_.clear(); |
| 251 navigation_chain_.clear(); | |
|
pkalinnikov
2017/05/04 12:04:22
optional: navigation_chain_.assign(1, navigation_h
engedy
2017/05/05 12:25:41
How about this?
pkalinnikov
2017/05/05 13:29:58
Even better :)
| |
| 246 navigation_chain_.push_back(navigation_handle->GetURL()); | 252 navigation_chain_.push_back(navigation_handle->GetURL()); |
| 247 client_->ToggleNotificationVisibility(false); | 253 client_->ToggleNotificationVisibility(false); |
| 248 } | 254 } |
| 249 } | 255 } |
| 250 | 256 |
| 251 void ContentSubresourceFilterDriverFactory::DidRedirectNavigation( | 257 void ContentSubresourceFilterDriverFactory::DidRedirectNavigation( |
| 252 content::NavigationHandle* navigation_handle) { | 258 content::NavigationHandle* navigation_handle) { |
| 253 DCHECK(!navigation_handle->IsSameDocument()); | 259 DCHECK(!navigation_handle->IsSameDocument()); |
| 254 if (navigation_handle->IsInMainFrame()) | 260 if (navigation_handle->IsInMainFrame()) |
| 255 navigation_chain_.push_back(navigation_handle->GetURL()); | 261 navigation_chain_.push_back(navigation_handle->GetURL()); |
| 256 } | 262 } |
| 257 | 263 |
| 264 void ContentSubresourceFilterDriverFactory::DidFinishNavigation( | |
| 265 content::NavigationHandle* navigation_handle) { | |
| 266 if (navigation_handle->IsInMainFrame() && | |
| 267 !navigation_handle->IsSameDocument() && | |
| 268 activation_decision_ == ActivationDecision::UNKNOWN && | |
| 269 navigation_handle->HasCommitted()) { | |
| 270 activation_decision_ = ActivationDecision::ACTIVATION_DISABLED; | |
| 271 activation_options_ = Configuration::ActivationOptions(); | |
| 272 } | |
| 273 } | |
| 274 | |
| 258 bool ContentSubresourceFilterDriverFactory::DidURLMatchActivationList( | 275 bool ContentSubresourceFilterDriverFactory::DidURLMatchActivationList( |
| 259 const GURL& url, | 276 const GURL& url, |
| 260 ActivationList activation_list) const { | 277 ActivationList activation_list) const { |
| 261 auto match_types = | 278 auto match_types = |
| 262 activation_list_matches_.find(DistillURLToHostAndPath(url)); | 279 activation_list_matches_.find(DistillURLToHostAndPath(url)); |
| 263 return match_types != activation_list_matches_.end() && | 280 return match_types != activation_list_matches_.end() && |
| 264 match_types->second.find(activation_list) != match_types->second.end(); | 281 match_types->second.find(activation_list) != match_types->second.end(); |
| 265 } | 282 } |
| 266 | 283 |
| 267 void ContentSubresourceFilterDriverFactory::AddActivationListMatch( | 284 void ContentSubresourceFilterDriverFactory::AddActivationListMatch( |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 REPORT_REDIRECT_PATTERN_FOR_SUFFIX("SubresourceFilterOnly", hits_pattern, | 347 REPORT_REDIRECT_PATTERN_FOR_SUFFIX("SubresourceFilterOnly", hits_pattern, |
| 331 chain_size); | 348 chain_size); |
| 332 break; | 349 break; |
| 333 default: | 350 default: |
| 334 NOTREACHED(); | 351 NOTREACHED(); |
| 335 break; | 352 break; |
| 336 } | 353 } |
| 337 } | 354 } |
| 338 | 355 |
| 339 } // namespace subresource_filter | 356 } // namespace subresource_filter |
| OLD | NEW |