Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1306)

Side by Side Diff: components/history/core/browser/history_backend.cc

Issue 2672753002: Refactor History's CommitLaterTask with CancelableCallback (Closed)
Patch Set: Remove leftover friendship. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698