| 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 // 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |