| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/browser/visitedlink_master.h" | 5 #include "chrome/browser/visitedlink_master.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <io.h> | 9 #include <io.h> |
| 10 #include <shlobj.h> | 10 #include <shlobj.h> |
| 11 #endif // defined(OS_WIN) | 11 #endif // defined(OS_WIN) |
| 12 #include <stdio.h> | 12 #include <stdio.h> |
| 13 | 13 |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 | 15 |
| 16 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
| 17 #include "app/win_util.h" | 17 #include "app/win_util.h" |
| 18 #endif | 18 #endif |
| 19 #include "base/file_util.h" | 19 #include "base/file_util.h" |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
| 22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
| 23 #include "base/process_util.h" | 23 #include "base/process_util.h" |
| 24 #include "base/rand_util.h" | 24 #include "base/rand_util.h" |
| 25 #include "base/stack_container.h" | 25 #include "base/stack_container.h" |
| 26 #include "base/string_util.h" | 26 #include "base/string_util.h" |
| 27 #include "chrome/browser/browser_process.h" | |
| 28 #include "chrome/browser/chrome_thread.h" | 27 #include "chrome/browser/chrome_thread.h" |
| 29 #include "chrome/browser/history/history.h" | 28 #include "chrome/browser/history/history.h" |
| 30 #include "chrome/browser/profile.h" | 29 #include "chrome/browser/profile.h" |
| 31 | 30 |
| 32 using file_util::ScopedFILE; | 31 using file_util::ScopedFILE; |
| 33 using file_util::OpenFile; | 32 using file_util::OpenFile; |
| 34 using file_util::TruncateFile; | 33 using file_util::TruncateFile; |
| 35 | 34 |
| 36 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; | 35 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; |
| 37 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; | 36 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 suppress_rebuild_ = false; | 247 suppress_rebuild_ = false; |
| 249 profile_ = profile; | 248 profile_ = profile; |
| 250 | 249 |
| 251 #ifndef NDEBUG | 250 #ifndef NDEBUG |
| 252 posted_asynchronous_operation_ = false; | 251 posted_asynchronous_operation_ = false; |
| 253 #endif | 252 #endif |
| 254 } | 253 } |
| 255 | 254 |
| 256 bool VisitedLinkMaster::Init() { | 255 bool VisitedLinkMaster::Init() { |
| 257 if (!InitFromFile()) | 256 if (!InitFromFile()) |
| 258 return InitFromScratch(suppress_rebuild_); | 257 return InitFromScratch(); |
| 259 return true; | 258 return true; |
| 260 } | 259 } |
| 261 | 260 |
| 261 bool VisitedLinkMaster::InitFromFile() { |
| 262 DCHECK(file_ == NULL); |
| 263 |
| 264 FilePath filename; |
| 265 GetDatabaseFileName(&filename); |
| 266 ScopedFILE file_closer(OpenFile(filename, "rb+")); |
| 267 if (!file_closer.get()) |
| 268 return false; |
| 269 |
| 270 int32 num_entries, used_count; |
| 271 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt_)) |
| 272 return false; // Header isn't valid. |
| 273 |
| 274 // Allocate and read the table. |
| 275 if (!CreateURLTable(num_entries, false)) |
| 276 return false; |
| 277 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, |
| 278 hash_table_, num_entries * sizeof(Fingerprint))) { |
| 279 FreeURLTable(); |
| 280 return false; |
| 281 } |
| 282 used_items_ = used_count; |
| 283 |
| 284 #ifndef NDEBUG |
| 285 DebugValidate(); |
| 286 #endif |
| 287 |
| 288 file_ = file_closer.release(); |
| 289 return true; |
| 290 } |
| 291 |
| 292 bool VisitedLinkMaster::InitFromScratch() { |
| 293 int32 table_size = kDefaultTableSize; |
| 294 if (table_size_override_) |
| 295 table_size = table_size_override_; |
| 296 |
| 297 // The salt must be generated before the table so that it can be copied to |
| 298 // the shared memory. |
| 299 GenerateSalt(salt_); |
| 300 if (!CreateURLTable(table_size, true)) |
| 301 return false; |
| 302 |
| 303 #ifndef NDEBUG |
| 304 DebugValidate(); |
| 305 #endif |
| 306 |
| 307 if (suppress_rebuild_) { |
| 308 // When we disallow rebuilds (normally just unit tests), just use the |
| 309 // current empty table. |
| 310 return WriteFullTable(); |
| 311 } |
| 312 |
| 313 // This will build the table from history. On the first run, history will |
| 314 // be empty, so this will be correct. This will also write the new table |
| 315 // to disk. We don't want to save explicitly here, since the rebuild may |
| 316 // not complete, leaving us with an empty but valid visited link database. |
| 317 // In the future, we won't know we need to try rebuilding again. |
| 318 return RebuildTableFromHistory(); |
| 319 } |
| 320 |
| 262 VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) { | 321 VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) { |
| 263 // Extra check that we are not off the record. This should not happen. | 322 // Extra check that we are not off the record. This should not happen. |
| 264 if (profile_ && profile_->IsOffTheRecord()) { | 323 if (profile_ && profile_->IsOffTheRecord()) { |
| 265 NOTREACHED(); | 324 NOTREACHED(); |
| 266 return null_hash_; | 325 return null_hash_; |
| 267 } | 326 } |
| 268 | 327 |
| 269 if (!url.is_valid()) | 328 if (!url.is_valid()) |
| 270 return null_hash_; // Don't add invalid URLs. | 329 return null_hash_; // Don't add invalid URLs. |
| 271 | 330 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 // Write the hash data. | 589 // Write the hash data. |
| 531 WriteToFile(file_, kFileHeaderSize, | 590 WriteToFile(file_, kFileHeaderSize, |
| 532 hash_table_, table_length_ * sizeof(Fingerprint)); | 591 hash_table_, table_length_ * sizeof(Fingerprint)); |
| 533 | 592 |
| 534 // The hash table may have shrunk, so make sure this is the end. | 593 // The hash table may have shrunk, so make sure this is the end. |
| 535 ChromeThread::PostTask( | 594 ChromeThread::PostTask( |
| 536 ChromeThread::FILE, FROM_HERE, new AsyncSetEndOfFile(file_)); | 595 ChromeThread::FILE, FROM_HERE, new AsyncSetEndOfFile(file_)); |
| 537 return true; | 596 return true; |
| 538 } | 597 } |
| 539 | 598 |
| 540 bool VisitedLinkMaster::InitFromFile() { | |
| 541 DCHECK(file_ == NULL); | |
| 542 | |
| 543 FilePath filename; | |
| 544 GetDatabaseFileName(&filename); | |
| 545 ScopedFILE file_closer(OpenFile(filename, "rb+")); | |
| 546 if (!file_closer.get()) | |
| 547 return false; | |
| 548 | |
| 549 int32 num_entries, used_count; | |
| 550 if (!ReadFileHeader(file_closer.get(), &num_entries, &used_count, salt_)) | |
| 551 return false; // Header isn't valid. | |
| 552 | |
| 553 // Allocate and read the table. | |
| 554 if (!CreateURLTable(num_entries, false)) | |
| 555 return false; | |
| 556 if (!ReadFromFile(file_closer.get(), kFileHeaderSize, | |
| 557 hash_table_, num_entries * sizeof(Fingerprint))) { | |
| 558 FreeURLTable(); | |
| 559 return false; | |
| 560 } | |
| 561 used_items_ = used_count; | |
| 562 | |
| 563 #ifndef NDEBUG | |
| 564 DebugValidate(); | |
| 565 #endif | |
| 566 | |
| 567 file_ = file_closer.release(); | |
| 568 return true; | |
| 569 } | |
| 570 | |
| 571 bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) { | |
| 572 int32 table_size = kDefaultTableSize; | |
| 573 if (table_size_override_) | |
| 574 table_size = table_size_override_; | |
| 575 | |
| 576 // The salt must be generated before the table so that it can be copied to | |
| 577 // the shared memory. | |
| 578 GenerateSalt(salt_); | |
| 579 if (!CreateURLTable(table_size, true)) | |
| 580 return false; | |
| 581 | |
| 582 #ifndef NDEBUG | |
| 583 DebugValidate(); | |
| 584 #endif | |
| 585 | |
| 586 if (suppress_rebuild) { | |
| 587 // When we disallow rebuilds (normally just unit tests), just use the | |
| 588 // current empty table. | |
| 589 return WriteFullTable(); | |
| 590 } | |
| 591 | |
| 592 // This will build the table from history. On the first run, history will | |
| 593 // be empty, so this will be correct. This will also write the new table | |
| 594 // to disk. We don't want to save explicitly here, since the rebuild may | |
| 595 // not complete, leaving us with an empty but valid visited link database. | |
| 596 // In the future, we won't know we need to try rebuilding again. | |
| 597 return RebuildTableFromHistory(); | |
| 598 } | |
| 599 | |
| 600 bool VisitedLinkMaster::ReadFileHeader(FILE* file, | 599 bool VisitedLinkMaster::ReadFileHeader(FILE* file, |
| 601 int32* num_entries, | 600 int32* num_entries, |
| 602 int32* used_count, | 601 int32* used_count, |
| 603 uint8 salt[LINK_SALT_LENGTH]) { | 602 uint8 salt[LINK_SALT_LENGTH]) { |
| 604 // Get file size. | 603 // Get file size. |
| 605 // Note that there is no need to seek back to the original location in the | 604 // Note that there is no need to seek back to the original location in the |
| 606 // file since ReadFromFile() [which is the next call accessing the file] | 605 // file since ReadFromFile() [which is the next call accessing the file] |
| 607 // seeks before reading. | 606 // seeks before reading. |
| 608 if (fseek(file, 0, SEEK_END) == -1) | 607 if (fseek(file, 0, SEEK_END) == -1) |
| 609 return false; | 608 return false; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 } | 994 } |
| 996 | 995 |
| 997 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 996 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 998 if (master_) | 997 if (master_) |
| 999 master_->OnTableRebuildComplete(success_, fingerprints_); | 998 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 1000 | 999 |
| 1001 // WILL (generally) DELETE THIS! This balances the AddRef in | 1000 // WILL (generally) DELETE THIS! This balances the AddRef in |
| 1002 // VisitedLinkMaster::RebuildTableFromHistory. | 1001 // VisitedLinkMaster::RebuildTableFromHistory. |
| 1003 Release(); | 1002 Release(); |
| 1004 } | 1003 } |
| OLD | NEW |