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 "components/visitedlink/browser/visitedlink_master.h" | 5 #include "components/visitedlink/browser/visitedlink_master.h" |
6 | 6 |
7 #if defined(OS_WIN) | |
8 #include <windows.h> | |
9 #include <io.h> | |
10 #include <shlobj.h> | |
11 #endif // defined(OS_WIN) | |
12 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <string.h> |
13 | 9 |
14 #include <algorithm> | 10 #include <algorithm> |
15 | 11 |
16 #include "base/bind.h" | 12 #include "base/bind.h" |
17 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
18 #include "base/containers/stack_container.h" | 14 #include "base/containers/stack_container.h" |
19 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
20 #include "base/files/scoped_file.h" | 16 #include "base/files/scoped_file.h" |
21 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/macros.h" |
22 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
23 #include "base/rand_util.h" | 20 #include "base/rand_util.h" |
24 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
25 #include "base/threading/thread_restrictions.h" | 22 #include "base/threading/thread_restrictions.h" |
| 23 #include "build/build_config.h" |
26 #include "components/visitedlink/browser/visitedlink_delegate.h" | 24 #include "components/visitedlink/browser/visitedlink_delegate.h" |
27 #include "components/visitedlink/browser/visitedlink_event_listener.h" | 25 #include "components/visitedlink/browser/visitedlink_event_listener.h" |
28 #include "content/public/browser/browser_context.h" | 26 #include "content/public/browser/browser_context.h" |
29 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
30 #include "url/gurl.h" | 28 #include "url/gurl.h" |
31 | 29 |
| 30 #if defined(OS_WIN) |
| 31 #include <windows.h> |
| 32 #include <io.h> |
| 33 #include <shlobj.h> |
| 34 #endif // defined(OS_WIN) |
| 35 |
32 using content::BrowserThread; | 36 using content::BrowserThread; |
33 | 37 |
34 namespace visitedlink { | 38 namespace visitedlink { |
35 | 39 |
36 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; | 40 const int32_t VisitedLinkMaster::kFileHeaderSignatureOffset = 0; |
37 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; | 41 const int32_t VisitedLinkMaster::kFileHeaderVersionOffset = 4; |
38 const int32 VisitedLinkMaster::kFileHeaderLengthOffset = 8; | 42 const int32_t VisitedLinkMaster::kFileHeaderLengthOffset = 8; |
39 const int32 VisitedLinkMaster::kFileHeaderUsedOffset = 12; | 43 const int32_t VisitedLinkMaster::kFileHeaderUsedOffset = 12; |
40 const int32 VisitedLinkMaster::kFileHeaderSaltOffset = 16; | 44 const int32_t VisitedLinkMaster::kFileHeaderSaltOffset = 16; |
41 | 45 |
42 const int32 VisitedLinkMaster::kFileCurrentVersion = 3; | 46 const int32_t VisitedLinkMaster::kFileCurrentVersion = 3; |
43 | 47 |
44 // the signature at the beginning of the URL table = "VLnk" (visited links) | 48 // the signature at the beginning of the URL table = "VLnk" (visited links) |
45 const int32 VisitedLinkMaster::kFileSignature = 0x6b6e4c56; | 49 const int32_t VisitedLinkMaster::kFileSignature = 0x6b6e4c56; |
46 const size_t VisitedLinkMaster::kFileHeaderSize = | 50 const size_t VisitedLinkMaster::kFileHeaderSize = |
47 kFileHeaderSaltOffset + LINK_SALT_LENGTH; | 51 kFileHeaderSaltOffset + LINK_SALT_LENGTH; |
48 | 52 |
49 // This value should also be the same as the smallest size in the lookup | 53 // This value should also be the same as the smallest size in the lookup |
50 // table in NewTableSizeForCount (prime number). | 54 // table in NewTableSizeForCount (prime number). |
51 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; | 55 const unsigned VisitedLinkMaster::kDefaultTableSize = 16381; |
52 | 56 |
53 const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; | 57 const size_t VisitedLinkMaster::kBigDeleteThreshold = 64; |
54 | 58 |
55 namespace { | 59 namespace { |
56 | 60 |
57 // Fills the given salt structure with some quasi-random values | 61 // Fills the given salt structure with some quasi-random values |
58 // It is not necessary to generate a cryptographically strong random string, | 62 // It is not necessary to generate a cryptographically strong random string, |
59 // only that it be reasonably different for different users. | 63 // only that it be reasonably different for different users. |
60 void GenerateSalt(uint8 salt[LINK_SALT_LENGTH]) { | 64 void GenerateSalt(uint8_t salt[LINK_SALT_LENGTH]) { |
61 DCHECK_EQ(LINK_SALT_LENGTH, 8) << "This code assumes the length of the salt"; | 65 DCHECK_EQ(LINK_SALT_LENGTH, 8) << "This code assumes the length of the salt"; |
62 uint64 randval = base::RandUint64(); | 66 uint64_t randval = base::RandUint64(); |
63 memcpy(salt, &randval, 8); | 67 memcpy(salt, &randval, 8); |
64 } | 68 } |
65 | 69 |
66 // Opens file on a background thread to not block UI thread. | 70 // Opens file on a background thread to not block UI thread. |
67 void AsyncOpen(FILE** file, const base::FilePath& filename) { | 71 void AsyncOpen(FILE** file, const base::FilePath& filename) { |
68 *file = base::OpenFile(filename, "wb+"); | 72 *file = base::OpenFile(filename, "wb+"); |
69 DLOG_IF(ERROR, !(*file)) << "Failed to open file " << filename.value(); | 73 DLOG_IF(ERROR, !(*file)) << "Failed to open file " << filename.value(); |
70 } | 74 } |
71 | 75 |
72 // Returns true if the write was complete. | 76 // Returns true if the write was complete. |
(...skipping 12 matching lines...) Expand all Loading... |
85 // Protect against this by calling fflush. | 89 // Protect against this by calling fflush. |
86 int ret = fflush(file); | 90 int ret = fflush(file); |
87 DCHECK_EQ(0, ret); | 91 DCHECK_EQ(0, ret); |
88 return num_written == data_len; | 92 return num_written == data_len; |
89 } | 93 } |
90 | 94 |
91 // This task executes on a background thread and executes a write. This | 95 // This task executes on a background thread and executes a write. This |
92 // prevents us from blocking the UI thread doing I/O. Double pointer to FILE | 96 // prevents us from blocking the UI thread doing I/O. Double pointer to FILE |
93 // is used because file may still not be opened by the time of scheduling | 97 // is used because file may still not be opened by the time of scheduling |
94 // the task for execution. | 98 // the task for execution. |
95 void AsyncWrite(FILE** file, int32 offset, const std::string& data) { | 99 void AsyncWrite(FILE** file, int32_t offset, const std::string& data) { |
96 if (*file) | 100 if (*file) |
97 WriteToFile(*file, offset, data.data(), data.size()); | 101 WriteToFile(*file, offset, data.data(), data.size()); |
98 } | 102 } |
99 | 103 |
100 // Truncates the file to the current position asynchronously on a background | 104 // Truncates the file to the current position asynchronously on a background |
101 // thread. Double pointer to FILE is used because file may still not be opened | 105 // thread. Double pointer to FILE is used because file may still not be opened |
102 // by the time of scheduling the task for execution. | 106 // by the time of scheduling the task for execution. |
103 void AsyncTruncate(FILE** file) { | 107 void AsyncTruncate(FILE** file) { |
104 if (*file) | 108 if (*file) |
105 base::IgnoreResult(base::TruncateFile(*file)); | 109 base::IgnoreResult(base::TruncateFile(*file)); |
106 } | 110 } |
107 | 111 |
108 // Closes the file on a background thread and releases memory used for storage | 112 // Closes the file on a background thread and releases memory used for storage |
109 // of FILE* value. Double pointer to FILE is used because file may still not | 113 // of FILE* value. Double pointer to FILE is used because file may still not |
110 // be opened by the time of scheduling the task for execution. | 114 // be opened by the time of scheduling the task for execution. |
111 void AsyncClose(FILE** file) { | 115 void AsyncClose(FILE** file) { |
112 if (*file) | 116 if (*file) |
113 base::IgnoreResult(fclose(*file)); | 117 base::IgnoreResult(fclose(*file)); |
114 free(file); | 118 free(file); |
115 } | 119 } |
116 | 120 |
117 } // namespace | 121 } // namespace |
118 | 122 |
119 struct VisitedLinkMaster::LoadFromFileResult | 123 struct VisitedLinkMaster::LoadFromFileResult |
120 : public base::RefCountedThreadSafe<LoadFromFileResult> { | 124 : public base::RefCountedThreadSafe<LoadFromFileResult> { |
121 LoadFromFileResult(base::ScopedFILE file, | 125 LoadFromFileResult(base::ScopedFILE file, |
122 scoped_ptr<base::SharedMemory> shared_memory, | 126 scoped_ptr<base::SharedMemory> shared_memory, |
123 Fingerprint* hash_table, | 127 Fingerprint* hash_table, |
124 int32 num_entries, | 128 int32_t num_entries, |
125 int32 used_count, | 129 int32_t used_count, |
126 uint8 salt[LINK_SALT_LENGTH]); | 130 uint8_t salt[LINK_SALT_LENGTH]); |
127 | 131 |
128 base::ScopedFILE file; | 132 base::ScopedFILE file; |
129 scoped_ptr<base::SharedMemory> shared_memory; | 133 scoped_ptr<base::SharedMemory> shared_memory; |
130 Fingerprint* hash_table; | 134 Fingerprint* hash_table; |
131 int32 num_entries; | 135 int32_t num_entries; |
132 int32 used_count; | 136 int32_t used_count; |
133 uint8 salt[LINK_SALT_LENGTH]; | 137 uint8_t salt[LINK_SALT_LENGTH]; |
134 | 138 |
135 private: | 139 private: |
136 friend class base::RefCountedThreadSafe<LoadFromFileResult>; | 140 friend class base::RefCountedThreadSafe<LoadFromFileResult>; |
137 virtual ~LoadFromFileResult(); | 141 virtual ~LoadFromFileResult(); |
138 | 142 |
139 DISALLOW_COPY_AND_ASSIGN(LoadFromFileResult); | 143 DISALLOW_COPY_AND_ASSIGN(LoadFromFileResult); |
140 }; | 144 }; |
141 | 145 |
142 VisitedLinkMaster::LoadFromFileResult::LoadFromFileResult( | 146 VisitedLinkMaster::LoadFromFileResult::LoadFromFileResult( |
143 base::ScopedFILE file, | 147 base::ScopedFILE file, |
144 scoped_ptr<base::SharedMemory> shared_memory, | 148 scoped_ptr<base::SharedMemory> shared_memory, |
145 Fingerprint* hash_table, | 149 Fingerprint* hash_table, |
146 int32 num_entries, | 150 int32_t num_entries, |
147 int32 used_count, | 151 int32_t used_count, |
148 uint8 salt[LINK_SALT_LENGTH]) | 152 uint8_t salt[LINK_SALT_LENGTH]) |
149 : file(file.Pass()), | 153 : file(file.Pass()), |
150 shared_memory(shared_memory.Pass()), | 154 shared_memory(shared_memory.Pass()), |
151 hash_table(hash_table), | 155 hash_table(hash_table), |
152 num_entries(num_entries), | 156 num_entries(num_entries), |
153 used_count(used_count) { | 157 used_count(used_count) { |
154 memcpy(this->salt, salt, LINK_SALT_LENGTH); | 158 memcpy(this->salt, salt, LINK_SALT_LENGTH); |
155 } | 159 } |
156 | 160 |
157 VisitedLinkMaster::LoadFromFileResult::~LoadFromFileResult() { | 161 VisitedLinkMaster::LoadFromFileResult::~LoadFromFileResult() { |
158 } | 162 } |
(...skipping 13 matching lines...) Expand all Loading... |
172 // master then replaces its table with a new table containing the computed | 176 // master then replaces its table with a new table containing the computed |
173 // fingerprints. | 177 // fingerprints. |
174 // | 178 // |
175 // The builder must remain active while the history system is using it. | 179 // The builder must remain active while the history system is using it. |
176 // Sometimes, the master will be deleted before the rebuild is complete, in | 180 // Sometimes, the master will be deleted before the rebuild is complete, in |
177 // which case it notifies the builder via DisownMaster(). The builder will | 181 // which case it notifies the builder via DisownMaster(). The builder will |
178 // delete itself once rebuilding is complete, and not execute any callback. | 182 // delete itself once rebuilding is complete, and not execute any callback. |
179 class VisitedLinkMaster::TableBuilder | 183 class VisitedLinkMaster::TableBuilder |
180 : public VisitedLinkDelegate::URLEnumerator { | 184 : public VisitedLinkDelegate::URLEnumerator { |
181 public: | 185 public: |
182 TableBuilder(VisitedLinkMaster* master, | 186 TableBuilder(VisitedLinkMaster* master, const uint8_t salt[LINK_SALT_LENGTH]); |
183 const uint8 salt[LINK_SALT_LENGTH]); | |
184 | 187 |
185 // Called on the main thread when the master is being destroyed. This will | 188 // Called on the main thread when the master is being destroyed. This will |
186 // prevent a crash when the query completes and the master is no longer | 189 // prevent a crash when the query completes and the master is no longer |
187 // around. We can not actually do anything but mark this fact, since the | 190 // around. We can not actually do anything but mark this fact, since the |
188 // table will be being rebuilt simultaneously on the other thread. | 191 // table will be being rebuilt simultaneously on the other thread. |
189 void DisownMaster(); | 192 void DisownMaster(); |
190 | 193 |
191 // VisitedLinkDelegate::URLEnumerator | 194 // VisitedLinkDelegate::URLEnumerator |
192 void OnURL(const GURL& url) override; | 195 void OnURL(const GURL& url) override; |
193 void OnComplete(bool succeed) override; | 196 void OnComplete(bool succeed) override; |
194 | 197 |
195 private: | 198 private: |
196 ~TableBuilder() override {} | 199 ~TableBuilder() override {} |
197 | 200 |
198 // OnComplete mashals to this function on the main thread to do the | 201 // OnComplete mashals to this function on the main thread to do the |
199 // notification. | 202 // notification. |
200 void OnCompleteMainThread(); | 203 void OnCompleteMainThread(); |
201 | 204 |
202 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! | 205 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! |
203 VisitedLinkMaster* master_; | 206 VisitedLinkMaster* master_; |
204 | 207 |
205 // Indicates whether the operation has failed or not. | 208 // Indicates whether the operation has failed or not. |
206 bool success_; | 209 bool success_; |
207 | 210 |
208 // Salt for this new table. | 211 // Salt for this new table. |
209 uint8 salt_[LINK_SALT_LENGTH]; | 212 uint8_t salt_[LINK_SALT_LENGTH]; |
210 | 213 |
211 // Stores the fingerprints we computed on the background thread. | 214 // Stores the fingerprints we computed on the background thread. |
212 VisitedLinkCommon::Fingerprints fingerprints_; | 215 VisitedLinkCommon::Fingerprints fingerprints_; |
213 | 216 |
214 DISALLOW_COPY_AND_ASSIGN(TableBuilder); | 217 DISALLOW_COPY_AND_ASSIGN(TableBuilder); |
215 }; | 218 }; |
216 | 219 |
217 // VisitedLinkMaster ---------------------------------------------------------- | 220 // VisitedLinkMaster ---------------------------------------------------------- |
218 | 221 |
219 VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context, | 222 VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context, |
220 VisitedLinkDelegate* delegate, | 223 VisitedLinkDelegate* delegate, |
221 bool persist_to_disk) | 224 bool persist_to_disk) |
222 : browser_context_(browser_context), | 225 : browser_context_(browser_context), |
223 delegate_(delegate), | 226 delegate_(delegate), |
224 listener_(new VisitedLinkEventListener(this, browser_context)), | 227 listener_(new VisitedLinkEventListener(this, browser_context)), |
225 persist_to_disk_(persist_to_disk), | 228 persist_to_disk_(persist_to_disk), |
226 table_is_loading_from_file_(false), | 229 table_is_loading_from_file_(false), |
227 weak_ptr_factory_(this) { | 230 weak_ptr_factory_(this) { |
228 InitMembers(); | 231 InitMembers(); |
229 } | 232 } |
230 | 233 |
231 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, | 234 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
232 VisitedLinkDelegate* delegate, | 235 VisitedLinkDelegate* delegate, |
233 bool persist_to_disk, | 236 bool persist_to_disk, |
234 bool suppress_rebuild, | 237 bool suppress_rebuild, |
235 const base::FilePath& filename, | 238 const base::FilePath& filename, |
236 int32 default_table_size) | 239 int32_t default_table_size) |
237 : browser_context_(NULL), | 240 : browser_context_(NULL), |
238 delegate_(delegate), | 241 delegate_(delegate), |
239 persist_to_disk_(persist_to_disk), | 242 persist_to_disk_(persist_to_disk), |
240 table_is_loading_from_file_(false), | 243 table_is_loading_from_file_(false), |
241 weak_ptr_factory_(this) { | 244 weak_ptr_factory_(this) { |
242 listener_.reset(listener); | 245 listener_.reset(listener); |
243 DCHECK(listener_.get()); | 246 DCHECK(listener_.get()); |
244 InitMembers(); | 247 InitMembers(); |
245 | 248 |
246 database_name_override_ = filename; | 249 database_name_override_ = filename; |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 DCHECK(persist_to_disk_); | 591 DCHECK(persist_to_disk_); |
589 | 592 |
590 if (!file_) { | 593 if (!file_) { |
591 file_ = static_cast<FILE**>(calloc(1, sizeof(*file_))); | 594 file_ = static_cast<FILE**>(calloc(1, sizeof(*file_))); |
592 base::FilePath filename; | 595 base::FilePath filename; |
593 GetDatabaseFileName(&filename); | 596 GetDatabaseFileName(&filename); |
594 PostIOTask(FROM_HERE, base::Bind(&AsyncOpen, file_, filename)); | 597 PostIOTask(FROM_HERE, base::Bind(&AsyncOpen, file_, filename)); |
595 } | 598 } |
596 | 599 |
597 // Write the new header. | 600 // Write the new header. |
598 int32 header[4]; | 601 int32_t header[4]; |
599 header[0] = kFileSignature; | 602 header[0] = kFileSignature; |
600 header[1] = kFileCurrentVersion; | 603 header[1] = kFileCurrentVersion; |
601 header[2] = table_length_; | 604 header[2] = table_length_; |
602 header[3] = used_items_; | 605 header[3] = used_items_; |
603 WriteToFile(file_, 0, header, sizeof(header)); | 606 WriteToFile(file_, 0, header, sizeof(header)); |
604 WriteToFile(file_, sizeof(header), salt_, LINK_SALT_LENGTH); | 607 WriteToFile(file_, sizeof(header), salt_, LINK_SALT_LENGTH); |
605 | 608 |
606 // Write the hash data. | 609 // Write the hash data. |
607 WriteToFile(file_, kFileHeaderSize, | 610 WriteToFile(file_, kFileHeaderSize, |
608 hash_table_, table_length_ * sizeof(Fingerprint)); | 611 hash_table_, table_length_ * sizeof(Fingerprint)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 // static | 649 // static |
647 bool VisitedLinkMaster::LoadApartFromFile( | 650 bool VisitedLinkMaster::LoadApartFromFile( |
648 const base::FilePath& filename, | 651 const base::FilePath& filename, |
649 scoped_refptr<LoadFromFileResult>* load_from_file_result) { | 652 scoped_refptr<LoadFromFileResult>* load_from_file_result) { |
650 DCHECK(load_from_file_result); | 653 DCHECK(load_from_file_result); |
651 | 654 |
652 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); | 655 base::ScopedFILE file_closer(base::OpenFile(filename, "rb+")); |
653 if (!file_closer.get()) | 656 if (!file_closer.get()) |
654 return false; | 657 return false; |
655 | 658 |
656 int32 num_entries, used_count; | 659 int32_t num_entries, used_count; |
657 uint8 salt[LINK_SALT_LENGTH]; | 660 uint8_t salt[LINK_SALT_LENGTH]; |
658 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) | 661 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt)) |
659 return false; // Header isn't valid. | 662 return false; // Header isn't valid. |
660 | 663 |
661 // Allocate and read the table. | 664 // Allocate and read the table. |
662 scoped_ptr<base::SharedMemory> shared_memory; | 665 scoped_ptr<base::SharedMemory> shared_memory; |
663 VisitedLinkCommon::Fingerprint* hash_table; | 666 VisitedLinkCommon::Fingerprint* hash_table; |
664 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) | 667 if (!CreateApartURLTable(num_entries, salt, &shared_memory, &hash_table)) |
665 return false; | 668 return false; |
666 | 669 |
667 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, hash_table, | 670 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, hash_table, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 // This will build the table from history. On the first run, history will | 788 // This will build the table from history. On the first run, history will |
786 // be empty, so this will be correct. This will also write the new table | 789 // be empty, so this will be correct. This will also write the new table |
787 // to disk. We don't want to save explicitly here, since the rebuild may | 790 // to disk. We don't want to save explicitly here, since the rebuild may |
788 // not complete, leaving us with an empty but valid visited link database. | 791 // not complete, leaving us with an empty but valid visited link database. |
789 // In the future, we won't know we need to try rebuilding again. | 792 // In the future, we won't know we need to try rebuilding again. |
790 return RebuildTableFromDelegate(); | 793 return RebuildTableFromDelegate(); |
791 } | 794 } |
792 | 795 |
793 // static | 796 // static |
794 bool VisitedLinkMaster::ReadFileHeader(FILE* file, | 797 bool VisitedLinkMaster::ReadFileHeader(FILE* file, |
795 int32* num_entries, | 798 int32_t* num_entries, |
796 int32* used_count, | 799 int32_t* used_count, |
797 uint8 salt[LINK_SALT_LENGTH]) { | 800 uint8_t salt[LINK_SALT_LENGTH]) { |
798 // Get file size. | 801 // Get file size. |
799 // Note that there is no need to seek back to the original location in the | 802 // Note that there is no need to seek back to the original location in the |
800 // file since ReadFromFile() [which is the next call accessing the file] | 803 // file since ReadFromFile() [which is the next call accessing the file] |
801 // seeks before reading. | 804 // seeks before reading. |
802 if (fseek(file, 0, SEEK_END) == -1) | 805 if (fseek(file, 0, SEEK_END) == -1) |
803 return false; | 806 return false; |
804 size_t file_size = ftell(file); | 807 size_t file_size = ftell(file); |
805 | 808 |
806 if (file_size <= kFileHeaderSize) | 809 if (file_size <= kFileHeaderSize) |
807 return false; | 810 return false; |
808 | 811 |
809 uint8 header[kFileHeaderSize]; | 812 uint8_t header[kFileHeaderSize]; |
810 if (!ReadFromFile(file, 0, &header, kFileHeaderSize)) | 813 if (!ReadFromFile(file, 0, &header, kFileHeaderSize)) |
811 return false; | 814 return false; |
812 | 815 |
813 // Verify the signature. | 816 // Verify the signature. |
814 int32 signature; | 817 int32_t signature; |
815 memcpy(&signature, &header[kFileHeaderSignatureOffset], sizeof(signature)); | 818 memcpy(&signature, &header[kFileHeaderSignatureOffset], sizeof(signature)); |
816 if (signature != kFileSignature) | 819 if (signature != kFileSignature) |
817 return false; | 820 return false; |
818 | 821 |
819 // Verify the version is up-to-date. As with other read errors, a version | 822 // Verify the version is up-to-date. As with other read errors, a version |
820 // mistmatch will trigger a rebuild of the database from history, which will | 823 // mistmatch will trigger a rebuild of the database from history, which will |
821 // have the effect of migrating the database. | 824 // have the effect of migrating the database. |
822 int32 version; | 825 int32_t version; |
823 memcpy(&version, &header[kFileHeaderVersionOffset], sizeof(version)); | 826 memcpy(&version, &header[kFileHeaderVersionOffset], sizeof(version)); |
824 if (version != kFileCurrentVersion) | 827 if (version != kFileCurrentVersion) |
825 return false; // Bad version. | 828 return false; // Bad version. |
826 | 829 |
827 // Read the table size and make sure it matches the file size. | 830 // Read the table size and make sure it matches the file size. |
828 memcpy(num_entries, &header[kFileHeaderLengthOffset], sizeof(*num_entries)); | 831 memcpy(num_entries, &header[kFileHeaderLengthOffset], sizeof(*num_entries)); |
829 if (*num_entries * sizeof(Fingerprint) + kFileHeaderSize != file_size) | 832 if (*num_entries * sizeof(Fingerprint) + kFileHeaderSize != file_size) |
830 return false; // Bad size. | 833 return false; // Bad size. |
831 | 834 |
832 // Read the used item count. | 835 // Read the used item count. |
(...skipping 18 matching lines...) Expand all Loading... |
851 if (!browser_context_ || browser_context_->GetPath().empty()) | 854 if (!browser_context_ || browser_context_->GetPath().empty()) |
852 return false; | 855 return false; |
853 | 856 |
854 base::FilePath profile_dir = browser_context_->GetPath(); | 857 base::FilePath profile_dir = browser_context_->GetPath(); |
855 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); | 858 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); |
856 return true; | 859 return true; |
857 } | 860 } |
858 | 861 |
859 // Initializes the shared memory structure. The salt should already be filled | 862 // Initializes the shared memory structure. The salt should already be filled |
860 // in so that it can be written to the shared memory | 863 // in so that it can be written to the shared memory |
861 bool VisitedLinkMaster::CreateURLTable(int32 num_entries) { | 864 bool VisitedLinkMaster::CreateURLTable(int32_t num_entries) { |
862 scoped_ptr<base::SharedMemory> shared_memory; | 865 scoped_ptr<base::SharedMemory> shared_memory; |
863 VisitedLinkCommon::Fingerprint* hash_table; | 866 VisitedLinkCommon::Fingerprint* hash_table; |
864 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { | 867 if (CreateApartURLTable(num_entries, salt_, &shared_memory, &hash_table)) { |
865 shared_memory_ = shared_memory.release(); | 868 shared_memory_ = shared_memory.release(); |
866 hash_table_ = hash_table; | 869 hash_table_ = hash_table; |
867 table_length_ = num_entries; | 870 table_length_ = num_entries; |
868 used_items_ = 0; | 871 used_items_ = 0; |
869 return true; | 872 return true; |
870 } | 873 } |
871 | 874 |
872 return false; | 875 return false; |
873 } | 876 } |
874 | 877 |
875 // static | 878 // static |
876 bool VisitedLinkMaster::CreateApartURLTable( | 879 bool VisitedLinkMaster::CreateApartURLTable( |
877 int32 num_entries, | 880 int32_t num_entries, |
878 const uint8 salt[LINK_SALT_LENGTH], | 881 const uint8_t salt[LINK_SALT_LENGTH], |
879 scoped_ptr<base::SharedMemory>* shared_memory, | 882 scoped_ptr<base::SharedMemory>* shared_memory, |
880 VisitedLinkCommon::Fingerprint** hash_table) { | 883 VisitedLinkCommon::Fingerprint** hash_table) { |
881 DCHECK(salt); | 884 DCHECK(salt); |
882 DCHECK(shared_memory); | 885 DCHECK(shared_memory); |
883 DCHECK(hash_table); | 886 DCHECK(hash_table); |
884 | 887 |
885 // The table is the size of the table followed by the entries. | 888 // The table is the size of the table followed by the entries. |
886 uint32 alloc_size = num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); | 889 uint32_t alloc_size = |
| 890 num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); |
887 | 891 |
888 // Create the shared memory object. | 892 // Create the shared memory object. |
889 scoped_ptr<base::SharedMemory> sh_mem(new base::SharedMemory()); | 893 scoped_ptr<base::SharedMemory> sh_mem(new base::SharedMemory()); |
890 if (!sh_mem) | 894 if (!sh_mem) |
891 return false; | 895 return false; |
892 | 896 |
893 base::SharedMemoryCreateOptions options; | 897 base::SharedMemoryCreateOptions options; |
894 options.size = alloc_size; | 898 options.size = alloc_size; |
895 options.share_read_only = true; | 899 options.share_read_only = true; |
896 | 900 |
897 if (!sh_mem->Create(options) || !sh_mem->Map(alloc_size)) | 901 if (!sh_mem->Create(options) || !sh_mem->Map(alloc_size)) |
898 return false; | 902 return false; |
899 | 903 |
900 memset(sh_mem->memory(), 0, alloc_size); | 904 memset(sh_mem->memory(), 0, alloc_size); |
901 | 905 |
902 // Save the header for other processes to read. | 906 // Save the header for other processes to read. |
903 SharedHeader* header = static_cast<SharedHeader*>(sh_mem->memory()); | 907 SharedHeader* header = static_cast<SharedHeader*>(sh_mem->memory()); |
904 header->length = num_entries; | 908 header->length = num_entries; |
905 memcpy(header->salt, salt, LINK_SALT_LENGTH); | 909 memcpy(header->salt, salt, LINK_SALT_LENGTH); |
906 | 910 |
907 // Our table pointer is just the data immediately following the size. | 911 // Our table pointer is just the data immediately following the size. |
908 *hash_table = reinterpret_cast<Fingerprint*>( | 912 *hash_table = reinterpret_cast<Fingerprint*>( |
909 static_cast<char*>(sh_mem->memory()) + sizeof(SharedHeader)); | 913 static_cast<char*>(sh_mem->memory()) + sizeof(SharedHeader)); |
910 | 914 |
911 *shared_memory = sh_mem.Pass(); | 915 *shared_memory = sh_mem.Pass(); |
912 | 916 |
913 return true; | 917 return true; |
914 } | 918 } |
915 | 919 |
916 bool VisitedLinkMaster::BeginReplaceURLTable(int32 num_entries) { | 920 bool VisitedLinkMaster::BeginReplaceURLTable(int32_t num_entries) { |
917 base::SharedMemory *old_shared_memory = shared_memory_; | 921 base::SharedMemory *old_shared_memory = shared_memory_; |
918 Fingerprint* old_hash_table = hash_table_; | 922 Fingerprint* old_hash_table = hash_table_; |
919 int32 old_table_length = table_length_; | 923 int32_t old_table_length = table_length_; |
920 if (!CreateURLTable(num_entries)) { | 924 if (!CreateURLTable(num_entries)) { |
921 // Try to put back the old state. | 925 // Try to put back the old state. |
922 shared_memory_ = old_shared_memory; | 926 shared_memory_ = old_shared_memory; |
923 hash_table_ = old_hash_table; | 927 hash_table_ = old_hash_table; |
924 table_length_ = old_table_length; | 928 table_length_ = old_table_length; |
925 return false; | 929 return false; |
926 } | 930 } |
927 | 931 |
928 #ifndef NDEBUG | 932 #ifndef NDEBUG |
929 DebugValidate(); | 933 DebugValidate(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 return false; | 965 return false; |
962 | 966 |
963 // Table needs to grow or shrink. | 967 // Table needs to grow or shrink. |
964 int new_size = NewTableSizeForCount(used_items_); | 968 int new_size = NewTableSizeForCount(used_items_); |
965 DCHECK(new_size > used_items_); | 969 DCHECK(new_size > used_items_); |
966 DCHECK(load <= min_table_load || new_size > table_length_); | 970 DCHECK(load <= min_table_load || new_size > table_length_); |
967 ResizeTable(new_size); | 971 ResizeTable(new_size); |
968 return true; | 972 return true; |
969 } | 973 } |
970 | 974 |
971 void VisitedLinkMaster::ResizeTable(int32 new_size) { | 975 void VisitedLinkMaster::ResizeTable(int32_t new_size) { |
972 DCHECK(shared_memory_ && shared_memory_->memory() && hash_table_); | 976 DCHECK(shared_memory_ && shared_memory_->memory() && hash_table_); |
973 shared_memory_serial_++; | 977 shared_memory_serial_++; |
974 | 978 |
975 #ifndef NDEBUG | 979 #ifndef NDEBUG |
976 DebugValidate(); | 980 DebugValidate(); |
977 #endif | 981 #endif |
978 | 982 |
979 base::SharedMemory* old_shared_memory = shared_memory_; | 983 base::SharedMemory* old_shared_memory = shared_memory_; |
980 Fingerprint* old_hash_table = hash_table_; | 984 Fingerprint* old_hash_table = hash_table_; |
981 int32 old_table_length = table_length_; | 985 int32_t old_table_length = table_length_; |
982 if (!BeginReplaceURLTable(new_size)) | 986 if (!BeginReplaceURLTable(new_size)) |
983 return; | 987 return; |
984 | 988 |
985 // Now we have two tables, our local copy which is the old one, and the new | 989 // Now we have two tables, our local copy which is the old one, and the new |
986 // one loaded into this object where we need to copy the data. | 990 // one loaded into this object where we need to copy the data. |
987 for (int32 i = 0; i < old_table_length; i++) { | 991 for (int32_t i = 0; i < old_table_length; i++) { |
988 Fingerprint cur = old_hash_table[i]; | 992 Fingerprint cur = old_hash_table[i]; |
989 if (cur) | 993 if (cur) |
990 AddFingerprint(cur, false); | 994 AddFingerprint(cur, false); |
991 } | 995 } |
992 | 996 |
993 // On error unmapping, just forget about it since we can't do anything | 997 // On error unmapping, just forget about it since we can't do anything |
994 // else to release it. | 998 // else to release it. |
995 delete old_shared_memory; | 999 delete old_shared_memory; |
996 | 1000 |
997 // Send an update notification to all child processes so they read the new | 1001 // Send an update notification to all child processes so they read the new |
998 // table. | 1002 // table. |
999 listener_->NewTable(shared_memory_); | 1003 listener_->NewTable(shared_memory_); |
1000 | 1004 |
1001 #ifndef NDEBUG | 1005 #ifndef NDEBUG |
1002 DebugValidate(); | 1006 DebugValidate(); |
1003 #endif | 1007 #endif |
1004 | 1008 |
1005 // The new table needs to be written to disk. | 1009 // The new table needs to be written to disk. |
1006 if (persist_to_disk_) | 1010 if (persist_to_disk_) |
1007 WriteFullTable(); | 1011 WriteFullTable(); |
1008 } | 1012 } |
1009 | 1013 |
1010 uint32 VisitedLinkMaster::DefaultTableSize() const { | 1014 uint32_t VisitedLinkMaster::DefaultTableSize() const { |
1011 if (table_size_override_) | 1015 if (table_size_override_) |
1012 return table_size_override_; | 1016 return table_size_override_; |
1013 | 1017 |
1014 return kDefaultTableSize; | 1018 return kDefaultTableSize; |
1015 } | 1019 } |
1016 | 1020 |
1017 uint32 VisitedLinkMaster::NewTableSizeForCount(int32 item_count) const { | 1021 uint32_t VisitedLinkMaster::NewTableSizeForCount(int32_t item_count) const { |
1018 // These table sizes are selected to be the maximum prime number less than | 1022 // These table sizes are selected to be the maximum prime number less than |
1019 // a "convenient" multiple of 1K. | 1023 // a "convenient" multiple of 1K. |
1020 static const int table_sizes[] = { | 1024 static const int table_sizes[] = { |
1021 16381, // 16K = 16384 <- don't shrink below this table size | 1025 16381, // 16K = 16384 <- don't shrink below this table size |
1022 // (should be == default_table_size) | 1026 // (should be == default_table_size) |
1023 32767, // 32K = 32768 | 1027 32767, // 32K = 32768 |
1024 65521, // 64K = 65536 | 1028 65521, // 64K = 65536 |
1025 130051, // 128K = 131072 | 1029 130051, // 128K = 131072 |
1026 262127, // 256K = 262144 | 1030 262127, // 256K = 262144 |
1027 524269, // 512K = 524288 | 1031 524269, // 512K = 524288 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 // Notify the unit test that the rebuild is complete (will be NULL in prod.) | 1109 // Notify the unit test that the rebuild is complete (will be NULL in prod.) |
1106 if (!rebuild_complete_task_.is_null()) { | 1110 if (!rebuild_complete_task_.is_null()) { |
1107 rebuild_complete_task_.Run(); | 1111 rebuild_complete_task_.Run(); |
1108 rebuild_complete_task_.Reset(); | 1112 rebuild_complete_task_.Reset(); |
1109 } | 1113 } |
1110 } | 1114 } |
1111 | 1115 |
1112 void VisitedLinkMaster::WriteToFile(FILE** file, | 1116 void VisitedLinkMaster::WriteToFile(FILE** file, |
1113 off_t offset, | 1117 off_t offset, |
1114 void* data, | 1118 void* data, |
1115 int32 data_size) { | 1119 int32_t data_size) { |
1116 DCHECK(persist_to_disk_); | 1120 DCHECK(persist_to_disk_); |
1117 DCHECK(!table_is_loading_from_file_); | 1121 DCHECK(!table_is_loading_from_file_); |
1118 PostIOTask(FROM_HERE, | 1122 PostIOTask(FROM_HERE, |
1119 base::Bind(&AsyncWrite, file, offset, | 1123 base::Bind(&AsyncWrite, file, offset, |
1120 std::string(static_cast<const char*>(data), data_size))); | 1124 std::string(static_cast<const char*>(data), data_size))); |
1121 } | 1125 } |
1122 | 1126 |
1123 void VisitedLinkMaster::WriteUsedItemCountToFile() { | 1127 void VisitedLinkMaster::WriteUsedItemCountToFile() { |
1124 DCHECK(persist_to_disk_); | 1128 DCHECK(persist_to_disk_); |
1125 if (!file_) | 1129 if (!file_) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 return false; | 1162 return false; |
1159 | 1163 |
1160 size_t num_read = fread(data, 1, data_size, file); | 1164 size_t num_read = fread(data, 1, data_size, file); |
1161 return num_read == data_size; | 1165 return num_read == data_size; |
1162 } | 1166 } |
1163 | 1167 |
1164 // VisitedLinkTableBuilder ---------------------------------------------------- | 1168 // VisitedLinkTableBuilder ---------------------------------------------------- |
1165 | 1169 |
1166 VisitedLinkMaster::TableBuilder::TableBuilder( | 1170 VisitedLinkMaster::TableBuilder::TableBuilder( |
1167 VisitedLinkMaster* master, | 1171 VisitedLinkMaster* master, |
1168 const uint8 salt[LINK_SALT_LENGTH]) | 1172 const uint8_t salt[LINK_SALT_LENGTH]) |
1169 : master_(master), | 1173 : master_(master), success_(true) { |
1170 success_(true) { | |
1171 fingerprints_.reserve(4096); | 1174 fingerprints_.reserve(4096); |
1172 memcpy(salt_, salt, LINK_SALT_LENGTH * sizeof(uint8)); | 1175 memcpy(salt_, salt, LINK_SALT_LENGTH * sizeof(uint8_t)); |
1173 } | 1176 } |
1174 | 1177 |
1175 // TODO(brettw): Do we want to try to cancel the request if this happens? It | 1178 // TODO(brettw): Do we want to try to cancel the request if this happens? It |
1176 // could delay shutdown if there are a lot of URLs. | 1179 // could delay shutdown if there are a lot of URLs. |
1177 void VisitedLinkMaster::TableBuilder::DisownMaster() { | 1180 void VisitedLinkMaster::TableBuilder::DisownMaster() { |
1178 master_ = NULL; | 1181 master_ = NULL; |
1179 } | 1182 } |
1180 | 1183 |
1181 void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) { | 1184 void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) { |
1182 if (!url.is_empty()) { | 1185 if (!url.is_empty()) { |
(...skipping 12 matching lines...) Expand all Loading... |
1195 BrowserThread::UI, FROM_HERE, | 1198 BrowserThread::UI, FROM_HERE, |
1196 base::Bind(&TableBuilder::OnCompleteMainThread, this)); | 1199 base::Bind(&TableBuilder::OnCompleteMainThread, this)); |
1197 } | 1200 } |
1198 | 1201 |
1199 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 1202 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
1200 if (master_) | 1203 if (master_) |
1201 master_->OnTableRebuildComplete(success_, fingerprints_); | 1204 master_->OnTableRebuildComplete(success_, fingerprints_); |
1202 } | 1205 } |
1203 | 1206 |
1204 } // namespace visitedlink | 1207 } // namespace visitedlink |
OLD | NEW |