| 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 "chrome/browser/visitedlink/visitedlink_master.h" | 5 #include "chrome/browser/visitedlink/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 #include "base/bind.h" | 16 #include "base/bind.h" |
| 17 #include "base/bind_helpers.h" | 17 #include "base/bind_helpers.h" |
| 18 #include "base/containers/stack_container.h" | 18 #include "base/containers/stack_container.h" |
| 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/string_util.h" | 25 #include "base/string_util.h" |
| 26 #include "base/threading/thread_restrictions.h" | 26 #include "base/threading/thread_restrictions.h" |
| 27 #include "chrome/browser/history/history.h" | 27 #include "chrome/browser/visitedlink/visitedlink_delegate.h" |
| 28 #include "chrome/browser/history/history_service_factory.h" | |
| 29 #include "chrome/browser/profiles/profile.h" | |
| 30 #include "chrome/browser/visitedlink/visitedlink_event_listener.h" | 28 #include "chrome/browser/visitedlink/visitedlink_event_listener.h" |
| 29 #include "content/public/browser/browser_context.h" |
| 31 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
| 31 #include "googleurl/src/gurl.h" |
| 32 | 32 |
| 33 using content::BrowserThread; | 33 using content::BrowserThread; |
| 34 using file_util::ScopedFILE; | 34 using file_util::ScopedFILE; |
| 35 using file_util::OpenFile; | 35 using file_util::OpenFile; |
| 36 using file_util::TruncateFile; | 36 using file_util::TruncateFile; |
| 37 | 37 |
| 38 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; | 38 const int32 VisitedLinkMaster::kFileHeaderSignatureOffset = 0; |
| 39 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; | 39 const int32 VisitedLinkMaster::kFileHeaderVersionOffset = 4; |
| 40 const int32 VisitedLinkMaster::kFileHeaderLengthOffset = 8; | 40 const int32 VisitedLinkMaster::kFileHeaderLengthOffset = 8; |
| 41 const int32 VisitedLinkMaster::kFileHeaderUsedOffset = 12; | 41 const int32 VisitedLinkMaster::kFileHeaderUsedOffset = 12; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 // The builder will store the fingerprints for those URLs, and then marshalls | 131 // The builder will store the fingerprints for those URLs, and then marshalls |
| 132 // back to the main thread where the VisitedLinkMaster will be notified. The | 132 // back to the main thread where the VisitedLinkMaster will be notified. The |
| 133 // master then replaces its table with a new table containing the computed | 133 // master then replaces its table with a new table containing the computed |
| 134 // fingerprints. | 134 // fingerprints. |
| 135 // | 135 // |
| 136 // The builder must remain active while the history system is using it. | 136 // The builder must remain active while the history system is using it. |
| 137 // Sometimes, the master will be deleted before the rebuild is complete, in | 137 // Sometimes, the master will be deleted before the rebuild is complete, in |
| 138 // which case it notifies the builder via DisownMaster(). The builder will | 138 // which case it notifies the builder via DisownMaster(). The builder will |
| 139 // delete itself once rebuilding is complete, and not execute any callback. | 139 // delete itself once rebuilding is complete, and not execute any callback. |
| 140 class VisitedLinkMaster::TableBuilder | 140 class VisitedLinkMaster::TableBuilder |
| 141 : public HistoryService::URLEnumerator, | 141 : public VisitedLinkDelegate::URLEnumerator { |
| 142 public base::RefCountedThreadSafe<TableBuilder> { | |
| 143 public: | 142 public: |
| 144 TableBuilder(VisitedLinkMaster* master, | 143 TableBuilder(VisitedLinkMaster* master, |
| 145 const uint8 salt[LINK_SALT_LENGTH]); | 144 const uint8 salt[LINK_SALT_LENGTH]); |
| 146 | 145 |
| 147 // Called on the main thread when the master is being destroyed. This will | 146 // Called on the main thread when the master is being destroyed. This will |
| 148 // prevent a crash when the query completes and the master is no longer | 147 // prevent a crash when the query completes and the master is no longer |
| 149 // around. We can not actually do anything but mark this fact, since the | 148 // around. We can not actually do anything but mark this fact, since the |
| 150 // table will be being rebuilt simultaneously on the other thread. | 149 // table will be being rebuilt simultaneously on the other thread. |
| 151 void DisownMaster(); | 150 void DisownMaster(); |
| 152 | 151 |
| 153 // HistoryService::URLEnumerator | 152 // VisitedLinkDelegate::URLEnumerator |
| 154 virtual void OnURL(const history::URLRow& url_row); | 153 virtual void OnURL(const GURL& url); |
| 155 virtual void OnComplete(bool succeed); | 154 virtual void OnComplete(bool succeed); |
| 156 | 155 |
| 157 private: | 156 private: |
| 158 friend class base::RefCountedThreadSafe<TableBuilder>; | 157 virtual ~TableBuilder() {} |
| 159 | |
| 160 ~TableBuilder() {} | |
| 161 | 158 |
| 162 // OnComplete mashals to this function on the main thread to do the | 159 // OnComplete mashals to this function on the main thread to do the |
| 163 // notification. | 160 // notification. |
| 164 void OnCompleteMainThread(); | 161 void OnCompleteMainThread(); |
| 165 | 162 |
| 166 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! | 163 // Owner of this object. MAY ONLY BE ACCESSED ON THE MAIN THREAD! |
| 167 VisitedLinkMaster* master_; | 164 VisitedLinkMaster* master_; |
| 168 | 165 |
| 169 // Indicates whether the operation has failed or not. | 166 // Indicates whether the operation has failed or not. |
| 170 bool success_; | 167 bool success_; |
| 171 | 168 |
| 172 // Salt for this new table. | 169 // Salt for this new table. |
| 173 uint8 salt_[LINK_SALT_LENGTH]; | 170 uint8 salt_[LINK_SALT_LENGTH]; |
| 174 | 171 |
| 175 // Stores the fingerprints we computed on the background thread. | 172 // Stores the fingerprints we computed on the background thread. |
| 176 VisitedLinkCommon::Fingerprints fingerprints_; | 173 VisitedLinkCommon::Fingerprints fingerprints_; |
| 174 |
| 175 DISALLOW_COPY_AND_ASSIGN(TableBuilder); |
| 177 }; | 176 }; |
| 178 | 177 |
| 179 // VisitedLinkMaster ---------------------------------------------------------- | 178 // VisitedLinkMaster ---------------------------------------------------------- |
| 180 | 179 |
| 181 VisitedLinkMaster::VisitedLinkMaster(Profile* profile) | 180 VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context, |
| 182 : profile_(profile) { | 181 VisitedLinkDelegate* delegate) |
| 183 listener_.reset(new VisitedLinkEventListener(profile)); | 182 : browser_context_(browser_context), |
| 184 DCHECK(listener_.get()); | 183 delegate_(delegate), |
| 184 listener_(new VisitedLinkEventListener( |
| 185 ALLOW_THIS_IN_INITIALIZER_LIST(this), browser_context)) { |
| 185 InitMembers(); | 186 InitMembers(); |
| 186 } | 187 } |
| 187 | 188 |
| 188 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, | 189 VisitedLinkMaster::VisitedLinkMaster(Listener* listener, |
| 189 HistoryService* history_service, | 190 VisitedLinkDelegate* delegate, |
| 190 bool suppress_rebuild, | 191 bool suppress_rebuild, |
| 191 const FilePath& filename, | 192 const FilePath& filename, |
| 192 int32 default_table_size) | 193 int32 default_table_size) |
| 193 : profile_(NULL) { | 194 : browser_context_(NULL), |
| 195 delegate_(delegate) { |
| 194 listener_.reset(listener); | 196 listener_.reset(listener); |
| 195 DCHECK(listener_.get()); | 197 DCHECK(listener_.get()); |
| 196 InitMembers(); | 198 InitMembers(); |
| 197 | 199 |
| 198 database_name_override_ = filename; | 200 database_name_override_ = filename; |
| 199 table_size_override_ = default_table_size; | 201 table_size_override_ = default_table_size; |
| 200 history_service_override_ = history_service; | |
| 201 suppress_rebuild_ = suppress_rebuild; | 202 suppress_rebuild_ = suppress_rebuild; |
| 202 } | 203 } |
| 203 | 204 |
| 204 VisitedLinkMaster::~VisitedLinkMaster() { | 205 VisitedLinkMaster::~VisitedLinkMaster() { |
| 205 if (table_builder_.get()) { | 206 if (table_builder_.get()) { |
| 206 // Prevent the table builder from calling us back now that we're being | 207 // Prevent the table builder from calling us back now that we're being |
| 207 // destroyed. Note that we DON'T delete the object, since the history | 208 // destroyed. Note that we DON'T delete the object, since the history |
| 208 // system is still writing into it. When that is complete, the table | 209 // system is still writing into it. When that is complete, the table |
| 209 // builder will destroy itself when it finds we are gone. | 210 // builder will destroy itself when it finds we are gone. |
| 210 table_builder_->DisownMaster(); | 211 table_builder_->DisownMaster(); |
| 211 } | 212 } |
| 212 FreeURLTable(); | 213 FreeURLTable(); |
| 213 // FreeURLTable() will schedule closing of the file and deletion of |file_|. | 214 // FreeURLTable() will schedule closing of the file and deletion of |file_|. |
| 214 // So nothing should be done here. | 215 // So nothing should be done here. |
| 215 } | 216 } |
| 216 | 217 |
| 217 void VisitedLinkMaster::InitMembers() { | 218 void VisitedLinkMaster::InitMembers() { |
| 218 file_ = NULL; | 219 file_ = NULL; |
| 219 shared_memory_ = NULL; | 220 shared_memory_ = NULL; |
| 220 shared_memory_serial_ = 0; | 221 shared_memory_serial_ = 0; |
| 221 used_items_ = 0; | 222 used_items_ = 0; |
| 222 table_size_override_ = 0; | 223 table_size_override_ = 0; |
| 223 history_service_override_ = NULL; | |
| 224 suppress_rebuild_ = false; | 224 suppress_rebuild_ = false; |
| 225 sequence_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); | 225 sequence_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); |
| 226 | 226 |
| 227 #ifndef NDEBUG | 227 #ifndef NDEBUG |
| 228 posted_asynchronous_operation_ = false; | 228 posted_asynchronous_operation_ = false; |
| 229 #endif | 229 #endif |
| 230 } | 230 } |
| 231 | 231 |
| 232 bool VisitedLinkMaster::Init() { | 232 bool VisitedLinkMaster::Init() { |
| 233 // We probably shouldn't be loading this from the UI thread, | 233 // We probably shouldn't be loading this from the UI thread, |
| 234 // but it does need to happen early on in startup. | 234 // but it does need to happen early on in startup. |
| 235 // http://code.google.com/p/chromium/issues/detail?id=24163 | 235 // http://code.google.com/p/chromium/issues/detail?id=24163 |
| 236 base::ThreadRestrictions::ScopedAllowIO allow_io; | 236 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 237 if (!InitFromFile()) | 237 if (!InitFromFile()) |
| 238 return InitFromScratch(suppress_rebuild_); | 238 return InitFromScratch(suppress_rebuild_); |
| 239 return true; | 239 return true; |
| 240 } | 240 } |
| 241 | 241 |
| 242 VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) { | 242 VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) { |
| 243 // Extra check that we are not incognito. This should not happen. | 243 // Extra check that we are not incognito. This should not happen. |
| 244 if (profile_ && profile_->IsOffTheRecord()) { | 244 // TODO(boliu): Move this check to HistoryService when IsOffTheRecord is |
| 245 // removed from BrowserContext. |
| 246 if (browser_context_ && browser_context_->IsOffTheRecord()) { |
| 245 NOTREACHED(); | 247 NOTREACHED(); |
| 246 return null_hash_; | 248 return null_hash_; |
| 247 } | 249 } |
| 248 | 250 |
| 249 if (!url.is_valid()) | 251 if (!url.is_valid()) |
| 250 return null_hash_; // Don't add invalid URLs. | 252 return null_hash_; // Don't add invalid URLs. |
| 251 | 253 |
| 252 Fingerprint fingerprint = ComputeURLFingerprint(url.spec().data(), | 254 Fingerprint fingerprint = ComputeURLFingerprint(url.spec().data(), |
| 253 url.spec().size(), | 255 url.spec().size(), |
| 254 salt_); | 256 salt_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 memset(hash_table_, 0, this->table_length_ * sizeof(Fingerprint)); | 315 memset(hash_table_, 0, this->table_length_ * sizeof(Fingerprint)); |
| 314 | 316 |
| 315 // Resize it if it is now too empty. Resize may write the new table out for | 317 // Resize it if it is now too empty. Resize may write the new table out for |
| 316 // us, otherwise, schedule writing the new table to disk ourselves. | 318 // us, otherwise, schedule writing the new table to disk ourselves. |
| 317 if (!ResizeTableIfNecessary()) | 319 if (!ResizeTableIfNecessary()) |
| 318 WriteFullTable(); | 320 WriteFullTable(); |
| 319 | 321 |
| 320 listener_->Reset(); | 322 listener_->Reset(); |
| 321 } | 323 } |
| 322 | 324 |
| 323 void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) { | 325 VisitedLinkDelegate* VisitedLinkMaster::GetDelegate() { |
| 324 typedef std::set<GURL>::const_iterator SetIterator; | 326 return delegate_; |
| 327 } |
| 325 | 328 |
| 326 if (rows.empty()) | 329 void VisitedLinkMaster::DeleteURLs(URLIterator* urls) { |
| 330 if (!urls->HasNextURL()) |
| 327 return; | 331 return; |
| 328 | 332 |
| 329 listener_->Reset(); | 333 listener_->Reset(); |
| 330 | 334 |
| 331 if (table_builder_) { | 335 if (table_builder_) { |
| 332 // A rebuild is in progress, save this deletion in the temporary list so | 336 // A rebuild is in progress, save this deletion in the temporary list so |
| 333 // it can be added once rebuild is complete. | 337 // it can be added once rebuild is complete. |
| 334 for (history::URLRows::const_iterator i = rows.begin(); i != rows.end(); | 338 while (urls->HasNextURL()) { |
| 335 ++i) { | 339 const GURL& url(urls->NextURL()); |
| 336 const GURL& url(i->url()); | |
| 337 if (!url.is_valid()) | 340 if (!url.is_valid()) |
| 338 continue; | 341 continue; |
| 339 | 342 |
| 340 Fingerprint fingerprint = | 343 Fingerprint fingerprint = |
| 341 ComputeURLFingerprint(url.spec().data(), url.spec().size(), salt_); | 344 ComputeURLFingerprint(url.spec().data(), url.spec().size(), salt_); |
| 342 deleted_since_rebuild_.insert(fingerprint); | 345 deleted_since_rebuild_.insert(fingerprint); |
| 343 | 346 |
| 344 // If the URL was just added and now we're deleting it, it may be in the | 347 // If the URL was just added and now we're deleting it, it may be in the |
| 345 // list of things added since the last rebuild. Delete it from that list. | 348 // list of things added since the last rebuild. Delete it from that list. |
| 346 std::set<Fingerprint>::iterator found = | 349 std::set<Fingerprint>::iterator found = |
| 347 added_since_rebuild_.find(fingerprint); | 350 added_since_rebuild_.find(fingerprint); |
| 348 if (found != added_since_rebuild_.end()) | 351 if (found != added_since_rebuild_.end()) |
| 349 added_since_rebuild_.erase(found); | 352 added_since_rebuild_.erase(found); |
| 350 | 353 |
| 351 // Delete the URLs from the in-memory table, but don't bother writing | 354 // Delete the URLs from the in-memory table, but don't bother writing |
| 352 // to disk since it will be replaced soon. | 355 // to disk since it will be replaced soon. |
| 353 DeleteFingerprint(fingerprint, false); | 356 DeleteFingerprint(fingerprint, false); |
| 354 } | 357 } |
| 355 return; | 358 return; |
| 356 } | 359 } |
| 357 | 360 |
| 358 // Compute the deleted URLs' fingerprints and delete them | 361 // Compute the deleted URLs' fingerprints and delete them |
| 359 std::set<Fingerprint> deleted_fingerprints; | 362 std::set<Fingerprint> deleted_fingerprints; |
| 360 for (history::URLRows::const_iterator i = rows.begin(); i != rows.end(); | 363 while (urls->HasNextURL()) { |
| 361 ++i) { | 364 const GURL& url(urls->NextURL()); |
| 362 const GURL& url(i->url()); | |
| 363 if (!url.is_valid()) | 365 if (!url.is_valid()) |
| 364 continue; | 366 continue; |
| 365 deleted_fingerprints.insert( | 367 deleted_fingerprints.insert( |
| 366 ComputeURLFingerprint(url.spec().data(), url.spec().size(), salt_)); | 368 ComputeURLFingerprint(url.spec().data(), url.spec().size(), salt_)); |
| 367 } | 369 } |
| 368 DeleteFingerprintsFromCurrentTable(deleted_fingerprints); | 370 DeleteFingerprintsFromCurrentTable(deleted_fingerprints); |
| 369 } | 371 } |
| 370 | 372 |
| 371 // See VisitedLinkCommon::IsVisited which should be in sync with this algorithm | 373 // See VisitedLinkCommon::IsVisited which should be in sync with this algorithm |
| 372 VisitedLinkMaster::Hash VisitedLinkMaster::AddFingerprint( | 374 VisitedLinkMaster::Hash VisitedLinkMaster::AddFingerprint( |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 // current empty table. | 576 // current empty table. |
| 575 WriteFullTable(); | 577 WriteFullTable(); |
| 576 return true; | 578 return true; |
| 577 } | 579 } |
| 578 | 580 |
| 579 // This will build the table from history. On the first run, history will | 581 // This will build the table from history. On the first run, history will |
| 580 // be empty, so this will be correct. This will also write the new table | 582 // be empty, so this will be correct. This will also write the new table |
| 581 // to disk. We don't want to save explicitly here, since the rebuild may | 583 // to disk. We don't want to save explicitly here, since the rebuild may |
| 582 // not complete, leaving us with an empty but valid visited link database. | 584 // not complete, leaving us with an empty but valid visited link database. |
| 583 // In the future, we won't know we need to try rebuilding again. | 585 // In the future, we won't know we need to try rebuilding again. |
| 584 return RebuildTableFromHistory(); | 586 return RebuildTableFromDelegate(); |
| 585 } | 587 } |
| 586 | 588 |
| 587 bool VisitedLinkMaster::ReadFileHeader(FILE* file, | 589 bool VisitedLinkMaster::ReadFileHeader(FILE* file, |
| 588 int32* num_entries, | 590 int32* num_entries, |
| 589 int32* used_count, | 591 int32* used_count, |
| 590 uint8 salt[LINK_SALT_LENGTH]) { | 592 uint8 salt[LINK_SALT_LENGTH]) { |
| 591 // Get file size. | 593 // Get file size. |
| 592 // Note that there is no need to seek back to the original location in the | 594 // Note that there is no need to seek back to the original location in the |
| 593 // file since ReadFromFile() [which is the next call accessing the file] | 595 // file since ReadFromFile() [which is the next call accessing the file] |
| 594 // seeks before reading. | 596 // seeks before reading. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 return true; | 636 return true; |
| 635 } | 637 } |
| 636 | 638 |
| 637 bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) { | 639 bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) { |
| 638 if (!database_name_override_.empty()) { | 640 if (!database_name_override_.empty()) { |
| 639 // use this filename, the directory must exist | 641 // use this filename, the directory must exist |
| 640 *filename = database_name_override_; | 642 *filename = database_name_override_; |
| 641 return true; | 643 return true; |
| 642 } | 644 } |
| 643 | 645 |
| 644 if (!profile_ || profile_->GetPath().empty()) | 646 if (!browser_context_ || browser_context_->GetPath().empty()) |
| 645 return false; | 647 return false; |
| 646 | 648 |
| 647 FilePath profile_dir = profile_->GetPath(); | 649 FilePath profile_dir = browser_context_->GetPath(); |
| 648 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); | 650 *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); |
| 649 return true; | 651 return true; |
| 650 } | 652 } |
| 651 | 653 |
| 652 // Initializes the shared memory structure. The salt should already be filled | 654 // Initializes the shared memory structure. The salt should already be filled |
| 653 // in so that it can be written to the shared memory | 655 // in so that it can be written to the shared memory |
| 654 bool VisitedLinkMaster::CreateURLTable(int32 num_entries, bool init_to_empty) { | 656 bool VisitedLinkMaster::CreateURLTable(int32 num_entries, bool init_to_empty) { |
| 655 // The table is the size of the table followed by the entries. | 657 // The table is the size of the table followed by the entries. |
| 656 uint32 alloc_size = num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); | 658 uint32 alloc_size = num_entries * sizeof(Fingerprint) + sizeof(SharedHeader); |
| 657 | 659 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 if (table_sizes[i] > desired) | 805 if (table_sizes[i] > desired) |
| 804 return table_sizes[i]; | 806 return table_sizes[i]; |
| 805 } | 807 } |
| 806 | 808 |
| 807 // Growing very big, just approximate a "good" number, not growing as much | 809 // Growing very big, just approximate a "good" number, not growing as much |
| 808 // as normal. | 810 // as normal. |
| 809 return item_count * 2 - 1; | 811 return item_count * 2 - 1; |
| 810 } | 812 } |
| 811 | 813 |
| 812 // See the TableBuilder definition in the header file for how this works. | 814 // See the TableBuilder definition in the header file for how this works. |
| 813 bool VisitedLinkMaster::RebuildTableFromHistory() { | 815 bool VisitedLinkMaster::RebuildTableFromDelegate() { |
| 814 DCHECK(!table_builder_); | 816 DCHECK(!table_builder_); |
| 815 if (table_builder_) | |
| 816 return false; | |
| 817 | |
| 818 HistoryService* history_service = history_service_override_; | |
| 819 if (!history_service && profile_) { | |
| 820 history_service = | |
| 821 HistoryServiceFactory::GetForProfile(profile_, | |
| 822 Profile::EXPLICIT_ACCESS); | |
| 823 } | |
| 824 | |
| 825 if (!history_service) { | |
| 826 DLOG(WARNING) << "Attempted to rebuild visited link table, but couldn't " | |
| 827 "obtain a HistoryService."; | |
| 828 return false; | |
| 829 } | |
| 830 | 817 |
| 831 // TODO(brettw) make sure we have reasonable salt! | 818 // TODO(brettw) make sure we have reasonable salt! |
| 832 table_builder_ = new TableBuilder(this, salt_); | 819 table_builder_ = new TableBuilder(this, salt_); |
| 833 | 820 delegate_->RebuildTable(table_builder_); |
| 834 // Make sure the table builder stays live during the call, even if the | |
| 835 // master is deleted. This is balanced in TableBuilder::OnCompleteMainThread. | |
| 836 table_builder_->AddRef(); | |
| 837 history_service->IterateURLs(table_builder_); | |
| 838 return true; | 821 return true; |
| 839 } | 822 } |
| 840 | 823 |
| 841 // See the TableBuilder declaration above for how this works. | 824 // See the TableBuilder declaration above for how this works. |
| 842 void VisitedLinkMaster::OnTableRebuildComplete( | 825 void VisitedLinkMaster::OnTableRebuildComplete( |
| 843 bool success, | 826 bool success, |
| 844 const std::vector<Fingerprint>& fingerprints) { | 827 const std::vector<Fingerprint>& fingerprints) { |
| 845 if (success) { | 828 if (success) { |
| 846 // Replace the old table with a new blank one. | 829 // Replace the old table with a new blank one. |
| 847 shared_memory_serial_++; | 830 shared_memory_serial_++; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 fingerprints_.reserve(4096); | 934 fingerprints_.reserve(4096); |
| 952 memcpy(salt_, salt, LINK_SALT_LENGTH * sizeof(uint8)); | 935 memcpy(salt_, salt, LINK_SALT_LENGTH * sizeof(uint8)); |
| 953 } | 936 } |
| 954 | 937 |
| 955 // TODO(brettw): Do we want to try to cancel the request if this happens? It | 938 // TODO(brettw): Do we want to try to cancel the request if this happens? It |
| 956 // could delay shutdown if there are a lot of URLs. | 939 // could delay shutdown if there are a lot of URLs. |
| 957 void VisitedLinkMaster::TableBuilder::DisownMaster() { | 940 void VisitedLinkMaster::TableBuilder::DisownMaster() { |
| 958 master_ = NULL; | 941 master_ = NULL; |
| 959 } | 942 } |
| 960 | 943 |
| 961 void VisitedLinkMaster::TableBuilder::OnURL(const history::URLRow& url_row) { | 944 void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) { |
| 962 const GURL& url(url_row.url()); | |
| 963 if (!url.is_empty()) { | 945 if (!url.is_empty()) { |
| 964 fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint( | 946 fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint( |
| 965 url.spec().data(), url.spec().length(), salt_)); | 947 url.spec().data(), url.spec().length(), salt_)); |
| 966 } | 948 } |
| 967 } | 949 } |
| 968 | 950 |
| 969 void VisitedLinkMaster::TableBuilder::OnComplete(bool success) { | 951 void VisitedLinkMaster::TableBuilder::OnComplete(bool success) { |
| 970 success_ = success; | 952 success_ = success; |
| 971 DLOG_IF(WARNING, !success) << "Unable to rebuild visited links"; | 953 DLOG_IF(WARNING, !success) << "Unable to rebuild visited links"; |
| 972 | 954 |
| 973 // Marshal to the main thread to notify the VisitedLinkMaster that the | 955 // Marshal to the main thread to notify the VisitedLinkMaster that the |
| 974 // rebuild is complete. | 956 // rebuild is complete. |
| 975 BrowserThread::PostTask( | 957 BrowserThread::PostTask( |
| 976 BrowserThread::UI, FROM_HERE, | 958 BrowserThread::UI, FROM_HERE, |
| 977 base::Bind(&TableBuilder::OnCompleteMainThread, this)); | 959 base::Bind(&TableBuilder::OnCompleteMainThread, this)); |
| 978 } | 960 } |
| 979 | 961 |
| 980 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { | 962 void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { |
| 981 if (master_) | 963 if (master_) |
| 982 master_->OnTableRebuildComplete(success_, fingerprints_); | 964 master_->OnTableRebuildComplete(success_, fingerprints_); |
| 983 | |
| 984 // WILL (generally) DELETE THIS! This balances the AddRef in | |
| 985 // VisitedLinkMaster::RebuildTableFromHistory. | |
| 986 Release(); | |
| 987 } | 965 } |
| OLD | NEW |