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 3 // found in the LICENSE file. 4 5 #include "content/browser/webui/url_data_manager.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/lazy_instance.h" 11 #include "base/memory/ref_counted_memory.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/strings/string_util.h" 14 #include "base/synchronization/lock.h" 15 #include "content/browser/resource_context_impl.h" 16 #include "content/browser/webui/url_data_manager_backend.h" 17 #include "content/browser/webui/url_data_source_impl.h" 18 #include "content/browser/webui/web_ui_data_source_impl.h" 19 #include "content/public/browser/browser_context.h" 20 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/url_data_source.h" 22 23 namespace content { 24 namespace { 25 26 const char kURLDataManagerKeyName[] = "url_data_manager"; 27 28 base::LazyInstance<base::Lock>::Leaky g_delete_lock = LAZY_INSTANCE_INITIALIZER; 29 30 URLDataManager* GetFromBrowserContext(BrowserContext* context) { 31 if (!context->GetUserData(kURLDataManagerKeyName)) { 32 context->SetUserData(kURLDataManagerKeyName, new URLDataManager(context)); 33 } 34 return static_cast<URLDataManager*>( 35 context->GetUserData(kURLDataManagerKeyName)); 36 } 37 38 // Invoked on the IO thread to do the actual adding of the DataSource. 39 static void AddDataSourceOnIOThread( 40 ResourceContext* resource_context, 41 scoped_refptr<URLDataSourceImpl> data_source) { 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 43 GetURLDataManagerForResourceContext(resource_context)->AddDataSource( 44 data_source.get()); 45 } 46 47 } // namespace 48 49 // static 50 URLDataManager::URLDataSources* URLDataManager::data_sources_ = NULL; 51 52 URLDataManager::URLDataManager(BrowserContext* browser_context) 53 : browser_context_(browser_context) { 54 } 55 56 URLDataManager::~URLDataManager() { 57 } 58 59 void URLDataManager::AddDataSource(URLDataSourceImpl* source) { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 BrowserThread::PostTask( 62 BrowserThread::IO, FROM_HERE, 63 base::Bind(&AddDataSourceOnIOThread, 64 browser_context_->GetResourceContext(), 65 make_scoped_refptr(source))); 66 } 67 68 // static 69 void URLDataManager::DeleteDataSources() { 70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 71 URLDataSources sources; 72 { 73 base::AutoLock lock(g_delete_lock.Get()); 74 if (!data_sources_) 75 return; 76 data_sources_->swap(sources); 77 } 78 for (size_t i = 0; i < sources.size(); ++i) 79 delete sources[i]; 80 } 81 82 // static 83 void URLDataManager::DeleteDataSource(const URLDataSourceImpl* data_source) { 84 // Invoked when a DataSource is no longer referenced and needs to be deleted. 85 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 86 // We're on the UI thread, delete right away. 87 delete data_source; 88 return; 89 } 90 91 // We're not on the UI thread, add the DataSource to the list of DataSources 92 // to delete. 93 bool schedule_delete = false; 94 { 95 base::AutoLock lock(g_delete_lock.Get()); 96 if (!data_sources_) 97 data_sources_ = new URLDataSources(); 98 schedule_delete = data_sources_->empty(); 99 data_sources_->push_back(data_source); 100 } 101 if (schedule_delete) { 102 // Schedule a task to delete the DataSource back on the UI thread. 103 BrowserThread::PostTask( 104 BrowserThread::UI, FROM_HERE, 105 base::Bind(&URLDataManager::DeleteDataSources)); 106 } 107 } 108 109 // static 110 void URLDataManager::AddDataSource(BrowserContext* browser_context, 111 URLDataSource* source) { 112 GetFromBrowserContext(browser_context)-> 113 AddDataSource(new URLDataSourceImpl(source->GetSource(), source)); 114 } 115 116 // static 117 void URLDataManager::AddWebUIDataSource(BrowserContext* browser_context, 118 WebUIDataSource* source) { 119 WebUIDataSourceImpl* impl = static_cast<WebUIDataSourceImpl*>(source); 120 GetFromBrowserContext(browser_context)->AddDataSource(impl); 121 } 122 123 // static 124 bool URLDataManager::IsScheduledForDeletion( 125 const URLDataSourceImpl* data_source) { 126 base::AutoLock lock(g_delete_lock.Get()); 127 if (!data_sources_) 128 return false; 129 return std::find(data_sources_->begin(), data_sources_->end(), data_source) != 130 data_sources_->end(); 131 } 132 133 } // namespace content 134