| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_
registry.h" | 5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_
registry.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" |
| 11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 12 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit
ion.h" | 13 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit
ion.h" |
| 13 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" | 14 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" |
| 14 #include "chrome/browser/extensions/api/web_request/web_request_permissions.h" | 15 #include "chrome/browser/extensions/api/web_request/web_request_permissions.h" |
| 15 #include "chrome/browser/extensions/extension_system.h" | 16 #include "chrome/browser/extensions/extension_system.h" |
| 17 #include "chrome/common/extensions/extension.h" |
| 18 #include "extensions/common/error_utils.h" |
| 16 #include "net/url_request/url_request.h" | 19 #include "net/url_request/url_request.h" |
| 17 | 20 |
| 18 namespace { | 21 namespace { |
| 19 const char kActionCannotBeExecuted[] = "An action can never be executed " | 22 |
| 23 const char kActionCannotBeExecuted[] = "The action '*' can never be executed " |
| 20 "because there are is no time in the request life-cycle during which the " | 24 "because there are is no time in the request life-cycle during which the " |
| 21 "conditions can be checked and the action can possibly be executed."; | 25 "conditions can be checked and the action can possibly be executed."; |
| 26 |
| 27 const char kAllURLsPermissionNeeded[] = |
| 28 "To execute the action '*', you need to request host permission for all " |
| 29 "hosts."; |
| 30 |
| 22 } // namespace | 31 } // namespace |
| 23 | 32 |
| 24 namespace extensions { | 33 namespace extensions { |
| 25 | 34 |
| 26 WebRequestRulesRegistry::WebRequestRulesRegistry(Profile* profile, | 35 WebRequestRulesRegistry::WebRequestRulesRegistry(Profile* profile, |
| 27 Delegate* delegate) | 36 Delegate* delegate) |
| 28 : RulesRegistryWithCache(delegate), | 37 : RulesRegistryWithCache(delegate), |
| 29 profile_id_(profile) { | 38 profile_id_(profile) { |
| 30 if (profile) | 39 if (profile) |
| 31 extension_info_map_ = ExtensionSystem::Get(profile)->info_map(); | 40 extension_info_map_ = ExtensionSystem::Get(profile)->info_map(); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 } | 147 } |
| 139 | 148 |
| 140 std::string WebRequestRulesRegistry::AddRulesImpl( | 149 std::string WebRequestRulesRegistry::AddRulesImpl( |
| 141 const std::string& extension_id, | 150 const std::string& extension_id, |
| 142 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) { | 151 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) { |
| 143 base::Time extension_installation_time = | 152 base::Time extension_installation_time = |
| 144 GetExtensionInstallationTime(extension_id); | 153 GetExtensionInstallationTime(extension_id); |
| 145 | 154 |
| 146 std::string error; | 155 std::string error; |
| 147 RulesMap new_webrequest_rules; | 156 RulesMap new_webrequest_rules; |
| 157 const Extension* extension = |
| 158 extension_info_map_->extensions().GetByID(extension_id); |
| 148 | 159 |
| 149 for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator rule = | 160 for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator rule = |
| 150 rules.begin(); rule != rules.end(); ++rule) { | 161 rules.begin(); rule != rules.end(); ++rule) { |
| 151 WebRequestRule::GlobalRuleId rule_id(extension_id, *(*rule)->id); | 162 WebRequestRule::GlobalRuleId rule_id(extension_id, *(*rule)->id); |
| 152 DCHECK(webrequest_rules_.find(rule_id) == webrequest_rules_.end()); | 163 DCHECK(webrequest_rules_.find(rule_id) == webrequest_rules_.end()); |
| 153 | 164 |
| 154 scoped_ptr<WebRequestRule> webrequest_rule( | 165 scoped_ptr<WebRequestRule> webrequest_rule(WebRequestRule::Create( |
| 155 WebRequestRule::Create(url_matcher_.condition_factory(), extension_id, | 166 url_matcher_.condition_factory(), |
| 156 extension_installation_time, *rule, | 167 extension_id, extension_installation_time, *rule, |
| 157 &CheckConsistency, &error)); | 168 base::Bind(&Checker, base::Unretained(extension)), |
| 169 &error)); |
| 158 if (!error.empty()) { | 170 if (!error.empty()) { |
| 159 // We don't return here, because we want to clear temporary | 171 // We don't return here, because we want to clear temporary |
| 160 // condition sets in the url_matcher_. | 172 // condition sets in the url_matcher_. |
| 161 break; | 173 break; |
| 162 } | 174 } |
| 163 | 175 |
| 164 new_webrequest_rules[rule_id] = make_linked_ptr(webrequest_rule.release()); | 176 new_webrequest_rules[rule_id] = make_linked_ptr(webrequest_rule.release()); |
| 165 } | 177 } |
| 166 | 178 |
| 167 if (!error.empty()) { | 179 if (!error.empty()) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 193 i != new_webrequest_rules.end(); ++i) { | 205 i != new_webrequest_rules.end(); ++i) { |
| 194 i->second->conditions().GetURLMatcherConditionSets(&all_new_condition_sets); | 206 i->second->conditions().GetURLMatcherConditionSets(&all_new_condition_sets); |
| 195 if (i->second->conditions().HasConditionsWithoutUrls()) | 207 if (i->second->conditions().HasConditionsWithoutUrls()) |
| 196 rules_with_untriggered_conditions_.insert(i->second.get()); | 208 rules_with_untriggered_conditions_.insert(i->second.get()); |
| 197 } | 209 } |
| 198 url_matcher_.AddConditionSets(all_new_condition_sets); | 210 url_matcher_.AddConditionSets(all_new_condition_sets); |
| 199 | 211 |
| 200 ClearCacheOnNavigation(); | 212 ClearCacheOnNavigation(); |
| 201 | 213 |
| 202 if (profile_id_ && !webrequest_rules_.empty()) { | 214 if (profile_id_ && !webrequest_rules_.empty()) { |
| 203 const Extension* extension = | |
| 204 extension_info_map_->extensions().GetByID(extension_id); | |
| 205 | |
| 206 BrowserThread::PostTask( | 215 BrowserThread::PostTask( |
| 207 BrowserThread::UI, FROM_HERE, | 216 BrowserThread::UI, FROM_HERE, |
| 208 base::Bind(&extension_web_request_api_helpers::NotifyWebRequestAPIUsed, | 217 base::Bind(&extension_web_request_api_helpers::NotifyWebRequestAPIUsed, |
| 209 profile_id_, make_scoped_refptr(extension))); | 218 profile_id_, make_scoped_refptr(extension))); |
| 210 } | 219 } |
| 211 | 220 |
| 212 return std::string(); | 221 return std::string(); |
| 213 } | 222 } |
| 214 | 223 |
| 215 std::string WebRequestRulesRegistry::RemoveRulesImpl( | 224 std::string WebRequestRulesRegistry::RemoveRulesImpl( |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 282 |
| 274 bool WebRequestRulesRegistry::IsEmpty() const { | 283 bool WebRequestRulesRegistry::IsEmpty() const { |
| 275 return rule_triggers_.empty() && webrequest_rules_.empty() && | 284 return rule_triggers_.empty() && webrequest_rules_.empty() && |
| 276 url_matcher_.IsEmpty(); | 285 url_matcher_.IsEmpty(); |
| 277 } | 286 } |
| 278 | 287 |
| 279 WebRequestRulesRegistry::~WebRequestRulesRegistry() {} | 288 WebRequestRulesRegistry::~WebRequestRulesRegistry() {} |
| 280 | 289 |
| 281 base::Time WebRequestRulesRegistry::GetExtensionInstallationTime( | 290 base::Time WebRequestRulesRegistry::GetExtensionInstallationTime( |
| 282 const std::string& extension_id) const { | 291 const std::string& extension_id) const { |
| 283 if (!extension_info_map_.get()) // May be NULL during testing. | |
| 284 return base::Time(); | |
| 285 | |
| 286 return extension_info_map_->GetInstallTime(extension_id); | 292 return extension_info_map_->GetInstallTime(extension_id); |
| 287 } | 293 } |
| 288 | 294 |
| 289 void WebRequestRulesRegistry::ClearCacheOnNavigation() { | 295 void WebRequestRulesRegistry::ClearCacheOnNavigation() { |
| 290 extension_web_request_api_helpers::ClearCacheOnNavigation(); | 296 extension_web_request_api_helpers::ClearCacheOnNavigation(); |
| 291 } | 297 } |
| 292 | 298 |
| 293 // static | 299 // static |
| 294 bool WebRequestRulesRegistry::CheckConsistency( | 300 bool WebRequestRulesRegistry::Checker(const Extension* extension, |
| 295 const WebRequestConditionSet* conditions, | 301 const WebRequestConditionSet* conditions, |
| 302 const WebRequestActionSet* actions, |
| 303 std::string* error) { |
| 304 return (StageChecker(conditions, actions, error) && |
| 305 HostPermissionsChecker(extension, actions, error)); |
| 306 } |
| 307 |
| 308 // static |
| 309 bool WebRequestRulesRegistry::HostPermissionsChecker( |
| 310 const Extension* extension, |
| 296 const WebRequestActionSet* actions, | 311 const WebRequestActionSet* actions, |
| 297 std::string* error) { | 312 std::string* error) { |
| 298 // Actions and conditions can be checked and executed in specific phases | 313 if (extension->HasEffectiveAccessToAllHosts()) |
| 299 // of each web request. We consider a rule inconsistent if there is an action | 314 return true; |
| 300 // that cannot be triggered by any condition. | 315 |
| 316 // Without the permission for all URLs, actions with the STRATEGY_DEFAULT |
| 317 // should not be registered, they would never be able to execute. |
| 301 for (WebRequestActionSet::Actions::const_iterator action_iter = | 318 for (WebRequestActionSet::Actions::const_iterator action_iter = |
| 302 actions->actions().begin(); | 319 actions->actions().begin(); |
| 303 action_iter != actions->actions().end(); | 320 action_iter != actions->actions().end(); |
| 304 ++action_iter) { | 321 ++action_iter) { |
| 305 bool found_matching_condition = false; | 322 if ((*action_iter)->host_permissions_strategy() == |
| 306 for (WebRequestConditionSet::Conditions::const_iterator condition_iter = | 323 WebRequestAction::STRATEGY_DEFAULT) { |
| 307 conditions->conditions().begin(); | 324 *error = ErrorUtils::FormatErrorMessage(kAllURLsPermissionNeeded, |
| 308 condition_iter != conditions->conditions().end() && | 325 (*action_iter)->GetName()); |
| 309 !found_matching_condition; | |
| 310 ++condition_iter) { | |
| 311 // Test the intersection of bit masks, this is intentionally & and not &&. | |
| 312 if ((*action_iter)->GetStages() & (*condition_iter)->stages()) | |
| 313 found_matching_condition = true; | |
| 314 } | |
| 315 if (!found_matching_condition) { | |
| 316 *error = kActionCannotBeExecuted; | |
| 317 return false; | 326 return false; |
| 318 } | 327 } |
| 319 } | 328 } |
| 320 return true; | 329 return true; |
| 321 } | 330 } |
| 322 | 331 |
| 332 // static |
| 333 bool WebRequestRulesRegistry::StageChecker( |
| 334 const WebRequestConditionSet* conditions, |
| 335 const WebRequestActionSet* actions, |
| 336 std::string* error) { |
| 337 // Actions and conditions can be checked and executed in specific stages |
| 338 // of each web request. A rule is inconsistent if there is an action that |
| 339 // can only be triggered in stages in which no condition can be evaluated. |
| 340 |
| 341 // In which stages there are conditions to evaluate. |
| 342 int condition_stages = 0; |
| 343 for (WebRequestConditionSet::Conditions::const_iterator condition_iter = |
| 344 conditions->conditions().begin(); |
| 345 condition_iter != conditions->conditions().end(); |
| 346 ++condition_iter) { |
| 347 condition_stages |= (*condition_iter)->stages(); |
| 348 } |
| 349 |
| 350 for (WebRequestActionSet::Actions::const_iterator action_iter = |
| 351 actions->actions().begin(); |
| 352 action_iter != actions->actions().end(); |
| 353 ++action_iter) { |
| 354 // Test the intersection of bit masks, this is intentionally & and not &&. |
| 355 if ((*action_iter)->GetStages() & condition_stages) |
| 356 continue; |
| 357 // We only get here if no matching condition was found. |
| 358 *error = ErrorUtils::FormatErrorMessage(kActionCannotBeExecuted, |
| 359 (*action_iter)->GetName()); |
| 360 return false; |
| 361 } |
| 362 return true; |
| 363 } |
| 323 void WebRequestRulesRegistry::AddTriggeredRules( | 364 void WebRequestRulesRegistry::AddTriggeredRules( |
| 324 const URLMatches& url_matches, | 365 const URLMatches& url_matches, |
| 325 const WebRequestCondition::MatchData& request_data, | 366 const WebRequestCondition::MatchData& request_data, |
| 326 RuleSet* result) const { | 367 RuleSet* result) const { |
| 327 for (URLMatches::const_iterator url_match = url_matches.begin(); | 368 for (URLMatches::const_iterator url_match = url_matches.begin(); |
| 328 url_match != url_matches.end(); ++url_match) { | 369 url_match != url_matches.end(); ++url_match) { |
| 329 RuleTriggers::const_iterator rule_trigger = rule_triggers_.find(*url_match); | 370 RuleTriggers::const_iterator rule_trigger = rule_triggers_.find(*url_match); |
| 330 CHECK(rule_trigger != rule_triggers_.end()); | 371 CHECK(rule_trigger != rule_triggers_.end()); |
| 331 if (!ContainsKey(*result, rule_trigger->second) && | 372 if (!ContainsKey(*result, rule_trigger->second) && |
| 332 rule_trigger->second->conditions().IsFulfilled(*url_match, | 373 rule_trigger->second->conditions().IsFulfilled(*url_match, |
| 333 request_data)) | 374 request_data)) |
| 334 result->insert(rule_trigger->second); | 375 result->insert(rule_trigger->second); |
| 335 } | 376 } |
| 336 } | 377 } |
| 337 | 378 |
| 338 } // namespace extensions | 379 } // namespace extensions |
| OLD | NEW |