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 23namespace content { 24namespace { 25 26const char kURLDataManagerKeyName[] = "url_data_manager"; 27 28base::LazyInstance<base::Lock>::Leaky g_delete_lock = LAZY_INSTANCE_INITIALIZER; 29 30URLDataManager* 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. 39static 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 50URLDataManager::URLDataSources* URLDataManager::data_sources_ = NULL; 51 52URLDataManager::URLDataManager(BrowserContext* browser_context) 53 : browser_context_(browser_context) { 54} 55 56URLDataManager::~URLDataManager() { 57} 58 59void 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 69void 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 83void 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 110void URLDataManager::AddDataSource(BrowserContext* browser_context, 111 URLDataSource* source) { 112 GetFromBrowserContext(browser_context)-> 113 AddDataSource(new URLDataSourceImpl(source->GetSource(), source)); 114} 115 116// static 117void 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 124bool 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