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 |