| 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/history/history_backend.h" | 5 #include "chrome/browser/history/history_backend.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <list> | 9 #include <list> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 URLDatabase (stores a list of URLs) | 60 URLDatabase (stores a list of URLs) |
| 61 DownloadDatabase (stores a list of downloads) | 61 DownloadDatabase (stores a list of downloads) |
| 62 VisitDatabase (stores a list of visits for the URLs) | 62 VisitDatabase (stores a list of visits for the URLs) |
| 63 VisitSegmentDatabase (stores groups of URLs for the most visited view). | 63 VisitSegmentDatabase (stores groups of URLs for the most visited view). |
| 64 | 64 |
| 65 ExpireHistoryBackend (manages deleting things older than 3 months) | 65 ExpireHistoryBackend (manages deleting things older than 3 months) |
| 66 */ | 66 */ |
| 67 | 67 |
| 68 namespace history { | 68 namespace history { |
| 69 | 69 |
| 70 namespace { |
| 71 void RunUnlessCanceled( |
| 72 const base::Closure& closure, |
| 73 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) { |
| 74 if (!is_canceled.Run()) |
| 75 closure.Run(); |
| 76 } |
| 77 } // namespace |
| 78 |
| 70 #if defined(OS_ANDROID) | 79 #if defined(OS_ANDROID) |
| 71 // How long we keep segment data for in days. Currently 3 months. | 80 // How long we keep segment data for in days. Currently 3 months. |
| 72 // This value needs to be greater or equal to | 81 // This value needs to be greater or equal to |
| 73 // MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct | 82 // MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct |
| 74 // dependency between MostVisitedModel and the history backend. | 83 // dependency between MostVisitedModel and the history backend. |
| 75 const int kSegmentDataRetention = 90; | 84 const int kSegmentDataRetention = 90; |
| 76 #endif | 85 #endif |
| 77 | 86 |
| 78 // How long we'll wait to do a commit, so that things are batched together. | 87 // How long we'll wait to do a commit, so that things are batched together. |
| 79 const int kCommitIntervalSeconds = 10; | 88 const int kCommitIntervalSeconds = 10; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } | 157 } |
| 149 | 158 |
| 150 private: | 159 private: |
| 151 friend class base::RefCounted<CommitLaterTask>; | 160 friend class base::RefCounted<CommitLaterTask>; |
| 152 | 161 |
| 153 ~CommitLaterTask() {} | 162 ~CommitLaterTask() {} |
| 154 | 163 |
| 155 scoped_refptr<HistoryBackend> history_backend_; | 164 scoped_refptr<HistoryBackend> history_backend_; |
| 156 }; | 165 }; |
| 157 | 166 |
| 167 // QueuedHistoryDBTask --------------------------------------------------------- |
| 168 |
| 169 QueuedHistoryDBTask::QueuedHistoryDBTask( |
| 170 scoped_refptr<HistoryDBTask> task, |
| 171 scoped_refptr<base::SingleThreadTaskRunner> origin_loop, |
| 172 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) |
| 173 : task_(task), origin_loop_(origin_loop), is_canceled_(is_canceled) { |
| 174 DCHECK(task_); |
| 175 DCHECK(origin_loop_); |
| 176 DCHECK(!is_canceled_.is_null()); |
| 177 } |
| 178 |
| 179 QueuedHistoryDBTask::~QueuedHistoryDBTask() { |
| 180 } |
| 181 |
| 182 bool QueuedHistoryDBTask::is_canceled() { |
| 183 return is_canceled_.Run(); |
| 184 } |
| 185 |
| 186 bool QueuedHistoryDBTask::RunOnDBThread(HistoryBackend* backend, |
| 187 HistoryDatabase* db) { |
| 188 return task_->RunOnDBThread(backend, db); |
| 189 } |
| 190 |
| 191 void QueuedHistoryDBTask::DoneRunOnMainThread() { |
| 192 origin_loop_->PostTask( |
| 193 FROM_HERE, |
| 194 base::Bind(&RunUnlessCanceled, |
| 195 base::Bind(&HistoryDBTask::DoneRunOnMainThread, task_), |
| 196 is_canceled_)); |
| 197 } |
| 198 |
| 158 // HistoryBackend -------------------------------------------------------------- | 199 // HistoryBackend -------------------------------------------------------------- |
| 159 | 200 |
| 160 HistoryBackend::HistoryBackend(const base::FilePath& history_dir, | 201 HistoryBackend::HistoryBackend(const base::FilePath& history_dir, |
| 161 Delegate* delegate, | 202 Delegate* delegate, |
| 162 HistoryClient* history_client) | 203 HistoryClient* history_client) |
| 163 : delegate_(delegate), | 204 : delegate_(delegate), |
| 164 history_dir_(history_dir), | 205 history_dir_(history_dir), |
| 165 scheduled_kill_db_(false), | 206 scheduled_kill_db_(false), |
| 166 expirer_(this, history_client), | 207 expirer_(this, history_client), |
| 167 recent_redirects_(kMaxRedirectCount), | 208 recent_redirects_(kMaxRedirectCount), |
| 168 backend_destroy_message_loop_(NULL), | 209 backend_destroy_message_loop_(NULL), |
| 169 segment_queried_(false), | 210 segment_queried_(false), |
| 170 history_client_(history_client) { | 211 history_client_(history_client) { |
| 171 } | 212 } |
| 172 | 213 |
| 173 HistoryBackend::~HistoryBackend() { | 214 HistoryBackend::~HistoryBackend() { |
| 174 DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; | 215 DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; |
| 175 ReleaseDBTasks(); | 216 queued_history_db_tasks_.clear(); |
| 176 | 217 |
| 177 #if defined(OS_ANDROID) | 218 #if defined(OS_ANDROID) |
| 178 // Release AndroidProviderBackend before other objects. | 219 // Release AndroidProviderBackend before other objects. |
| 179 android_provider_backend_.reset(); | 220 android_provider_backend_.reset(); |
| 180 #endif | 221 #endif |
| 181 | 222 |
| 182 // First close the databases before optionally running the "destroy" task. | 223 // First close the databases before optionally running the "destroy" task. |
| 183 CloseAllDatabases(); | 224 CloseAllDatabases(); |
| 184 | 225 |
| 185 if (!backend_destroy_task_.is_null()) { | 226 if (!backend_destroy_task_.is_null()) { |
| (...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2281 void HistoryBackend::CancelScheduledCommit() { | 2322 void HistoryBackend::CancelScheduledCommit() { |
| 2282 if (scheduled_commit_.get()) { | 2323 if (scheduled_commit_.get()) { |
| 2283 scheduled_commit_->Cancel(); | 2324 scheduled_commit_->Cancel(); |
| 2284 scheduled_commit_ = NULL; | 2325 scheduled_commit_ = NULL; |
| 2285 } | 2326 } |
| 2286 } | 2327 } |
| 2287 | 2328 |
| 2288 void HistoryBackend::ProcessDBTaskImpl() { | 2329 void HistoryBackend::ProcessDBTaskImpl() { |
| 2289 if (!db_) { | 2330 if (!db_) { |
| 2290 // db went away, release all the refs. | 2331 // db went away, release all the refs. |
| 2291 ReleaseDBTasks(); | 2332 queued_history_db_tasks_.clear(); |
| 2292 return; | 2333 return; |
| 2293 } | 2334 } |
| 2294 | 2335 |
| 2295 // Remove any canceled tasks. | 2336 // Remove any canceled tasks. |
| 2296 while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { | 2337 while (!queued_history_db_tasks_.empty()) { |
| 2297 db_task_requests_.front()->Release(); | 2338 QueuedHistoryDBTask& task = queued_history_db_tasks_.front(); |
| 2298 db_task_requests_.pop_front(); | 2339 if (!task.is_canceled()) { |
| 2340 break; |
| 2341 } |
| 2342 queued_history_db_tasks_.pop_front(); |
| 2299 } | 2343 } |
| 2300 if (db_task_requests_.empty()) | 2344 if (queued_history_db_tasks_.empty()) |
| 2301 return; | 2345 return; |
| 2302 | 2346 |
| 2303 // Run the first task. | 2347 // Run the first task. |
| 2304 HistoryDBTaskRequest* request = db_task_requests_.front(); | 2348 QueuedHistoryDBTask task = queued_history_db_tasks_.front(); |
| 2305 db_task_requests_.pop_front(); | 2349 queued_history_db_tasks_.pop_front(); |
| 2306 if (request->value->RunOnDBThread(this, db_.get())) { | 2350 if (task.RunOnDBThread(this, db_.get())) { |
| 2307 // The task is done. Notify the callback. | 2351 // The task is done, notify the callback. |
| 2308 request->ForwardResult(); | 2352 task.DoneRunOnMainThread(); |
| 2309 // We AddRef'd the request before adding, need to release it now. | |
| 2310 request->Release(); | |
| 2311 } else { | 2353 } else { |
| 2312 // Tasks wants to run some more. Schedule it at the end of current tasks. | 2354 // The task wants to run some more. Schedule it at the end of the current |
| 2313 db_task_requests_.push_back(request); | 2355 // tasks, and process it after an invoke later. |
| 2314 // And process it after an invoke later. | 2356 queued_history_db_tasks_.insert(queued_history_db_tasks_.end(), task); |
| 2315 base::MessageLoop::current()->PostTask( | 2357 base::MessageLoop::current()->PostTask( |
| 2316 FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); | 2358 FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); |
| 2317 } | 2359 } |
| 2318 } | 2360 } |
| 2319 | 2361 |
| 2320 void HistoryBackend::ReleaseDBTasks() { | |
| 2321 for (std::list<HistoryDBTaskRequest*>::iterator i = | |
| 2322 db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { | |
| 2323 (*i)->Release(); | |
| 2324 } | |
| 2325 db_task_requests_.clear(); | |
| 2326 } | |
| 2327 | |
| 2328 //////////////////////////////////////////////////////////////////////////////// | 2362 //////////////////////////////////////////////////////////////////////////////// |
| 2329 // | 2363 // |
| 2330 // Generic operations | 2364 // Generic operations |
| 2331 // | 2365 // |
| 2332 //////////////////////////////////////////////////////////////////////////////// | 2366 //////////////////////////////////////////////////////////////////////////////// |
| 2333 | 2367 |
| 2334 void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { | 2368 void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { |
| 2335 expirer_.DeleteURLs(urls); | 2369 expirer_.DeleteURLs(urls); |
| 2336 | 2370 |
| 2337 db_->GetStartDate(&first_recorded_time_); | 2371 db_->GetStartDate(&first_recorded_time_); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2498 // The expirer keeps tabs on the active databases. Tell it about the | 2532 // The expirer keeps tabs on the active databases. Tell it about the |
| 2499 // databases which will be closed. | 2533 // databases which will be closed. |
| 2500 expirer_.SetDatabases(NULL, NULL); | 2534 expirer_.SetDatabases(NULL, NULL); |
| 2501 | 2535 |
| 2502 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). | 2536 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). |
| 2503 db_->BeginTransaction(); | 2537 db_->BeginTransaction(); |
| 2504 CloseAllDatabases(); | 2538 CloseAllDatabases(); |
| 2505 } | 2539 } |
| 2506 | 2540 |
| 2507 void HistoryBackend::ProcessDBTask( | 2541 void HistoryBackend::ProcessDBTask( |
| 2508 scoped_refptr<HistoryDBTaskRequest> request) { | 2542 scoped_refptr<HistoryDBTask> task, |
| 2509 DCHECK(request.get()); | 2543 scoped_refptr<base::SingleThreadTaskRunner> origin_loop, |
| 2510 if (request->canceled()) | 2544 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) { |
| 2511 return; | 2545 bool scheduled = !queued_history_db_tasks_.empty(); |
| 2512 | 2546 queued_history_db_tasks_.insert( |
| 2513 bool task_scheduled = !db_task_requests_.empty(); | 2547 queued_history_db_tasks_.end(), |
| 2514 // Make sure we up the refcount of the request. ProcessDBTaskImpl will | 2548 QueuedHistoryDBTask(task, origin_loop, is_canceled)); |
| 2515 // release when done with the task. | 2549 if (!scheduled) |
| 2516 request->AddRef(); | |
| 2517 db_task_requests_.push_back(request.get()); | |
| 2518 if (!task_scheduled) { | |
| 2519 // No other tasks are scheduled. Process request now. | |
| 2520 ProcessDBTaskImpl(); | 2550 ProcessDBTaskImpl(); |
| 2521 } | |
| 2522 } | 2551 } |
| 2523 | 2552 |
| 2524 void HistoryBackend::BroadcastNotifications( | 2553 void HistoryBackend::BroadcastNotifications( |
| 2525 int type, | 2554 int type, |
| 2526 scoped_ptr<HistoryDetails> details) { | 2555 scoped_ptr<HistoryDetails> details) { |
| 2527 // |delegate_| may be NULL if |this| is in the process of closing (closed by | 2556 // |delegate_| may be NULL if |this| is in the process of closing (closed by |
| 2528 // HistoryService -> HistoryBackend::Closing(). | 2557 // HistoryService -> HistoryBackend::Closing(). |
| 2529 if (delegate_) | 2558 if (delegate_) |
| 2530 delegate_->BroadcastNotifications(type, details.Pass()); | 2559 delegate_->BroadcastNotifications(type, details.Pass()); |
| 2531 } | 2560 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2714 int rank = kPageVisitStatsMaxTopSites; | 2743 int rank = kPageVisitStatsMaxTopSites; |
| 2715 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); | 2744 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); |
| 2716 if (it != most_visited_urls_map_.end()) | 2745 if (it != most_visited_urls_map_.end()) |
| 2717 rank = (*it).second; | 2746 rank = (*it).second; |
| 2718 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", | 2747 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", |
| 2719 rank, kPageVisitStatsMaxTopSites + 1); | 2748 rank, kPageVisitStatsMaxTopSites + 1); |
| 2720 } | 2749 } |
| 2721 #endif | 2750 #endif |
| 2722 | 2751 |
| 2723 } // namespace history | 2752 } // namespace history |
| OLD | NEW |