OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // This file contains the SdchManager class and two nested classes |
| 6 // (Dictionary, DictionarySet). SdchManager::Dictionary contains all |
| 7 // of the information about an SDCH dictionary. The manager is |
| 8 // responsible for storing those dictionaries, and provides access to |
| 9 // them through DictionarySet objects. A DictionarySet is an object |
| 10 // whose lifetime is under the control of the consumer. It is a |
| 11 // reference to a set of dictionaries, and guarantees that none of |
| 12 // those dictionaries will be destroyed while the DictionarySet |
| 13 // reference is alive. |
| 14 |
5 #ifndef NET_BASE_SDCH_MANAGER_H_ | 15 #ifndef NET_BASE_SDCH_MANAGER_H_ |
6 #define NET_BASE_SDCH_MANAGER_H_ | 16 #define NET_BASE_SDCH_MANAGER_H_ |
7 | 17 |
8 #include <map> | 18 #include <map> |
9 #include <set> | 19 #include <set> |
10 #include <string> | 20 #include <string> |
| 21 #include <vector> |
11 | 22 |
12 #include "base/gtest_prod_util.h" | 23 #include "base/gtest_prod_util.h" |
13 #include "base/memory/ref_counted.h" | 24 #include "base/memory/ref_counted.h" |
14 #include "base/memory/scoped_ptr.h" | 25 #include "base/memory/scoped_ptr.h" |
15 #include "base/observer_list.h" | 26 #include "base/observer_list.h" |
16 #include "base/threading/thread_checker.h" | 27 #include "base/threading/thread_checker.h" |
17 #include "base/time/time.h" | 28 #include "base/time/time.h" |
18 #include "net/base/net_export.h" | 29 #include "net/base/net_export.h" |
19 #include "net/base/sdch_problem_codes.h" | 30 #include "net/base/sdch_problem_codes.h" |
20 #include "url/gurl.h" | 31 #include "url/gurl.h" |
21 | 32 |
22 namespace base { | 33 namespace base { |
| 34 class Clock; |
23 class Value; | 35 class Value; |
24 } | 36 } |
25 | 37 |
26 namespace net { | 38 namespace net { |
27 | 39 |
28 class SdchObserver; | 40 class SdchObserver; |
29 | 41 |
30 // Provides global database of differential decompression dictionaries for the | 42 // Provides global database of differential decompression dictionaries for the |
31 // SDCH filter (processes sdch enconded content). | 43 // SDCH filter (processes sdch enconded content). |
32 // | 44 // |
33 // The SdchManager maintains a collection of memory resident dictionaries. It | 45 // The SdchManager maintains a collection of memory resident dictionaries. It |
34 // can find a dictionary (based on a server specification of a hash), store a | 46 // can find a dictionary (based on a server specification of a hash), store a |
35 // dictionary, and make judgements about what URLs can use, set, etc. a | 47 // dictionary, and make judgements about what URLs can use, set, etc. a |
36 // dictionary. | 48 // dictionary. |
37 | 49 |
38 // These dictionaries are acquired over the net, and include a header | 50 // These dictionaries are acquired over the net, and include a header |
39 // (containing metadata) as well as a VCDIFF dictionary (for use by a VCDIFF | 51 // (containing metadata) as well as a VCDIFF dictionary (for use by a VCDIFF |
40 // module) to decompress data. | 52 // module) to decompress data. |
| 53 // |
| 54 // A dictionary held by the manager may nonetheless outlive the manager if |
| 55 // a DictionarySet object refers to it; see below. |
41 class NET_EXPORT SdchManager { | 56 class NET_EXPORT SdchManager { |
42 public: | 57 public: |
| 58 class Dictionary; |
| 59 typedef std::map<std::string, scoped_refptr<base::RefCountedData<Dictionary>>> |
| 60 DictionaryMap; |
| 61 |
43 // Use the following static limits to block DOS attacks until we implement | 62 // Use the following static limits to block DOS attacks until we implement |
44 // a cached dictionary evicition strategy. | 63 // a cached dictionary evicition strategy. |
45 static const size_t kMaxDictionarySize; | 64 static const size_t kMaxDictionarySize; |
46 static const size_t kMaxDictionaryCount; | 65 static const size_t kMaxDictionaryCount; |
47 | 66 |
48 // There is one instance of |Dictionary| for each memory-cached SDCH | 67 class NET_EXPORT_PRIVATE Dictionary { |
49 // dictionary. | |
50 class NET_EXPORT_PRIVATE Dictionary : public base::RefCounted<Dictionary> { | |
51 public: | 68 public: |
52 // Sdch filters can get our text to use in decoding compressed data. | |
53 const std::string& text() const { return text_; } | |
54 | |
55 private: | |
56 friend class base::RefCounted<Dictionary>; | |
57 friend class SdchManager; // Only manager can construct an instance. | |
58 FRIEND_TEST_ALL_PREFIXES(SdchManagerTest, PathMatch); | |
59 | |
60 // Construct a vc-diff usable dictionary from the dictionary_text starting | 69 // Construct a vc-diff usable dictionary from the dictionary_text starting |
61 // at the given offset. The supplied client_hash should be used to | 70 // at the given offset. The supplied client_hash should be used to |
62 // advertise the dictionary's availability relative to the suppplied URL. | 71 // advertise the dictionary's availability relative to the suppplied URL. |
63 Dictionary(const std::string& dictionary_text, | 72 Dictionary(const std::string& dictionary_text, |
64 size_t offset, | 73 size_t offset, |
65 const std::string& client_hash, | 74 const std::string& client_hash, |
66 const GURL& url, | 75 const GURL& url, |
67 const std::string& domain, | 76 const std::string& domain, |
68 const std::string& path, | 77 const std::string& path, |
69 const base::Time& expiration, | 78 const base::Time& expiration, |
70 const std::set<int>& ports); | 79 const std::set<int>& ports); |
71 virtual ~Dictionary(); | 80 |
| 81 ~Dictionary(); |
| 82 |
| 83 // Sdch filters can get our text to use in decoding compressed data. |
| 84 const std::string& text() const { return text_; } |
72 | 85 |
73 const GURL& url() const { return url_; } | 86 const GURL& url() const { return url_; } |
74 const std::string& client_hash() const { return client_hash_; } | 87 const std::string& client_hash() const { return client_hash_; } |
75 const std::string& domain() const { return domain_; } | 88 const std::string& domain() const { return domain_; } |
76 const std::string& path() const { return path_; } | 89 const std::string& path() const { return path_; } |
77 const base::Time& expiration() const { return expiration_; } | 90 const base::Time& expiration() const { return expiration_; } |
78 const std::set<int>& ports() const { return ports_; } | 91 const std::set<int>& ports() const { return ports_; } |
79 | 92 |
80 // Security method to check if we can advertise this dictionary for use | |
81 // if the |target_url| returns SDCH compressed data. | |
82 SdchProblemCode CanAdvertise(const GURL& target_url) const; | |
83 | |
84 // Security methods to check if we can establish a new dictionary with the | 93 // Security methods to check if we can establish a new dictionary with the |
85 // given data, that arrived in response to get of dictionary_url. | 94 // given data, that arrived in response to get of dictionary_url. |
86 static SdchProblemCode CanSet(const std::string& domain, | 95 static SdchProblemCode CanSet(const std::string& domain, |
87 const std::string& path, | 96 const std::string& path, |
88 const std::set<int>& ports, | 97 const std::set<int>& ports, |
89 const GURL& dictionary_url); | 98 const GURL& dictionary_url); |
90 | 99 |
91 // Security method to check if we can use a dictionary to decompress a | 100 // Security method to check if we can use a dictionary to decompress a |
92 // target that arrived with a reference to this dictionary. | 101 // target that arrived with a reference to this dictionary. |
93 SdchProblemCode CanUse(const GURL& referring_url) const; | 102 SdchProblemCode CanUse(const GURL& referring_url) const; |
94 | 103 |
95 // Compare paths to see if they "match" for dictionary use. | 104 // Compare paths to see if they "match" for dictionary use. |
96 static bool PathMatch(const std::string& path, | 105 static bool PathMatch(const std::string& path, |
97 const std::string& restriction); | 106 const std::string& restriction); |
98 | 107 |
99 // Compare domains to see if the "match" for dictionary use. | 108 // Compare domains to see if the "match" for dictionary use. |
100 static bool DomainMatch(const GURL& url, const std::string& restriction); | 109 static bool DomainMatch(const GURL& url, const std::string& restriction); |
101 | 110 |
| 111 // Is this dictionary expired? |
| 112 bool Expired() const; |
| 113 |
| 114 void SetClockForTesting(scoped_ptr<base::Clock> clock); |
| 115 |
| 116 private: |
| 117 friend class base::RefCountedData<Dictionary>; |
| 118 |
| 119 // Private copy-constructor to support RefCountedData<>, which requires |
| 120 // that an object stored in it be either DefaultConstructible or |
| 121 // CopyConstructible |
| 122 Dictionary(const Dictionary& rhs); |
| 123 |
102 // The actual text of the dictionary. | 124 // The actual text of the dictionary. |
103 std::string text_; | 125 std::string text_; |
104 | 126 |
105 // Part of the hash of text_ that the client uses to advertise the fact that | 127 // Part of the hash of text_ that the client uses to advertise the fact that |
106 // it has a specific dictionary pre-cached. | 128 // it has a specific dictionary pre-cached. |
107 std::string client_hash_; | 129 std::string client_hash_; |
108 | 130 |
109 // The GURL that arrived with the text_ in a URL request to specify where | 131 // The GURL that arrived with the text_ in a URL request to specify where |
110 // this dictionary may be used. | 132 // this dictionary may be used. |
111 const GURL url_; | 133 const GURL url_; |
112 | 134 |
113 // Metadate "headers" in before dictionary text contained the following: | 135 // Metadate "headers" in before dictionary text contained the following: |
114 // Each dictionary payload consists of several headers, followed by the text | 136 // Each dictionary payload consists of several headers, followed by the text |
115 // of the dictionary. The following are the known headers. | 137 // of the dictionary. The following are the known headers. |
116 const std::string domain_; | 138 const std::string domain_; |
117 const std::string path_; | 139 const std::string path_; |
118 const base::Time expiration_; // Implied by max-age. | 140 const base::Time expiration_; // Implied by max-age. |
119 const std::set<int> ports_; | 141 const std::set<int> ports_; |
120 | 142 |
121 DISALLOW_COPY_AND_ASSIGN(Dictionary); | 143 scoped_ptr<base::Clock> clock_; |
| 144 |
| 145 void operator=(const Dictionary&) = delete; |
| 146 }; |
| 147 |
| 148 // A handle for one or more dictionaries which will keep the dictionaries |
| 149 // alive and accessible for the handle's lifetime. |
| 150 class NET_EXPORT_PRIVATE DictionarySet { |
| 151 public: |
| 152 ~DictionarySet(); |
| 153 |
| 154 // Return a comma separated list of client hashes. |
| 155 std::string GetDictionaryClientHashList() const; |
| 156 |
| 157 // Lookup a given dictionary based on server hash. Returned pointer |
| 158 // is guaranteed to be valid for the lifetime of the DictionarySet. |
| 159 // Returns NULL if hash is not a valid server hash for a dictionary |
| 160 // named by DictionarySet. |
| 161 const SdchManager::Dictionary* GetDictionary(const std::string& hash) const; |
| 162 |
| 163 bool Empty() const; |
| 164 |
| 165 private: |
| 166 // A DictionarySet may only be constructed by the SdchManager. |
| 167 friend class SdchManager; |
| 168 |
| 169 DictionarySet(); |
| 170 void AddDictionary(const std::string& server_hash, |
| 171 const scoped_refptr<base::RefCountedData< |
| 172 SdchManager::Dictionary>>& dictionary); |
| 173 |
| 174 DictionaryMap dictionaries_; |
| 175 |
| 176 DISALLOW_COPY_AND_ASSIGN(DictionarySet); |
122 }; | 177 }; |
123 | 178 |
124 SdchManager(); | 179 SdchManager(); |
125 ~SdchManager(); | 180 ~SdchManager(); |
126 | 181 |
127 // Clear data (for browser data removal). | 182 // Clear data (for browser data removal). |
128 void ClearData(); | 183 void ClearData(); |
129 | 184 |
130 // Record stats on various errors. | 185 // Record stats on various errors. |
131 static void SdchErrorRecovery(SdchProblemCode problem); | 186 static void SdchErrorRecovery(SdchProblemCode problem); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 // supported domain (i.e., not blacklisted, and either the specific supported | 226 // supported domain (i.e., not blacklisted, and either the specific supported |
172 // domain, or all domains were assumed supported). If it is blacklist, reduce | 227 // domain, or all domains were assumed supported). If it is blacklist, reduce |
173 // by 1 the number of times it will be reported as blacklisted. | 228 // by 1 the number of times it will be reported as blacklisted. |
174 SdchProblemCode IsInSupportedDomain(const GURL& url); | 229 SdchProblemCode IsInSupportedDomain(const GURL& url); |
175 | 230 |
176 // Send out appropriate events notifying observers that a Get-Dictionary | 231 // Send out appropriate events notifying observers that a Get-Dictionary |
177 // header has been seen. | 232 // header has been seen. |
178 SdchProblemCode OnGetDictionary(const GURL& request_url, | 233 SdchProblemCode OnGetDictionary(const GURL& request_url, |
179 const GURL& dictionary_url); | 234 const GURL& dictionary_url); |
180 | 235 |
181 // Find the vcdiff dictionary (the body of the sdch dictionary that appears | 236 // Get a handle to the available dictionaries that might be used |
182 // after the meta-data headers like Domain:...) with the given |server_hash| | 237 // for encoding responses for the given URL. The return set will not |
183 // to use to decompreses data that arrived as SDCH encoded content. Check to | 238 // include expired dictionaries. If no dictionaries |
184 // be sure the returned |dictionary| can be used for decoding content supplied | 239 // are appropriate to use with the target_url, NULL is returned. |
185 // in response to a request for |referring_url|. | 240 scoped_ptr<DictionarySet> GetDictionarySet(const GURL& target_url); |
186 // Return null in |dictionary| if there is no matching legal dictionary. | |
187 // Returns SDCH_OK if dictionary is not found, SDCH(-over-https) is disabled, | |
188 // or if matching legal dictionary exists. Otherwise returns the | |
189 // corresponding problem code. | |
190 SdchProblemCode GetVcdiffDictionary(const std::string& server_hash, | |
191 const GURL& referring_url, | |
192 scoped_refptr<Dictionary>* dictionary); | |
193 | 241 |
194 // Get list of available (pre-cached) dictionaries that we have already loaded | 242 // Get a handle to a specific dictionary, by its server hash, confirming |
195 // into memory. The list is a comma separated list of (client) hashes per | 243 // that that specific dictionary is appropriate to use with |target_url|. |
196 // the SDCH spec. | 244 // Expired dictionaries will be returned. If no dictionary with that |
197 void GetAvailDictionaryList(const GURL& target_url, std::string* list); | 245 // hash exists that is usable with |target_url|, NULL is returned. |
| 246 // If there is a usability problem, |*error_code| is set to the |
| 247 // appropriate problem code. |
| 248 scoped_ptr<DictionarySet> GetDictionarySetByHash( |
| 249 const GURL& target_url, |
| 250 const std::string& server_hash, |
| 251 SdchProblemCode* problem_code); |
198 | 252 |
199 // Construct the pair of hashes for client and server to identify an SDCH | 253 // Construct the pair of hashes for client and server to identify an SDCH |
200 // dictionary. This is only made public to facilitate unit testing, but is | 254 // dictionary. This is only made public to facilitate unit testing, but is |
201 // otherwise private | 255 // otherwise private |
202 static void GenerateHash(const std::string& dictionary_text, | 256 static void GenerateHash(const std::string& dictionary_text, |
203 std::string* client_hash, std::string* server_hash); | 257 std::string* client_hash, std::string* server_hash); |
204 | 258 |
205 // For Latency testing only, we need to know if we've succeeded in doing a | 259 // For Latency testing only, we need to know if we've succeeded in doing a |
206 // round trip before starting our comparative tests. If ever we encounter | 260 // round trip before starting our comparative tests. If ever we encounter |
207 // problems with SDCH, we opt-out of the test unless/until we perform a | 261 // problems with SDCH, we opt-out of the test unless/until we perform a |
(...skipping 10 matching lines...) Expand all Loading... |
218 // dictionary_url; dictionary already added, etc.). | 272 // dictionary_url; dictionary already added, etc.). |
219 // Returns SDCH_OK if the addition was successfull, and corresponding error | 273 // Returns SDCH_OK if the addition was successfull, and corresponding error |
220 // code otherwise. | 274 // code otherwise. |
221 SdchProblemCode AddSdchDictionary(const std::string& dictionary_text, | 275 SdchProblemCode AddSdchDictionary(const std::string& dictionary_text, |
222 const GURL& dictionary_url); | 276 const GURL& dictionary_url); |
223 | 277 |
224 // Registration for events generated by the SDCH subsystem. | 278 // Registration for events generated by the SDCH subsystem. |
225 void AddObserver(SdchObserver* observer); | 279 void AddObserver(SdchObserver* observer); |
226 void RemoveObserver(SdchObserver* observer); | 280 void RemoveObserver(SdchObserver* observer); |
227 | 281 |
| 282 static scoped_ptr<DictionarySet> CreateEmptyDictionarySetForTesting(); |
| 283 |
228 private: | 284 private: |
229 struct BlacklistInfo { | 285 struct BlacklistInfo { |
230 BlacklistInfo() : count(0), exponential_count(0), reason(SDCH_OK) {} | 286 BlacklistInfo() : count(0), exponential_count(0), reason(SDCH_OK) {} |
231 | 287 |
232 int count; // # of times to refuse SDCH advertisement. | 288 int count; // # of times to refuse SDCH advertisement. |
233 int exponential_count; // Current exponential backoff ratchet. | 289 int exponential_count; // Current exponential backoff ratchet. |
234 SdchProblemCode reason; // Why domain was blacklisted. | 290 SdchProblemCode reason; // Why domain was blacklisted. |
235 }; | 291 }; |
| 292 |
236 typedef std::map<std::string, BlacklistInfo> DomainBlacklistInfo; | 293 typedef std::map<std::string, BlacklistInfo> DomainBlacklistInfo; |
237 typedef std::set<std::string> ExperimentSet; | 294 typedef std::set<std::string> ExperimentSet; |
238 | 295 |
239 // Determines whether a "Get-Dictionary" header is legal (dictionary | 296 // Determines whether a "Get-Dictionary" header is legal (dictionary |
240 // url has appropriate relationship to referrer url) in the SDCH | 297 // url has appropriate relationship to referrer url) in the SDCH |
241 // protocol. Return SDCH_OK if fetch is legal. | 298 // protocol. Return SDCH_OK if fetch is legal. |
242 SdchProblemCode CanFetchDictionary(const GURL& referring_url, | 299 SdchProblemCode CanFetchDictionary(const GURL& referring_url, |
243 const GURL& dictionary_url) const; | 300 const GURL& dictionary_url) const; |
244 | 301 |
245 // A map of dictionaries info indexed by the hash that the server provides. | |
246 typedef std::map<std::string, scoped_refptr<Dictionary> > DictionaryMap; | |
247 | |
248 // Support SDCH compression, by advertising in headers. | 302 // Support SDCH compression, by advertising in headers. |
249 static bool g_sdch_enabled_; | 303 static bool g_sdch_enabled_; |
250 | 304 |
251 // Support SDCH compression for HTTPS requests and responses. When supported, | 305 // Support SDCH compression for HTTPS requests and responses. When supported, |
252 // HTTPS applicable dictionaries MUST have been acquired securely via HTTPS. | 306 // HTTPS applicable dictionaries MUST have been acquired securely via HTTPS. |
253 static bool g_secure_scheme_supported_; | 307 static bool g_secure_scheme_supported_; |
254 | 308 |
255 // A simple implementation of a RFC 3548 "URL safe" base64 encoder. | 309 // A simple implementation of a RFC 3548 "URL safe" base64 encoder. |
256 static void UrlSafeBase64Encode(const std::string& input, | 310 static void UrlSafeBase64Encode(const std::string& input, |
257 std::string* output); | 311 std::string* output); |
(...skipping 14 matching lines...) Expand all Loading... |
272 ObserverList<SdchObserver, true> observers_; | 326 ObserverList<SdchObserver, true> observers_; |
273 | 327 |
274 base::ThreadChecker thread_checker_; | 328 base::ThreadChecker thread_checker_; |
275 | 329 |
276 DISALLOW_COPY_AND_ASSIGN(SdchManager); | 330 DISALLOW_COPY_AND_ASSIGN(SdchManager); |
277 }; | 331 }; |
278 | 332 |
279 } // namespace net | 333 } // namespace net |
280 | 334 |
281 #endif // NET_BASE_SDCH_MANAGER_H_ | 335 #endif // NET_BASE_SDCH_MANAGER_H_ |
OLD | NEW |