| 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 #ifndef CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ | 5 #ifndef CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ |
| 6 #define CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ | 6 #define CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 // A class that implements Chrome's interface with the SafeBrowsing protocol. | 9 // A class that implements Chrome's interface with the SafeBrowsing protocol. |
| 10 // The SafeBrowsingProtocolManager handles formatting and making requests of, | 10 // The SafeBrowsingProtocolManager handles formatting and making requests of, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 class SafeBrowsingProtocolManager; | 43 class SafeBrowsingProtocolManager; |
| 44 // Interface of a factory to create ProtocolManager. Useful for tests. | 44 // Interface of a factory to create ProtocolManager. Useful for tests. |
| 45 class SBProtocolManagerFactory { | 45 class SBProtocolManagerFactory { |
| 46 public: | 46 public: |
| 47 SBProtocolManagerFactory() {} | 47 SBProtocolManagerFactory() {} |
| 48 virtual ~SBProtocolManagerFactory() {} | 48 virtual ~SBProtocolManagerFactory() {} |
| 49 virtual SafeBrowsingProtocolManager* CreateProtocolManager( | 49 virtual SafeBrowsingProtocolManager* CreateProtocolManager( |
| 50 SafeBrowsingService* sb_service, | 50 SafeBrowsingService* sb_service, |
| 51 const std::string& client_name, | 51 const std::string& client_name, |
| 52 const std::string& client_key, | |
| 53 const std::string& wrapped_key, | |
| 54 net::URLRequestContextGetter* request_context_getter, | 52 net::URLRequestContextGetter* request_context_getter, |
| 55 const std::string& info_url_prefix, | 53 const std::string& url_prefix, |
| 56 const std::string& mackey_url_prefix, | |
| 57 bool disable_auto_update) = 0; | 54 bool disable_auto_update) = 0; |
| 58 private: | 55 private: |
| 59 DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactory); | 56 DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactory); |
| 60 }; | 57 }; |
| 61 | 58 |
| 62 class SafeBrowsingProtocolManager : public content::URLFetcherDelegate { | 59 class SafeBrowsingProtocolManager : public content::URLFetcherDelegate { |
| 63 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestBackOffTimes); | 60 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestBackOffTimes); |
| 64 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestChunkStrings); | 61 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestChunkStrings); |
| 65 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestGetHashUrl); | 62 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestGetHashUrl); |
| 66 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, | 63 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, |
| 67 TestGetHashBackOffTimes); | 64 TestGetHashBackOffTimes); |
| 68 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestMacKeyUrl); | |
| 69 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, | 65 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, |
| 70 TestSafeBrowsingHitUrl); | 66 TestSafeBrowsingHitUrl); |
| 71 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, | 67 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, |
| 72 TestMalwareDetailsUrl); | 68 TestMalwareDetailsUrl); |
| 73 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestNextChunkUrl); | 69 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestNextChunkUrl); |
| 74 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestUpdateUrl); | 70 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestUpdateUrl); |
| 75 friend class SafeBrowsingServiceTest; | 71 friend class SafeBrowsingServiceTest; |
| 76 | 72 |
| 77 public: | 73 public: |
| 78 virtual ~SafeBrowsingProtocolManager(); | 74 virtual ~SafeBrowsingProtocolManager(); |
| 79 | 75 |
| 80 // Makes the passed |factory| the factory used to instantiate | 76 // Makes the passed |factory| the factory used to instantiate |
| 81 // a SafeBrowsingService. Useful for tests. | 77 // a SafeBrowsingService. Useful for tests. |
| 82 static void RegisterFactory(SBProtocolManagerFactory* factory) { | 78 static void RegisterFactory(SBProtocolManagerFactory* factory) { |
| 83 factory_ = factory; | 79 factory_ = factory; |
| 84 } | 80 } |
| 85 | 81 |
| 86 // Create an instance of the safe browsing service. | 82 // Create an instance of the safe browsing service. |
| 87 static SafeBrowsingProtocolManager* Create( | 83 static SafeBrowsingProtocolManager* Create( |
| 88 SafeBrowsingService* sb_service, | 84 SafeBrowsingService* sb_service, |
| 89 const std::string& client_name, | 85 const std::string& client_name, |
| 90 const std::string& client_key, | |
| 91 const std::string& wrapped_key, | |
| 92 net::URLRequestContextGetter* request_context_getter, | 86 net::URLRequestContextGetter* request_context_getter, |
| 93 const std::string& info_url_prefix, | 87 const std::string& url_prefix, |
| 94 const std::string& mackey_url_prefix, | |
| 95 bool disable_auto_update); | 88 bool disable_auto_update); |
| 96 | 89 |
| 97 // Sets up the update schedule and internal state for making periodic requests | 90 // Sets up the update schedule and internal state for making periodic requests |
| 98 // of the SafeBrowsing service. | 91 // of the SafeBrowsing service. |
| 99 virtual void Initialize(); | 92 virtual void Initialize(); |
| 100 | 93 |
| 101 // content::URLFetcherDelegate interface. | 94 // content::URLFetcherDelegate interface. |
| 102 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE; | 95 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE; |
| 103 | 96 |
| 104 // API used by the SafeBrowsingService for issuing queries. When the results | 97 // API used by the SafeBrowsingService for issuing queries. When the results |
| (...skipping 24 matching lines...) Expand all Loading... |
| 129 const GURL& page_url, | 122 const GURL& page_url, |
| 130 const GURL& referrer_url, | 123 const GURL& referrer_url, |
| 131 bool is_subresource, | 124 bool is_subresource, |
| 132 SafeBrowsingService::UrlCheckResult threat_type, | 125 SafeBrowsingService::UrlCheckResult threat_type, |
| 133 const std::string& post_data); | 126 const std::string& post_data); |
| 134 | 127 |
| 135 // Users can opt-in on the SafeBrowsing interstitial to send detailed | 128 // Users can opt-in on the SafeBrowsing interstitial to send detailed |
| 136 // malware reports. |report| is the serialized report. | 129 // malware reports. |report| is the serialized report. |
| 137 void ReportMalwareDetails(const std::string& report); | 130 void ReportMalwareDetails(const std::string& report); |
| 138 | 131 |
| 139 bool is_initial_request() const { return initial_request_; } | |
| 140 | |
| 141 // The last time we received an update. | 132 // The last time we received an update. |
| 142 base::Time last_update() const { return last_update_; } | 133 base::Time last_update() const { return last_update_; } |
| 143 | 134 |
| 144 // Setter for additional_query_. To make sure the additional_query_ won't | 135 // Setter for additional_query_. To make sure the additional_query_ won't |
| 145 // be changed in the middle of an update, caller (e.g.: SafeBrowsingService) | 136 // be changed in the middle of an update, caller (e.g.: SafeBrowsingService) |
| 146 // should call this after callbacks triggered in UpdateFinished() or before | 137 // should call this after callbacks triggered in UpdateFinished() or before |
| 147 // IssueUpdateRequest(). | 138 // IssueUpdateRequest(). |
| 148 void set_additional_query(const std::string& query) { | 139 void set_additional_query(const std::string& query) { |
| 149 additional_query_ = query; | 140 additional_query_ = query; |
| 150 } | 141 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 ResultType result_type); | 177 ResultType result_type); |
| 187 | 178 |
| 188 protected: | 179 protected: |
| 189 // Constructs a SafeBrowsingProtocolManager for |sb_service| that issues | 180 // Constructs a SafeBrowsingProtocolManager for |sb_service| that issues |
| 190 // network requests using |request_context_getter|. When |disable_auto_update| | 181 // network requests using |request_context_getter|. When |disable_auto_update| |
| 191 // is true, protocol manager won't schedule next update until | 182 // is true, protocol manager won't schedule next update until |
| 192 // ForceScheduleNextUpdate is called. | 183 // ForceScheduleNextUpdate is called. |
| 193 SafeBrowsingProtocolManager( | 184 SafeBrowsingProtocolManager( |
| 194 SafeBrowsingService* sb_service, | 185 SafeBrowsingService* sb_service, |
| 195 const std::string& client_name, | 186 const std::string& client_name, |
| 196 const std::string& client_key, | |
| 197 const std::string& wrapped_key, | |
| 198 net::URLRequestContextGetter* request_context_getter, | 187 net::URLRequestContextGetter* request_context_getter, |
| 199 const std::string& http_url_prefix, | 188 const std::string& url_prefix, |
| 200 const std::string& https_url_prefix, | |
| 201 bool disable_auto_update); | 189 bool disable_auto_update); |
| 202 | 190 |
| 203 private: | 191 private: |
| 204 friend class SBProtocolManagerFactoryImpl; | 192 friend class SBProtocolManagerFactoryImpl; |
| 205 | 193 |
| 206 // Internal API for fetching information from the SafeBrowsing servers. The | 194 // Internal API for fetching information from the SafeBrowsing servers. The |
| 207 // GetHash requests are higher priority since they can block user requests | 195 // GetHash requests are higher priority since they can block user requests |
| 208 // so are handled separately. | 196 // so are handled separately. |
| 209 enum SafeBrowsingRequestType { | 197 enum SafeBrowsingRequestType { |
| 210 NO_REQUEST = 0, // No requests in progress | 198 NO_REQUEST = 0, // No requests in progress |
| 211 UPDATE_REQUEST, // Request for redirect URLs | 199 UPDATE_REQUEST, // Request for redirect URLs |
| 212 CHUNK_REQUEST, // Request for a specific chunk | 200 CHUNK_REQUEST, // Request for a specific chunk |
| 213 GETKEY_REQUEST // Update the client's MAC key | |
| 214 }; | 201 }; |
| 215 | 202 |
| 216 // Composes a URL using |prefix|, |method| (e.g.: gethash, download, | 203 // Composes a URL using |prefix|, |method| (e.g.: gethash, download, report). |
| 217 // newkey, report), |client_name| and |version|. When not empty, | 204 // |client_name| and |version|. When not empty, |additional_query| is |
| 218 // |additional_query| is appended to the URL with an additional "&" | 205 // appended to the URL with an additional "&" in the front. |
| 219 // in the front. | |
| 220 static std::string ComposeUrl(const std::string& prefix, | 206 static std::string ComposeUrl(const std::string& prefix, |
| 221 const std::string& method, | 207 const std::string& method, |
| 222 const std::string& client_name, | 208 const std::string& client_name, |
| 223 const std::string& version, | 209 const std::string& version, |
| 224 const std::string& additional_query); | 210 const std::string& additional_query); |
| 225 | 211 |
| 226 // Generates Update URL for querying about the latest set of chunk updates. | 212 // Generates Update URL for querying about the latest set of chunk updates. |
| 227 // Append "wrkey=xxx" to the URL when |use_mac| is true. | 213 GURL UpdateUrl() const; |
| 228 GURL UpdateUrl(bool use_mac) const; | |
| 229 // Generates GetHash request URL for retrieving full hashes. | 214 // Generates GetHash request URL for retrieving full hashes. |
| 230 // Append "wrkey=xxx" to the URL when |use_mac| is true. | 215 GURL GetHashUrl() const; |
| 231 GURL GetHashUrl(bool use_mac) const; | |
| 232 // Generates new MAC client key request URL. | |
| 233 GURL MacKeyUrl() const; | |
| 234 // Generates URL for reporting safe browsing hits for UMA users. | 216 // Generates URL for reporting safe browsing hits for UMA users. |
| 235 GURL SafeBrowsingHitUrl( | 217 GURL SafeBrowsingHitUrl( |
| 236 const GURL& malicious_url, const GURL& page_url, const GURL& referrer_url, | 218 const GURL& malicious_url, const GURL& page_url, const GURL& referrer_url, |
| 237 bool is_subresource, | 219 bool is_subresource, |
| 238 SafeBrowsingService::UrlCheckResult threat_type) const; | 220 SafeBrowsingService::UrlCheckResult threat_type) const; |
| 239 // Generates URL for reporting malware details for users who opt-in. | 221 // Generates URL for reporting malware details for users who opt-in. |
| 240 GURL MalwareDetailsUrl() const; | 222 GURL MalwareDetailsUrl() const; |
| 241 | 223 |
| 242 // Composes a ChunkUrl based on input string. | 224 // Composes a ChunkUrl based on input string. |
| 243 GURL NextChunkUrl(const std::string& input) const; | 225 GURL NextChunkUrl(const std::string& input) const; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 262 // Sends a request for a list of chunks we should download to the SafeBrowsing | 244 // Sends a request for a list of chunks we should download to the SafeBrowsing |
| 263 // servers. In order to format this request, we need to send all the chunk | 245 // servers. In order to format this request, we need to send all the chunk |
| 264 // numbers for each list that we have to the server. Getting the chunk numbers | 246 // numbers for each list that we have to the server. Getting the chunk numbers |
| 265 // requires a database query (run on the database thread), and the request | 247 // requires a database query (run on the database thread), and the request |
| 266 // is sent upon completion of that query in OnGetChunksComplete. | 248 // is sent upon completion of that query in OnGetChunksComplete. |
| 267 void IssueUpdateRequest(); | 249 void IssueUpdateRequest(); |
| 268 | 250 |
| 269 // Sends a request for a chunk to the SafeBrowsing servers. | 251 // Sends a request for a chunk to the SafeBrowsing servers. |
| 270 void IssueChunkRequest(); | 252 void IssueChunkRequest(); |
| 271 | 253 |
| 272 // Gets a key from the SafeBrowsing servers for use with MAC. This should only | |
| 273 // be called once per client unless the server directly tells us to update. | |
| 274 void IssueKeyRequest(); | |
| 275 | |
| 276 // Formats a string returned from the database into: | 254 // Formats a string returned from the database into: |
| 277 // "list_name;a:<add_chunk_ranges>:s:<sub_chunk_ranges>:mac\n" | 255 // "list_name;a:<add_chunk_ranges>:s:<sub_chunk_ranges>\n" |
| 278 static std::string FormatList(const SBListChunkRanges& list, bool use_mac); | 256 static std::string FormatList(const SBListChunkRanges& list); |
| 279 | 257 |
| 280 // Runs the protocol parser on received data and update the | 258 // Runs the protocol parser on received data and update the |
| 281 // SafeBrowsingService with the new content. Returns 'true' on successful | 259 // SafeBrowsingService with the new content. Returns 'true' on successful |
| 282 // parse, 'false' on error. | 260 // parse, 'false' on error. |
| 283 bool HandleServiceResponse(const GURL& url, const char* data, int length); | 261 bool HandleServiceResponse(const GURL& url, const char* data, int length); |
| 284 | 262 |
| 285 // If the SafeBrowsing service wants us to re-key, we clear our key state and | |
| 286 // issue the request. | |
| 287 void HandleReKey(); | |
| 288 | |
| 289 // Updates internal state for each GetHash response error, assuming that the | 263 // Updates internal state for each GetHash response error, assuming that the |
| 290 // current time is |now|. | 264 // current time is |now|. |
| 291 void HandleGetHashError(const base::Time& now); | 265 void HandleGetHashError(const base::Time& now); |
| 292 | 266 |
| 293 // Helper function for update completion. | 267 // Helper function for update completion. |
| 294 void UpdateFinished(bool success); | 268 void UpdateFinished(bool success); |
| 295 | 269 |
| 296 // A callback that runs if we timeout waiting for a response to an update | 270 // A callback that runs if we timeout waiting for a response to an update |
| 297 // request. We use this to properly set our update state. | 271 // request. We use this to properly set our update state. |
| 298 void UpdateResponseTimeout(); | 272 void UpdateResponseTimeout(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 325 float back_off_fuzz_; | 299 float back_off_fuzz_; |
| 326 | 300 |
| 327 // The list for which we are make a request. | 301 // The list for which we are make a request. |
| 328 std::string list_name_; | 302 std::string list_name_; |
| 329 | 303 |
| 330 // For managing the next earliest time to query the SafeBrowsing servers for | 304 // For managing the next earliest time to query the SafeBrowsing servers for |
| 331 // updates. | 305 // updates. |
| 332 int next_update_sec_; | 306 int next_update_sec_; |
| 333 base::OneShotTimer<SafeBrowsingProtocolManager> update_timer_; | 307 base::OneShotTimer<SafeBrowsingProtocolManager> update_timer_; |
| 334 | 308 |
| 335 // All chunk requests that need to be made, along with their MAC. | 309 // All chunk requests that need to be made. |
| 336 std::deque<ChunkUrl> chunk_request_urls_; | 310 std::deque<ChunkUrl> chunk_request_urls_; |
| 337 | 311 |
| 338 // Map of GetHash requests. | 312 // Map of GetHash requests. |
| 339 typedef base::hash_map<const content::URLFetcher*, | 313 typedef base::hash_map<const content::URLFetcher*, |
| 340 SafeBrowsingService::SafeBrowsingCheck*> HashRequests; | 314 SafeBrowsingService::SafeBrowsingCheck*> HashRequests; |
| 341 HashRequests hash_requests_; | 315 HashRequests hash_requests_; |
| 342 | 316 |
| 343 // The next scheduled update has special behavior for the first 2 requests. | 317 // The next scheduled update has special behavior for the first 2 requests. |
| 344 enum UpdateRequestState { | 318 enum UpdateRequestState { |
| 345 FIRST_REQUEST = 0, | 319 FIRST_REQUEST = 0, |
| 346 SECOND_REQUEST, | 320 SECOND_REQUEST, |
| 347 NORMAL_REQUEST | 321 NORMAL_REQUEST |
| 348 }; | 322 }; |
| 349 UpdateRequestState update_state_; | 323 UpdateRequestState update_state_; |
| 350 | 324 |
| 351 // We'll attempt to get keys once per browser session if we don't already have | |
| 352 // them. They are not essential to operation, but provide a layer of | |
| 353 // verification. | |
| 354 bool initial_request_; | |
| 355 | |
| 356 // True if the service has been given an add/sub chunk but it hasn't been | 325 // True if the service has been given an add/sub chunk but it hasn't been |
| 357 // added to the database yet. | 326 // added to the database yet. |
| 358 bool chunk_pending_to_write_; | 327 bool chunk_pending_to_write_; |
| 359 | 328 |
| 360 // The keys used for MAC. Empty keys mean we aren't using MAC. | |
| 361 std::string client_key_; | |
| 362 std::string wrapped_key_; | |
| 363 | |
| 364 // The last time we successfully received an update. | 329 // The last time we successfully received an update. |
| 365 base::Time last_update_; | 330 base::Time last_update_; |
| 366 | 331 |
| 367 // While in GetHash backoff, we can't make another GetHash until this time. | 332 // While in GetHash backoff, we can't make another GetHash until this time. |
| 368 base::Time next_gethash_time_; | 333 base::Time next_gethash_time_; |
| 369 | 334 |
| 370 // Current product version sent in each request. | 335 // Current product version sent in each request. |
| 371 std::string version_; | 336 std::string version_; |
| 372 | 337 |
| 373 // Used for measuring chunk request latency. | 338 // Used for measuring chunk request latency. |
| 374 base::Time chunk_request_start_; | 339 base::Time chunk_request_start_; |
| 375 | 340 |
| 376 // Tracks the size of each update (in bytes). | 341 // Tracks the size of each update (in bytes). |
| 377 int update_size_; | 342 int update_size_; |
| 378 | 343 |
| 379 // Track outstanding SafeBrowsing report fetchers for clean up. | 344 // Track outstanding SafeBrowsing report fetchers for clean up. |
| 380 // We add both "hit" and "detail" fetchers in this set. | 345 // We add both "hit" and "detail" fetchers in this set. |
| 381 std::set<const content::URLFetcher*> safebrowsing_reports_; | 346 std::set<const content::URLFetcher*> safebrowsing_reports_; |
| 382 | 347 |
| 383 // The safe browsing client name sent in each request. | 348 // The safe browsing client name sent in each request. |
| 384 std::string client_name_; | 349 std::string client_name_; |
| 385 | 350 |
| 386 // A string that is appended to the end of URLs for download, gethash, | 351 // A string that is appended to the end of URLs for download, gethash, |
| 387 // newkey, safebrowsing hits and chunk update requests. | 352 // safebrowsing hits and chunk update requests. |
| 388 std::string additional_query_; | 353 std::string additional_query_; |
| 389 | 354 |
| 390 // The context we use to issue network requests. | 355 // The context we use to issue network requests. |
| 391 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | 356 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| 392 | 357 |
| 393 // URL prefix where browser fetches safebrowsing chunk updates, hashes, and | 358 // URL prefix where browser fetches safebrowsing chunk updates, hashes, and |
| 394 // reports hits to the safebrowsing list for UMA users. | 359 // reports hits to the safebrowsing list and sends detaild malware reports |
| 395 std::string http_url_prefix_; | 360 // for UMA users. |
| 396 | 361 std::string url_prefix_; |
| 397 // URL prefix where browser fetches MAC client key, and reports detailed | |
| 398 // malware reports for users who opt-in. | |
| 399 std::string https_url_prefix_; | |
| 400 | 362 |
| 401 // When true, protocol manager will not start an update unless | 363 // When true, protocol manager will not start an update unless |
| 402 // ForceScheduleNextUpdate() is called. This is set for testing purpose. | 364 // ForceScheduleNextUpdate() is called. This is set for testing purpose. |
| 403 bool disable_auto_update_; | 365 bool disable_auto_update_; |
| 404 | 366 |
| 405 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingProtocolManager); | 367 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingProtocolManager); |
| 406 }; | 368 }; |
| 407 | 369 |
| 408 #endif // CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ | 370 #endif // CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ |
| OLD | NEW |