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 #ifndef CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ | 5 #ifndef CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ |
6 #define CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ | 6 #define CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ |
7 | 7 |
8 #include <functional> | 8 #include <functional> |
9 #include <map> | 9 #include <map> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
15 #include "base/file_path.h" | 15 #include "base/file_path.h" |
16 #include "base/gtest_prod_util.h" | 16 #include "base/gtest_prod_util.h" |
17 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
18 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
| 19 #include "base/observer_list.h" |
19 #include "base/string16.h" | 20 #include "base/string16.h" |
| 21 #include "base/threading/sequenced_worker_pool.h" |
20 #include "chrome/browser/autocomplete/autocomplete_match.h" | 22 #include "chrome/browser/autocomplete/autocomplete_match.h" |
21 #include "chrome/browser/autocomplete/history_provider_util.h" | 23 #include "chrome/browser/autocomplete/history_provider_util.h" |
22 #include "chrome/browser/cancelable_request.h" | 24 #include "chrome/browser/cancelable_request.h" |
23 #include "chrome/browser/history/history.h" | 25 #include "chrome/browser/history/history.h" |
24 #include "chrome/browser/history/history_types.h" | 26 #include "chrome/browser/history/history_types.h" |
25 #include "chrome/browser/history/in_memory_url_index_types.h" | 27 #include "chrome/browser/history/in_memory_url_index_types.h" |
26 #include "chrome/browser/history/scored_history_match.h" | 28 #include "chrome/browser/history/scored_history_match.h" |
| 29 #include "chrome/browser/history/url_index_private_data.h" |
27 #include "content/public/browser/notification_observer.h" | 30 #include "content/public/browser/notification_observer.h" |
28 #include "content/public/browser/notification_registrar.h" | 31 #include "content/public/browser/notification_registrar.h" |
29 #include "sql/connection.h" | 32 #include "sql/connection.h" |
30 | 33 |
31 class HistoryQuickProviderTest; | 34 class HistoryQuickProviderTest; |
32 class Profile; | 35 class Profile; |
33 | 36 |
34 namespace base { | 37 namespace base { |
35 class Time; | 38 class Time; |
36 } | 39 } |
37 | 40 |
38 namespace in_memory_url_index { | |
39 class InMemoryURLIndexCacheItem; | |
40 } | |
41 | |
42 namespace history { | 41 namespace history { |
43 | 42 |
44 namespace imui = in_memory_url_index; | 43 class InMemoryURLIndexObserver; |
45 | 44 class URLDatabase; |
46 class HistoryDatabase; | 45 struct URLsDeletedDetails; |
47 class URLIndexPrivateData; | 46 struct URLsModifiedDetails; |
48 struct URLVisitedDetails; | 47 struct URLVisitedDetails; |
49 struct URLsModifiedDetails; | |
50 struct URLsDeletedDetails; | |
51 | 48 |
52 // The URL history source. | 49 // The URL history source. |
53 // Holds portions of the URL database in memory in an indexed form. Used to | 50 // Holds portions of the URL database in memory in an indexed form. Used to |
54 // quickly look up matching URLs for a given query string. Used by | 51 // quickly look up matching URLs for a given query string. Used by |
55 // the HistoryURLProvider for inline autocomplete and to provide URL | 52 // the HistoryURLProvider for inline autocomplete and to provide URL |
56 // matches to the omnibox. | 53 // matches to the omnibox. |
57 // | 54 // |
58 // Note about multi-byte codepoints and the data structures in the | 55 // Note about multi-byte codepoints and the data structures in the |
59 // InMemoryURLIndex class: One will quickly notice that no effort is made to | 56 // InMemoryURLIndex class: One will quickly notice that no effort is made to |
60 // insure that multi-byte character boundaries are detected when indexing the | 57 // insure that multi-byte character boundaries are detected when indexing the |
61 // words and characters in the URL history database except when converting | 58 // words and characters in the URL history database except when converting |
62 // URL strings to lowercase. Multi-byte-edness makes no difference when | 59 // URL strings to lowercase. Multi-byte-edness makes no difference when |
63 // indexing or when searching the index as the final filtering of results | 60 // indexing or when searching the index as the final filtering of results |
64 // is dependent on the comparison of a string of bytes, not individual | 61 // is dependent on the comparison of a string of bytes, not individual |
65 // characters. While the lookup of those bytes during a search in the | 62 // characters. While the lookup of those bytes during a search in the |
66 // |char_word_map_| could serve up words in which the individual char16 | 63 // |char_word_map_| could serve up words in which the individual char16 |
67 // occurs as a portion of a composite character the next filtering step | 64 // occurs as a portion of a composite character the next filtering step |
68 // will eliminate such words except in the case where a single character | 65 // will eliminate such words except in the case where a single character |
69 // is being searched on and which character occurs as the second char16 of a | 66 // is being searched on and which character occurs as the second char16 of a |
70 // multi-char16 instance. | 67 // multi-char16 instance. |
71 class InMemoryURLIndex : public content::NotificationObserver, | 68 class InMemoryURLIndex : public content::NotificationObserver { |
72 public base::SupportsWeakPtr<InMemoryURLIndex> { | |
73 public: | 69 public: |
74 // Defines an abstract class which is notified upon completion of restoring | 70 // Observer is used for blocking until the InMemoryURLIndex has finished |
75 // the index's private data either by reading from the cache file or by | 71 // loading. Usage typically follows this pattern: |
76 // rebuilding from the history database. | 72 // InMemoryURLIndex::Observer observer(index); // Create observer. |
77 class RestoreCacheObserver { | 73 // MessageLoop::current()->Run(); // Blocks until loaded. |
| 74 // |
| 75 class Observer { |
78 public: | 76 public: |
79 virtual ~RestoreCacheObserver(); | 77 explicit Observer(InMemoryURLIndex* index); |
80 | 78 |
81 // Callback that lets the observer know that the restore operation has | 79 // Called when the InMemoryURLIndex has completed loading. |
82 // completed. |succeeded| indicates if the restore was successful. This is | 80 virtual void Loaded(); |
83 // called on the UI thread. | |
84 virtual void OnCacheRestoreFinished(bool succeeded) = 0; | |
85 }; | |
86 | 81 |
87 // Defines an abstract class which is notified upon completion of saving | 82 private: |
88 // the index's private data to the cache file. | 83 friend class InMemoryURLIndexBaseTest; |
89 class SaveCacheObserver { | 84 virtual ~Observer(); |
90 public: | |
91 virtual ~SaveCacheObserver(); | |
92 | 85 |
93 // Callback that lets the observer know that the save succeeded. | 86 InMemoryURLIndex* index_; |
94 // This is called on the UI thread. | 87 |
95 virtual void OnCacheSaveFinished(bool succeeded) = 0; | 88 DISALLOW_COPY_AND_ASSIGN(Observer); |
96 }; | 89 }; |
97 | 90 |
98 // |profile|, which may be NULL during unit testing, is used to register for | 91 // |profile|, which may be NULL during unit testing, is used to register for |
99 // history changes. |history_dir| is a path to the directory containing the | 92 // history changes. |history_dir| is a path to the directory containing the |
100 // history database within the profile wherein the cache and transaction | 93 // history database within the profile wherein the cache and transaction |
101 // journals will be stored. |languages| gives a list of language encodings by | 94 // journals will be stored. |languages| gives a list of language encodings by |
102 // which URLs and omnibox searches are broken down into words and characters. | 95 // which URLs and omnibox searches are broken down into words and characters. |
103 InMemoryURLIndex(Profile* profile, | 96 InMemoryURLIndex(Profile* profile, |
104 const FilePath& history_dir, | 97 const FilePath& history_dir, |
105 const std::string& languages); | 98 const std::string& languages); |
106 virtual ~InMemoryURLIndex(); | 99 virtual ~InMemoryURLIndex(); |
107 | 100 |
108 // Opens and prepares the index of historical URL visits. If the index private | 101 // Opens and prepares the index of historical URL visits. If the index private |
109 // data cannot be restored from its cache file then it is rebuilt from the | 102 // data cannot be restored from its cache database then it is rebuilt from the |
110 // history database. | 103 // history database. |disable_cache| causes the InMemoryURLIndex to not create |
111 void Init(); | 104 // or use its cache database. |
| 105 void Init(bool disable_cache); |
112 | 106 |
113 // Signals that any outstanding initialization should be canceled and | 107 // Signals that any outstanding initialization should be canceled. |
114 // flushes the cache to disk. | 108 void Shutdown(); |
115 void ShutDown(); | 109 |
| 110 // Returns true if the index has been loaded or rebuilt and so is available |
| 111 // for use. |
| 112 bool index_available() const { return index_available_; } |
116 | 113 |
117 // Scans the history index and returns a vector with all scored, matching | 114 // Scans the history index and returns a vector with all scored, matching |
118 // history items. This entry point simply forwards the call on to the | 115 // history items. This entry point simply forwards the call on to the |
119 // URLIndexPrivateData class. For a complete description of this function | 116 // URLIndexPrivateData class. For a complete description of this function |
120 // refer to that class. | 117 // refer to that class. |
121 ScoredHistoryMatches HistoryItemsForTerms(const string16& term_string); | 118 ScoredHistoryMatches HistoryItemsForTerms(const string16& term_string); |
122 | 119 |
123 // Sets the optional observers for completion of restoral and saving of the | 120 // Deletes the index entry, if any, for the given |url|. |
124 // index's private data. | 121 void DeleteURL(const GURL& url); |
125 void set_restore_cache_observer( | |
126 RestoreCacheObserver* restore_cache_observer) { | |
127 restore_cache_observer_ = restore_cache_observer; | |
128 } | |
129 void set_save_cache_observer(SaveCacheObserver* save_cache_observer) { | |
130 save_cache_observer_ = save_cache_observer; | |
131 } | |
132 | 122 |
133 private: | 123 private: |
134 friend class ::HistoryQuickProviderTest; | 124 friend class ::HistoryQuickProviderTest; |
| 125 friend class InMemoryURLIndex::Observer; |
| 126 friend class InMemoryURLIndexCacheTest; |
135 friend class InMemoryURLIndexTest; | 127 friend class InMemoryURLIndexTest; |
136 friend class InMemoryURLIndexCacheTest; | 128 friend class InMemoryURLIndexBaseTest; |
| 129 friend class IntercessionaryIndexTest; |
| 130 FRIEND_TEST_ALL_PREFIXES(InMemoryURLIndexTest, ExpireRow); |
| 131 FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest, CacheDatabaseFailure); |
| 132 FRIEND_TEST_ALL_PREFIXES(IntercessionaryIndexTest, |
| 133 ShutdownDuringCacheRefresh); |
137 FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization); | 134 FRIEND_TEST_ALL_PREFIXES(LimitedInMemoryURLIndexTest, Initialization); |
138 | 135 |
139 // Creating one of me without a history path is not allowed (tests excepted). | |
140 InMemoryURLIndex(); | |
141 | |
142 // HistoryDBTask used to rebuild our private data from the history database. | 136 // HistoryDBTask used to rebuild our private data from the history database. |
143 class RebuildPrivateDataFromHistoryDBTask : public HistoryDBTask { | 137 class RebuildPrivateDataFromHistoryDBTask : public HistoryDBTask { |
144 public: | 138 public: |
145 explicit RebuildPrivateDataFromHistoryDBTask( | 139 explicit RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index); |
146 InMemoryURLIndex* index, | |
147 const std::string& languages, | |
148 const std::set<std::string>& scheme_whitelist); | |
149 | 140 |
150 virtual bool RunOnDBThread(HistoryBackend* backend, | 141 virtual bool RunOnDBThread(HistoryBackend* backend, |
151 history::HistoryDatabase* db) OVERRIDE; | 142 history::HistoryDatabase* db) OVERRIDE; |
152 virtual void DoneRunOnMainThread() OVERRIDE; | 143 virtual void DoneRunOnMainThread() OVERRIDE; |
153 | 144 |
154 private: | 145 private: |
155 virtual ~RebuildPrivateDataFromHistoryDBTask(); | 146 virtual ~RebuildPrivateDataFromHistoryDBTask(); |
156 | 147 |
157 InMemoryURLIndex* index_; // Call back to this index at completion. | 148 InMemoryURLIndex* index_; // Call back to this index at completion. |
158 std::string languages_; // Languages for word-breaking. | |
159 std::set<std::string> scheme_whitelist_; // Schemes to be indexed. | |
160 bool succeeded_; // Indicates if the rebuild was successful. | 149 bool succeeded_; // Indicates if the rebuild was successful. |
161 scoped_refptr<URLIndexPrivateData> data_; // The rebuilt private data. | 150 scoped_refptr<URLIndexPrivateData> data_; // The rebuilt private data. |
162 | 151 |
163 DISALLOW_COPY_AND_ASSIGN(RebuildPrivateDataFromHistoryDBTask); | 152 DISALLOW_COPY_AND_ASSIGN(RebuildPrivateDataFromHistoryDBTask); |
164 }; | 153 }; |
165 | 154 |
166 // Initializes all index data members in preparation for restoring the index | 155 // For unit testing only. |
167 // from the cache or a complete rebuild from the history database. | 156 InMemoryURLIndex(const FilePath& history_dir, const std::string& languages); |
168 void ClearPrivateData(); | |
169 | 157 |
170 // Constructs a file path for the cache file within the same directory where | 158 // Completes index initialization once the cache DB has been initialized. |
171 // the history database is kept and saves that path to |file_path|. Returns | 159 void OnPrivateDataInitDone(bool succeeded); |
172 // true if |file_path| can be successfully constructed. (This function | |
173 // provided as a hook for unit testing.) | |
174 bool GetCacheFilePath(FilePath* file_path); | |
175 | 160 |
176 // Restores the index's private data from the cache file stored in the | 161 // Adds or removes an observer that is notified when the index has been |
177 // profile directory. | 162 // loaded. |
178 void PostRestoreFromCacheFileTask(); | 163 void AddObserver(InMemoryURLIndex::Observer* observer); |
| 164 void RemoveObserver(InMemoryURLIndex::Observer* observer); |
| 165 |
| 166 // Handles notifications of history changes. |
| 167 virtual void Observe(int notification_type, |
| 168 const content::NotificationSource& source, |
| 169 const content::NotificationDetails& details) OVERRIDE; |
| 170 |
| 171 // Notification handlers. |
| 172 void OnURLVisited(const URLVisitedDetails* details); |
| 173 void OnURLsModified(const URLsModifiedDetails* details); |
| 174 void OnURLsDeleted(const URLsDeletedDetails* details); |
| 175 |
| 176 // Posts any outstanding updates to the index which were queued while the |
| 177 // index was being initialized. |
| 178 void FlushPendingUpdates(); |
| 179 |
| 180 // Restores the index's private data from the cache database stored in the |
| 181 // profile directory. If no database is found or can be restored then look |
| 182 // for an old version protobuf-based cache file. |
| 183 void PostRestoreFromCacheTask(); |
| 184 |
| 185 // Determines if the private data was successfully restored from the cache |
| 186 // database, as indicated by |succeeded|, or if the private data must be |
| 187 // rebuilt from the history database. If successful, notifies any |
| 188 // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history |
| 189 // database. |
| 190 void OnCacheRestoreDone(bool succeeded); |
| 191 |
| 192 // Notifies all observers that the index has been loaded or rebuilt. |
| 193 void NotifyHasLoaded(); |
| 194 |
| 195 // Rebuilds the index from the history database if the history database has |
| 196 // been loaded, otherwise registers for the history loaded notification so |
| 197 // that the rebuild can take place at a later time. |
| 198 void RebuildFromHistoryIfLoaded(); |
179 | 199 |
180 // Schedules a history task to rebuild our private data from the history | 200 // Schedules a history task to rebuild our private data from the history |
181 // database. | 201 // database. |
182 void ScheduleRebuildFromHistory(); | 202 void ScheduleRebuildFromHistory(); |
183 | 203 |
184 // Callback used by RebuildPrivateDataFromHistoryDBTask to signal completion | 204 // Callback used by RebuildPrivateDataFromHistoryDBTask to signal completion |
185 // or rebuilding our private data from the history database. |succeeded| | 205 // or rebuilding our private data from the history database. |succeeded| |
186 // will be true if the rebuild was successful. |data| will point to a new | 206 // will be true if the rebuild was successful. |data| will point to a new |
187 // instanceof the private data just rebuilt. | 207 // instanceof the private data just rebuilt. |
188 void DoneRebuidingPrivateDataFromHistoryDB( | 208 void DoneRebuidingPrivateDataFromHistoryDB( |
189 bool succeeded, | 209 bool succeeded, |
190 scoped_refptr<URLIndexPrivateData> private_data); | 210 scoped_refptr<URLIndexPrivateData> private_data); |
191 | 211 |
192 // Rebuilds the history index from the history database in |history_db|. | 212 // Posts a task to completely reset the private data and the backing cache. |
193 // Used for unit testing only. | 213 void PostResetPrivateDataTask(); |
194 void RebuildFromHistory(HistoryDatabase* history_db); | |
195 | 214 |
196 // Determines if the private data was successfully reloaded from the cache | 215 // Posts a task to completely replace the cache database with a current |
197 // file or if the private data must be rebuilt from the history database. | 216 // image of the index private data. |
198 // |private_data_ptr|'s data will be NULL if the cache file load failed. If | 217 void PostRefreshCacheTask(); |
199 // successful, sets the private data and notifies any | |
200 // |restore_cache_observer_|. Otherwise, kicks off a rebuild from the history | |
201 // database. | |
202 void OnCacheLoadDone( | |
203 scoped_refptr<URLIndexPrivateData> private_data_ptr); | |
204 | 218 |
205 // Callback function that sets the private data from the just-restored-from- | 219 // Callback used by PostRefreshCacheTask and PostResetPrivateDataTask to |
206 // file |private_data|. Notifies any |restore_cache_observer_| that the | 220 // notify observers that the cache database contents have been refreshed or |
207 // restore has succeeded. | 221 // reset and that the loading of the index is complete. |
208 void OnCacheRestored(URLIndexPrivateData* private_data); | 222 void OnCacheRefreshOrResetDone(); |
209 | 223 |
210 // Posts a task to cache the index private data and write the cache file to | 224 // Attempts to refresh the cache database in response to a notification that |
211 // the profile directory. | 225 // an update transaction has failed. If the refresh fails then the cache |
212 void PostSaveToCacheFileTask(); | 226 // database is ignored and an attempt will be made to rebuild the cache |
| 227 // the next time the associated profile is opened. |
| 228 void RepairCacheDatabase(); |
213 | 229 |
214 // Saves private_data_ to the given |path|. Runs on the UI thread. | 230 // Returns a pointer to our private data. |
215 // Provided for unit testing so that a test cache file can be used. | 231 scoped_refptr<URLIndexPrivateData> private_data() { return private_data_; } |
216 void DoSaveToCacheFile(const FilePath& path); | |
217 | 232 |
218 // Notifies the observer, if any, of the success of the private data caching. | 233 // Returns the blocking pool sequence token. |
219 // |succeeded| is true on a successful save. | 234 base::SequencedWorkerPool::SequenceToken sequence_token_for_testing() { |
220 void OnCacheSaveDone(scoped_refptr<RefCountedBool> succeeded); | 235 return sequence_token_; |
221 | 236 } |
222 // Handles notifications of history changes. | |
223 virtual void Observe(int notification_type, | |
224 const content::NotificationSource& source, | |
225 const content::NotificationDetails& details) OVERRIDE; | |
226 | |
227 // Notification handlers. | |
228 void OnURLVisited(const URLVisitedDetails* details); | |
229 void OnURLsModified(const URLsModifiedDetails* details); | |
230 void OnURLsDeleted(const URLsDeletedDetails* details); | |
231 | |
232 // Sets the directory wherein the cache file will be maintained. | |
233 // For unit test usage only. | |
234 void set_history_dir(const FilePath& dir_path) { history_dir_ = dir_path; } | |
235 | |
236 // Returns a pointer to our private data. For unit testing only. | |
237 URLIndexPrivateData* private_data() { return private_data_.get(); } | |
238 | |
239 // Returns the set of whitelisted schemes. For unit testing only. | |
240 const std::set<std::string>& scheme_whitelist() { return scheme_whitelist_; } | |
241 | 237 |
242 // The profile, may be null when testing. | 238 // The profile, may be null when testing. |
243 Profile* profile_; | 239 Profile* profile_; |
244 | 240 |
245 // Directory where cache file resides. This is, except when unit testing, | |
246 // the same directory in which the profile's history database is found. It | |
247 // should never be empty. | |
248 FilePath history_dir_; | |
249 | |
250 // Languages used during the word-breaking process during indexing. | 241 // Languages used during the word-breaking process during indexing. |
251 std::string languages_; | 242 std::string languages_; |
252 | 243 |
253 // Only URLs with a whitelisted scheme are indexed. | 244 // Directory where cache database or protobuf-based cache file resides. |
254 std::set<std::string> scheme_whitelist_; | 245 // This is, except when unit testing, the same directory in which the |
| 246 // profile's history database is found. |
| 247 FilePath history_dir_; |
255 | 248 |
256 // The index's durable private data. | 249 // The index's durable private data. |
257 scoped_refptr<URLIndexPrivateData> private_data_; | 250 scoped_refptr<URLIndexPrivateData> private_data_; |
258 | 251 |
259 // Observers to notify upon restoral or save of the private data cache. | 252 // Sequence token for coordinating database tasks. This is shared with |
260 RestoreCacheObserver* restore_cache_observer_; | 253 // our private data and its cache database. |
261 SaveCacheObserver* save_cache_observer_; | 254 const base::SequencedWorkerPool::SequenceToken sequence_token_; |
| 255 |
| 256 bool index_available_; // True when index is available for updating. |
| 257 |
| 258 // Contains index updates queued up while the index is unavailable. This |
| 259 // usually during profile startup. |
| 260 enum UpdateType { UPDATE_VISIT, DELETE_VISIT }; |
| 261 |
| 262 struct IndexUpdateItem { |
| 263 IndexUpdateItem(UpdateType update_type, URLRow row); |
| 264 ~IndexUpdateItem(); |
| 265 |
| 266 UpdateType update_type; |
| 267 URLRow row; // The row to be updated or deleted. |
| 268 }; |
| 269 typedef std::vector<IndexUpdateItem> PendingUpdates; |
| 270 PendingUpdates pending_updates_; |
| 271 |
| 272 ObserverList<InMemoryURLIndex::Observer> observers_; |
262 | 273 |
263 CancelableRequestConsumer cache_reader_consumer_; | 274 CancelableRequestConsumer cache_reader_consumer_; |
264 content::NotificationRegistrar registrar_; | 275 content::NotificationRegistrar registrar_; |
265 | 276 |
266 // Set to true once the shutdown process has begun. | 277 // Set to true once the shutdown process has begun. |
267 bool shutdown_; | 278 bool shutdown_; |
268 | 279 |
269 // Set to true when changes to the index have been made and the index needs | 280 // Note: This should remain the last member so it'll be destroyed and |
270 // to be cached. Set to false when the index has been cached. Used as a | 281 // invalidate its weak pointers before any other members are destroyed. |
271 // temporary safety check to insure that the cache is saved before the | 282 base::WeakPtrFactory<InMemoryURLIndex> weak_ptr_factory_; |
272 // index has been destructed. | |
273 // TODO(mrossetti): Eliminate once the transition to SQLite has been done. | |
274 // http://crbug.com/83659 | |
275 bool needs_to_be_cached_; | |
276 | 283 |
277 DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex); | 284 DISALLOW_COPY_AND_ASSIGN(InMemoryURLIndex); |
278 }; | 285 }; |
279 | 286 |
280 } // namespace history | 287 } // namespace history |
281 | 288 |
282 #endif // CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ | 289 #endif // CHROME_BROWSER_HISTORY_IN_MEMORY_URL_INDEX_H_ |
OLD | NEW |