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

Side by Side Diff: chrome/browser/history/history_service.cc

Issue 510033004: Minor history tweaks that I came across while looking at crashes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 // The history system runs on a background thread so that potentially slow 5 // The history system runs on a background thread so that potentially slow
6 // database operations don't delay the browser. This backend processing is 6 // database operations don't delay the browser. This backend processing is
7 // represented by HistoryBackend. The HistoryService's job is to dispatch to 7 // represented by HistoryBackend. The HistoryService's job is to dispatch to
8 // that thread. 8 // that thread.
9 // 9 //
10 // Main thread History thread 10 // Main thread History thread
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 DCHECK(thread_checker_.CalledOnValidThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
225 // Shutdown the backend. This does nothing if Cleanup was already invoked. 225 // Shutdown the backend. This does nothing if Cleanup was already invoked.
226 Cleanup(); 226 Cleanup();
227 } 227 }
228 228
229 bool HistoryService::BackendLoaded() { 229 bool HistoryService::BackendLoaded() {
230 DCHECK(thread_checker_.CalledOnValidThread()); 230 DCHECK(thread_checker_.CalledOnValidThread());
231 return backend_loaded_; 231 return backend_loaded_;
232 } 232 }
233 233
234 void HistoryService::Cleanup() {
235 DCHECK(thread_checker_.CalledOnValidThread());
236 if (!thread_) {
237 // We've already cleaned up.
238 return;
239 }
240
241 weak_ptr_factory_.InvalidateWeakPtrs();
242
243 // Unload the backend.
244 if (history_backend_.get()) {
245 // Get rid of the in-memory backend.
246 in_memory_backend_.reset();
247
248 // Give the InMemoryURLIndex a chance to shutdown.
249 // NOTE: In tests, there may be no index.
250 if (in_memory_url_index_)
251 in_memory_url_index_->ShutDown();
252
253 // The backend's destructor must run on the history thread since it is not
254 // threadsafe. So this thread must not be the last thread holding a
255 // reference to the backend, or a crash could happen.
256 //
257 // We have a reference to the history backend. There is also an extra
258 // reference held by our delegate installed in the backend, which
259 // HistoryBackend::Closing will release. This means if we scheduled a call
260 // to HistoryBackend::Closing and *then* released our backend reference,
261 // there will be a race between us and the backend's Closing function to see
262 // who is the last holder of a reference. If the backend thread's Closing
263 // manages to run before we release our backend refptr, the last reference
264 // will be held by this thread and the destructor will be called from here.
265 //
266 // Therefore, we create a closure to run the Closing operation first. This
267 // holds a reference to the backend. Then we release our reference, then we
268 // schedule the task to run. After the task runs, it will delete its
269 // reference from the history thread, ensuring everything works properly.
270 //
271 // TODO(ajwong): Cleanup HistoryBackend lifetime issues.
272 // See http://crbug.com/99767.
273 history_backend_->AddRef();
274 base::Closure closing_task =
275 base::Bind(&HistoryBackend::Closing, history_backend_.get());
276 ScheduleTask(PRIORITY_NORMAL, closing_task);
277 closing_task.Reset();
278 HistoryBackend* raw_ptr = history_backend_.get();
279 history_backend_ = NULL;
280 thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
281 }
282
283 // Delete the thread, which joins with the background thread. We defensively
284 // NULL the pointer before deleting it in case somebody tries to use it
285 // during shutdown, but this shouldn't happen.
286 base::Thread* thread = thread_;
287 thread_ = NULL;
288 delete thread;
289 }
290
291 void HistoryService::ClearCachedDataForContextID( 234 void HistoryService::ClearCachedDataForContextID(
292 history::ContextID context_id) { 235 history::ContextID context_id) {
293 DCHECK(thread_) << "History service being called after cleanup"; 236 DCHECK(thread_) << "History service being called after cleanup";
294 DCHECK(thread_checker_.CalledOnValidThread()); 237 DCHECK(thread_checker_.CalledOnValidThread());
295 ScheduleAndForget(PRIORITY_NORMAL, 238 ScheduleAndForget(PRIORITY_NORMAL,
296 &HistoryBackend::ClearCachedDataForContextID, context_id); 239 &HistoryBackend::ClearCachedDataForContextID, context_id);
297 } 240 }
298 241
299 history::URLDatabase* HistoryService::InMemoryDatabase() { 242 history::URLDatabase* HistoryService::InMemoryDatabase() {
300 DCHECK(thread_checker_.CalledOnValidThread()); 243 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 FROM_HERE, 839 FROM_HERE,
897 base::Bind(&HistoryBackend::QueryFilteredURLs, 840 base::Bind(&HistoryBackend::QueryFilteredURLs,
898 history_backend_.get(), 841 history_backend_.get(),
899 result_count, 842 result_count,
900 filter, 843 filter,
901 extended_info, 844 extended_info,
902 base::Unretained(result)), 845 base::Unretained(result)),
903 base::Bind(callback, base::Owned(result))); 846 base::Bind(callback, base::Owned(result)));
904 } 847 }
905 848
849 void HistoryService::Cleanup() {
850 DCHECK(thread_checker_.CalledOnValidThread());
851 if (!thread_) {
852 // We've already cleaned up.
853 return;
854 }
855
856 weak_ptr_factory_.InvalidateWeakPtrs();
857
858 // Unload the backend.
859 if (history_backend_.get()) {
860 // Get rid of the in-memory backend.
861 in_memory_backend_.reset();
862
863 // Give the InMemoryURLIndex a chance to shutdown.
864 // NOTE: In tests, there may be no index.
865 if (in_memory_url_index_)
866 in_memory_url_index_->ShutDown();
867
868 // The backend's destructor must run on the history thread since it is not
869 // threadsafe. So this thread must not be the last thread holding a
870 // reference to the backend, or a crash could happen.
871 //
872 // We have a reference to the history backend. There is also an extra
873 // reference held by our delegate installed in the backend, which
874 // HistoryBackend::Closing will release. This means if we scheduled a call
875 // to HistoryBackend::Closing and *then* released our backend reference,
876 // there will be a race between us and the backend's Closing function to see
877 // who is the last holder of a reference. If the backend thread's Closing
878 // manages to run before we release our backend refptr, the last reference
879 // will be held by this thread and the destructor will be called from here.
880 //
881 // Therefore, we create a closure to run the Closing operation first. This
882 // holds a reference to the backend. Then we release our reference, then we
883 // schedule the task to run. After the task runs, it will delete its
884 // reference from the history thread, ensuring everything works properly.
885 //
886 // TODO(ajwong): Cleanup HistoryBackend lifetime issues.
887 // See http://crbug.com/99767.
888 history_backend_->AddRef();
889 base::Closure closing_task =
890 base::Bind(&HistoryBackend::Closing, history_backend_.get());
891 ScheduleTask(PRIORITY_NORMAL, closing_task);
892 closing_task.Reset();
893 HistoryBackend* raw_ptr = history_backend_.get();
894 history_backend_ = NULL;
895 thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
896 }
897
898 // Delete the thread, which joins with the background thread. We defensively
899 // NULL the pointer before deleting it in case somebody tries to use it
900 // during shutdown, but this shouldn't happen.
901 base::Thread* thread = thread_;
902 thread_ = NULL;
903 delete thread;
904 }
905
906 void HistoryService::Observe(int type, 906 void HistoryService::Observe(int type,
907 const content::NotificationSource& source, 907 const content::NotificationSource& source,
908 const content::NotificationDetails& details) { 908 const content::NotificationDetails& details) {
909 DCHECK(thread_checker_.CalledOnValidThread()); 909 DCHECK(thread_checker_.CalledOnValidThread());
910 if (!thread_) 910 if (!thread_)
911 return; 911 return;
912 912
913 switch (type) { 913 switch (type) {
914 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: { 914 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: {
915 // Update the visited link system for deleted URLs. We will update the 915 // Update the visited link system for deleted URLs. We will update the
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 DCHECK(thread_checker_.CalledOnValidThread()); 1222 DCHECK(thread_checker_.CalledOnValidThread());
1223 visit_database_observers_.RemoveObserver(observer); 1223 visit_database_observers_.RemoveObserver(observer);
1224 } 1224 }
1225 1225
1226 void HistoryService::NotifyVisitDBObserversOnAddVisit( 1226 void HistoryService::NotifyVisitDBObserversOnAddVisit(
1227 const history::BriefVisitInfo& info) { 1227 const history::BriefVisitInfo& info) {
1228 DCHECK(thread_checker_.CalledOnValidThread()); 1228 DCHECK(thread_checker_.CalledOnValidThread());
1229 FOR_EACH_OBSERVER(history::VisitDatabaseObserver, visit_database_observers_, 1229 FOR_EACH_OBSERVER(history::VisitDatabaseObserver, visit_database_observers_,
1230 OnAddVisit(info)); 1230 OnAddVisit(info));
1231 } 1231 }
OLDNEW
« no previous file with comments | « chrome/browser/history/history_service.h ('k') | chrome/browser/history/history_service_factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698