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 3 // found in the LICENSE file. 4 5 #ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_ 6 #define EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_ 7 8 #include <list> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <vector> 13 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/linked_ptr.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/time/time.h" 19 #include "components/url_matcher/url_matcher.h" 20 #include "extensions/browser/api/declarative/declarative_rule.h" 21 #include "extensions/browser/api/declarative/rules_registry.h" 22 #include "extensions/browser/api/declarative_webrequest/request_stage.h" 23 #include "extensions/browser/api/declarative_webrequest/webrequest_action.h" 24 #include "extensions/browser/api/declarative_webrequest/webrequest_condition.h" 25 #include "extensions/browser/info_map.h" 26 27 class WebRequestPermissions; 28 29 namespace content { 30 class BrowserContext; 31 } 32 33 namespace extension_web_request_api_helpers { 34 struct EventResponseDelta; 35 } 36 37 namespace net { 38 class URLRequest; 39 } 40 41 namespace extensions { 42 43 class RulesRegistryService; 44 45 typedef linked_ptr<extension_web_request_api_helpers::EventResponseDelta> 46 LinkedPtrEventResponseDelta; 47 typedef DeclarativeRule<WebRequestCondition, WebRequestAction> WebRequestRule; 48 49 // The WebRequestRulesRegistry is responsible for managing 50 // the internal representation of rules for the Declarative Web Request API. 51 // 52 // Here is the high level overview of this functionality: 53 // 54 // RulesRegistry::Rule consists of Conditions and Actions, these are 55 // represented as a WebRequestRule with WebRequestConditions and 56 // WebRequestRuleActions. 57 // 58 // WebRequestConditions represent JSON dictionaries as the following: 59 // { 60 // 'instanceType': 'URLMatcher', 61 // 'host_suffix': 'example.com', 62 // 'path_prefix': '/query', 63 // 'scheme': 'http' 64 // } 65 // 66 // The evaluation of URL related condition attributes (host_suffix, path_prefix) 67 // is delegated to a URLMatcher, because this is capable of evaluating many 68 // of such URL related condition attributes in parallel. 69 // 70 // For this, the URLRequestCondition has a URLMatcherConditionSet, which 71 // represents the {'host_suffix': 'example.com', 'path_prefix': '/query'} part. 72 // We will then ask the URLMatcher, whether a given URL 73 // "http://www.example.com/query/" has any matches, and the URLMatcher 74 // will respond with the URLMatcherConditionSet::ID. We can map this 75 // to the WebRequestRule and check whether also the other conditions (in this 76 // example 'scheme': 'http') are fulfilled. 77 class WebRequestRulesRegistry : public RulesRegistry { 78 public: 79 // |cache_delegate| can be NULL. In that case it constructs the registry with 80 // storage functionality suspended. 81 WebRequestRulesRegistry(content::BrowserContext* browser_context, 82 RulesCacheDelegate* cache_delegate, 83 const WebViewKey& webview_key); 84 85 // TODO(battre): This will become an implementation detail, because we need 86 // a way to also execute the actions of the rules. 87 std::set<const WebRequestRule*> GetMatches( 88 const WebRequestData& request_data_without_ids) const; 89 90 // Returns which modifications should be executed on the network request 91 // according to the rules registered in this registry. 92 std::list<LinkedPtrEventResponseDelta> CreateDeltas( 93 const InfoMap* extension_info_map, 94 const WebRequestData& request_data, 95 bool crosses_incognito); 96 97 // Implementation of RulesRegistry: 98 virtual std::string AddRulesImpl( 99 const std::string& extension_id, 100 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) OVERRIDE; 101 virtual std::string RemoveRulesImpl( 102 const std::string& extension_id, 103 const std::vector<std::string>& rule_identifiers) OVERRIDE; 104 virtual std::string RemoveAllRulesImpl( 105 const std::string& extension_id) OVERRIDE; 106 107 // Returns true if this object retains no allocated data. Only for debugging. 108 bool IsEmpty() const; 109 110 protected: 111 virtual ~WebRequestRulesRegistry(); 112 113 // Virtual for testing: 114 virtual base::Time GetExtensionInstallationTime( 115 const std::string& extension_id) const; 116 virtual void ClearCacheOnNavigation(); 117 118 void SetExtensionInfoMapForTesting( 119 scoped_refptr<InfoMap> extension_info_map) { 120 extension_info_map_ = extension_info_map; 121 } 122 123 const std::set<const WebRequestRule*>& 124 rules_with_untriggered_conditions_for_test() const { 125 return rules_with_untriggered_conditions_; 126 } 127 128 private: 129 FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest, StageChecker); 130 FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest, 131 HostPermissionsChecker); 132 133 typedef std::map<url_matcher::URLMatcherConditionSet::ID, WebRequestRule*> 134 RuleTriggers; 135 typedef std::map<WebRequestRule::RuleId, linked_ptr<WebRequestRule> > 136 RulesMap; 137 typedef std::set<url_matcher::URLMatcherConditionSet::ID> URLMatches; 138 typedef std::set<const WebRequestRule*> RuleSet; 139 140 // This bundles all consistency checkers. Returns true in case of consistency 141 // and MUST set |error| otherwise. 142 static bool Checker(const Extension* extension, 143 const WebRequestConditionSet* conditions, 144 const WebRequestActionSet* actions, 145 std::string* error); 146 147 // Check that the |extension| has host permissions for all URLs if actions 148 // requiring them are present. 149 static bool HostPermissionsChecker(const Extension* extension, 150 const WebRequestActionSet* actions, 151 std::string* error); 152 153 // Check that every action is applicable in the same request stage as at 154 // least one condition. 155 static bool StageChecker(const WebRequestConditionSet* conditions, 156 const WebRequestActionSet* actions, 157 std::string* error); 158 159 // Helper for RemoveRulesImpl and RemoveAllRulesImpl. Call this before 160 // deleting |rule| from one of the maps in |webrequest_rules_|. It will erase 161 // the rule from |rule_triggers_| and |rules_with_untriggered_conditions_|, 162 // and add every of the rule's URLMatcherConditionSet to 163 // |remove_from_url_matcher|, so that the caller can remove them from the 164 // matcher later. 165 void CleanUpAfterRule(const WebRequestRule* rule, 166 std::vector<url_matcher::URLMatcherConditionSet::ID>* 167 remove_from_url_matcher); 168 169 // This is a helper function to GetMatches. Rules triggered by |url_matches| 170 // get added to |result| if one of their conditions is fulfilled. 171 // |request_data| gets passed to IsFulfilled of the rules' condition sets. 172 void AddTriggeredRules(const URLMatches& url_matches, 173 const WebRequestCondition::MatchData& request_data, 174 RuleSet* result) const; 175 176 // Map that tells us which WebRequestRule may match under the condition that 177 // the URLMatcherConditionSet::ID was returned by the |url_matcher_|. 178 RuleTriggers rule_triggers_; 179 180 // These rules contain condition sets with conditions without URL attributes. 181 // Such conditions are not triggered by URL matcher, so we need to test them 182 // separately. 183 std::set<const WebRequestRule*> rules_with_untriggered_conditions_; 184 185 std::map<WebRequestRule::ExtensionId, RulesMap> webrequest_rules_; 186 187 url_matcher::URLMatcher url_matcher_; 188 189 content::BrowserContext* browser_context_; 190 scoped_refptr<InfoMap> extension_info_map_; 191 192 DISALLOW_COPY_AND_ASSIGN(WebRequestRulesRegistry); 193 }; 194 195 } // namespace extensions 196 197 #endif // EXTENSIONS_BROWSER_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_ 198