| 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 |