Chromium Code Reviews| 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/history/core/browser/history_backend.h" | 5 #include "components/history/core/browser/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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 } else { | 107 } else { |
| 108 mv.redirects = redirects; | 108 mv.redirects = redirects; |
| 109 if (mv.redirects.back() != mv.url) { | 109 if (mv.redirects.back() != mv.url) { |
| 110 // The last url must be the target url. | 110 // The last url must be the target url. |
| 111 mv.redirects.push_back(mv.url); | 111 mv.redirects.push_back(mv.url); |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 return mv; | 114 return mv; |
| 115 } | 115 } |
| 116 | 116 |
| 117 // This task is run on a timer so that commits happen at regular intervals | |
| 118 // so they are batched together. The important thing about this class is that | |
| 119 // it supports canceling of the task so the reference to the backend will be | |
| 120 // freed. The problem is that when history is shutting down, there is likely | |
| 121 // to be one of these commits still pending and holding a reference. | |
| 122 // | |
| 123 // The backend can call Cancel to have this task release the reference. The | |
| 124 // task will still run (if we ever get to processing the event before | |
| 125 // shutdown), but it will not do anything. | |
| 126 // | |
| 127 // Note that this is a refcounted object and is not a task in itself. It should | |
| 128 // be assigned to a RunnableMethod. | |
| 129 // | |
| 130 // TODO(brettw): bug 1165182: This should be replaced with a | |
|
Marc Treib
2017/02/02 10:52:21
Wow, this might be the oldest Chrome bug I've seen
| |
| 131 // base::WeakPtrFactory which will handle everything automatically (like we do | |
| 132 // in ExpireHistoryBackend). | |
| 133 class CommitLaterTask : public base::RefCounted<CommitLaterTask> { | |
| 134 public: | |
| 135 explicit CommitLaterTask(HistoryBackend* history_backend) | |
| 136 : history_backend_(history_backend) {} | |
| 137 | |
| 138 // The backend will call this function if it is being destroyed so that we | |
| 139 // release our reference. | |
| 140 void Cancel() { history_backend_ = nullptr; } | |
| 141 | |
| 142 void RunCommit() { | |
| 143 if (history_backend_) | |
| 144 history_backend_->Commit(); | |
| 145 } | |
| 146 | |
| 147 private: | |
| 148 friend class base::RefCounted<CommitLaterTask>; | |
| 149 | |
| 150 ~CommitLaterTask() {} | |
| 151 | |
| 152 scoped_refptr<HistoryBackend> history_backend_; | |
| 153 }; | |
| 154 | |
| 155 QueuedHistoryDBTask::QueuedHistoryDBTask( | 117 QueuedHistoryDBTask::QueuedHistoryDBTask( |
| 156 std::unique_ptr<HistoryDBTask> task, | 118 std::unique_ptr<HistoryDBTask> task, |
| 157 scoped_refptr<base::SingleThreadTaskRunner> origin_loop, | 119 scoped_refptr<base::SingleThreadTaskRunner> origin_loop, |
| 158 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) | 120 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) |
| 159 : task_(std::move(task)), | 121 : task_(std::move(task)), |
| 160 origin_loop_(origin_loop), | 122 origin_loop_(origin_loop), |
| 161 is_canceled_(is_canceled) { | 123 is_canceled_(is_canceled) { |
| 162 DCHECK(task_); | 124 DCHECK(task_); |
| 163 DCHECK(origin_loop_); | 125 DCHECK(origin_loop_); |
| 164 DCHECK(!is_canceled_.is_null()); | 126 DCHECK(!is_canceled_.is_null()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 HistoryBackend::HistoryBackend( | 169 HistoryBackend::HistoryBackend( |
| 208 Delegate* delegate, | 170 Delegate* delegate, |
| 209 std::unique_ptr<HistoryBackendClient> backend_client, | 171 std::unique_ptr<HistoryBackendClient> backend_client, |
| 210 scoped_refptr<base::SequencedTaskRunner> task_runner) | 172 scoped_refptr<base::SequencedTaskRunner> task_runner) |
| 211 : delegate_(delegate), | 173 : delegate_(delegate), |
| 212 scheduled_kill_db_(false), | 174 scheduled_kill_db_(false), |
| 213 expirer_(this, backend_client.get(), task_runner), | 175 expirer_(this, backend_client.get(), task_runner), |
| 214 recent_redirects_(kMaxRedirectCount), | 176 recent_redirects_(kMaxRedirectCount), |
| 215 segment_queried_(false), | 177 segment_queried_(false), |
| 216 backend_client_(std::move(backend_client)), | 178 backend_client_(std::move(backend_client)), |
| 217 task_runner_(task_runner) {} | 179 task_runner_(task_runner), |
| 180 weak_ptr_factory_(this) {} | |
| 218 | 181 |
| 219 HistoryBackend::~HistoryBackend() { | 182 HistoryBackend::~HistoryBackend() { |
| 220 DCHECK(!scheduled_commit_) << "Deleting without cleanup"; | 183 DCHECK(!scheduled_commit_tracker_.HasTrackedTasks()) |
| 184 << "Deleting without cleanup"; | |
| 221 queued_history_db_tasks_.clear(); | 185 queued_history_db_tasks_.clear(); |
| 222 | 186 |
| 223 // Release stashed embedder object before cleaning up the databases. | 187 // Release stashed embedder object before cleaning up the databases. |
| 224 supports_user_data_helper_.reset(); | 188 supports_user_data_helper_.reset(); |
| 225 | 189 |
| 226 // First close the databases before optionally running the "destroy" task. | 190 // First close the databases before optionally running the "destroy" task. |
| 227 CloseAllDatabases(); | 191 CloseAllDatabases(); |
| 228 | 192 |
| 229 if (!backend_destroy_task_.is_null()) { | 193 if (!backend_destroy_task_.is_null()) { |
| 230 // Notify an interested party (typically a unit test) that we're done. | 194 // Notify an interested party (typically a unit test) that we're done. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 257 void HistoryBackend::SetOnBackendDestroyTask( | 221 void HistoryBackend::SetOnBackendDestroyTask( |
| 258 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 222 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 259 const base::Closure& task) { | 223 const base::Closure& task) { |
| 260 if (!backend_destroy_task_.is_null()) | 224 if (!backend_destroy_task_.is_null()) |
| 261 DLOG(WARNING) << "Setting more than one destroy task, overriding"; | 225 DLOG(WARNING) << "Setting more than one destroy task, overriding"; |
| 262 backend_destroy_task_runner_ = std::move(task_runner); | 226 backend_destroy_task_runner_ = std::move(task_runner); |
| 263 backend_destroy_task_ = task; | 227 backend_destroy_task_ = task; |
| 264 } | 228 } |
| 265 | 229 |
| 266 void HistoryBackend::Closing() { | 230 void HistoryBackend::Closing() { |
| 267 // Any scheduled commit will have a reference to us, we must make it | 231 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 268 // release that reference before we can be destroyed. | |
| 269 CancelScheduledCommit(); | 232 CancelScheduledCommit(); |
| 270 | 233 |
| 271 // Release our reference to the delegate, this reference will be keeping the | 234 // Release our reference to the delegate, this reference will be keeping the |
| 272 // history service alive. | 235 // history service alive. |
| 273 delegate_.reset(); | 236 delegate_.reset(); |
| 274 } | 237 } |
| 275 | 238 |
| 276 #if defined(OS_IOS) | 239 #if defined(OS_IOS) |
| 277 void HistoryBackend::PersistState() { | 240 void HistoryBackend::PersistState() { |
| 278 Commit(); | 241 Commit(); |
| (...skipping 1956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2235 | 2198 |
| 2236 if (thumbnail_db_) { | 2199 if (thumbnail_db_) { |
| 2237 thumbnail_db_->CommitTransaction(); | 2200 thumbnail_db_->CommitTransaction(); |
| 2238 DCHECK_EQ(thumbnail_db_->transaction_nesting(), 0) | 2201 DCHECK_EQ(thumbnail_db_->transaction_nesting(), 0) |
| 2239 << "Somebody left a transaction open"; | 2202 << "Somebody left a transaction open"; |
| 2240 thumbnail_db_->BeginTransaction(); | 2203 thumbnail_db_->BeginTransaction(); |
| 2241 } | 2204 } |
| 2242 } | 2205 } |
| 2243 | 2206 |
| 2244 void HistoryBackend::ScheduleCommit() { | 2207 void HistoryBackend::ScheduleCommit() { |
| 2245 if (scheduled_commit_) | 2208 if (scheduled_commit_tracker_.HasTrackedTasks()) |
| 2246 return; | 2209 return; |
| 2247 scheduled_commit_ = new CommitLaterTask(this); | 2210 scheduled_commit_tracker_.PostDelayedTask( |
| 2248 task_runner_->PostDelayedTask( | 2211 task_runner_.get(), FROM_HERE, |
| 2249 FROM_HERE, | 2212 base::Bind(&HistoryBackend::Commit, weak_ptr_factory_.GetWeakPtr()), |
| 2250 base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_), | |
| 2251 base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); | 2213 base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); |
| 2252 } | 2214 } |
| 2253 | 2215 |
| 2254 void HistoryBackend::CancelScheduledCommit() { | 2216 void HistoryBackend::CancelScheduledCommit() { |
| 2255 if (scheduled_commit_) { | 2217 scheduled_commit_tracker_.TryCancelAll(); |
| 2256 scheduled_commit_->Cancel(); | |
| 2257 scheduled_commit_ = nullptr; | |
| 2258 } | |
| 2259 } | 2218 } |
| 2260 | 2219 |
| 2261 void HistoryBackend::ProcessDBTaskImpl() { | 2220 void HistoryBackend::ProcessDBTaskImpl() { |
| 2262 if (!db_) { | 2221 if (!db_) { |
| 2263 // db went away, release all the refs. | 2222 // db went away, release all the refs. |
| 2264 queued_history_db_tasks_.clear(); | 2223 queued_history_db_tasks_.clear(); |
| 2265 return; | 2224 return; |
| 2266 } | 2225 } |
| 2267 | 2226 |
| 2268 // Remove any canceled tasks. | 2227 // Remove any canceled tasks. |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2646 // transaction is currently open. | 2605 // transaction is currently open. |
| 2647 db_->CommitTransaction(); | 2606 db_->CommitTransaction(); |
| 2648 db_->Vacuum(); | 2607 db_->Vacuum(); |
| 2649 db_->BeginTransaction(); | 2608 db_->BeginTransaction(); |
| 2650 db_->GetStartDate(&first_recorded_time_); | 2609 db_->GetStartDate(&first_recorded_time_); |
| 2651 | 2610 |
| 2652 return true; | 2611 return true; |
| 2653 } | 2612 } |
| 2654 | 2613 |
| 2655 } // namespace history | 2614 } // namespace history |
| OLD | NEW |