1// Copyright (c) 2011 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 "chrome/browser/ui/webui/chrome_url_data_manager.h" 6 7#include <vector> 8 9#include "base/i18n/rtl.h" 10#include "base/memory/ref_counted_memory.h" 11#include "base/message_loop.h" 12#include "base/string_util.h" 13#include "base/synchronization/lock.h" 14#include "base/values.h" 15#include "chrome/browser/net/chrome_url_request_context.h" 16#include "chrome/browser/profiles/profile.h" 17#include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" 18#include "content/browser/browser_thread.h" 19#include "grit/platform_locale_settings.h" 20#include "ui/base/l10n/l10n_util.h" 21 22#if defined(OS_WIN) 23#include "base/win/windows_version.h" 24#endif 25 26// static 27base::Lock ChromeURLDataManager::delete_lock_; 28 29// static 30ChromeURLDataManager::DataSources* ChromeURLDataManager::data_sources_ = NULL; 31 32// Invoked on the IO thread to do the actual adding of the DataSource. 33static void AddDataSourceOnIOThread( 34 scoped_refptr<net::URLRequestContextGetter> context_getter, 35 scoped_refptr<ChromeURLDataManager::DataSource> data_source) { 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 37 static_cast<ChromeURLRequestContext*>( 38 context_getter->GetURLRequestContext())-> 39 GetChromeURLDataManagerBackend()->AddDataSource(data_source.get()); 40} 41 42ChromeURLDataManager::ChromeURLDataManager(Profile* profile) 43 : profile_(profile) { 44} 45 46ChromeURLDataManager::~ChromeURLDataManager() { 47} 48 49void ChromeURLDataManager::AddDataSource(DataSource* source) { 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 51 BrowserThread::PostTask( 52 BrowserThread::IO, FROM_HERE, 53 NewRunnableFunction(AddDataSourceOnIOThread, 54 make_scoped_refptr(profile_->GetRequestContext()), 55 make_scoped_refptr(source))); 56} 57 58// static 59void ChromeURLDataManager::DeleteDataSources() { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 DataSources sources; 62 { 63 base::AutoLock lock(delete_lock_); 64 if (!data_sources_) 65 return; 66 data_sources_->swap(sources); 67 } 68 for (size_t i = 0; i < sources.size(); ++i) 69 delete sources[i]; 70} 71 72// static 73void ChromeURLDataManager::DeleteDataSource(const DataSource* data_source) { 74 // Invoked when a DataSource is no longer referenced and needs to be deleted. 75 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 76 // We're on the UI thread, delete right away. 77 delete data_source; 78 return; 79 } 80 81 // We're not on the UI thread, add the DataSource to the list of DataSources 82 // to delete. 83 bool schedule_delete = false; 84 { 85 base::AutoLock lock(delete_lock_); 86 if (!data_sources_) 87 data_sources_ = new DataSources(); 88 schedule_delete = data_sources_->empty(); 89 data_sources_->push_back(data_source); 90 } 91 if (schedule_delete) { 92 // Schedule a task to delete the DataSource back on the UI thread. 93 BrowserThread::PostTask(BrowserThread::UI, 94 FROM_HERE, 95 NewRunnableFunction( 96 &ChromeURLDataManager::DeleteDataSources)); 97 } 98} 99 100// static 101bool ChromeURLDataManager::IsScheduledForDeletion( 102 const DataSource* data_source) { 103 base::AutoLock lock(delete_lock_); 104 if (!data_sources_) 105 return false; 106 return std::find(data_sources_->begin(), data_sources_->end(), data_source) != 107 data_sources_->end(); 108} 109 110ChromeURLDataManager::DataSource::DataSource(const std::string& source_name, 111 MessageLoop* message_loop) 112 : source_name_(source_name), 113 message_loop_(message_loop), 114 backend_(NULL) { 115} 116 117ChromeURLDataManager::DataSource::~DataSource() { 118} 119 120void ChromeURLDataManager::DataSource::SendResponse(int request_id, 121 RefCountedMemory* bytes) { 122 if (IsScheduledForDeletion(this)) { 123 // We're scheduled for deletion. Servicing the request would result in 124 // this->AddRef being invoked, even though the ref count is 0 and 'this' is 125 // about to be deleted. If the AddRef were allowed through, when 'this' is 126 // released it would be deleted again. 127 // 128 // This scenario occurs with DataSources that make history requests. Such 129 // DataSources do a history query in |StartDataRequest| and the request is 130 // live until the object is deleted (history requests don't up the ref 131 // count). This means it's entirely possible for the DataSource to invoke 132 // |SendResponse| between the time when there are no more refs and the time 133 // when the object is deleted. 134 return; 135 } 136 BrowserThread::PostTask( 137 BrowserThread::IO, FROM_HERE, 138 NewRunnableMethod(this, &DataSource::SendResponseOnIOThread, 139 request_id, make_scoped_refptr(bytes))); 140} 141 142MessageLoop* ChromeURLDataManager::DataSource::MessageLoopForRequestPath( 143 const std::string& path) const { 144 return message_loop_; 145} 146 147bool ChromeURLDataManager::DataSource::ShouldReplaceExistingSource() const { 148 return true; 149} 150 151// static 152void ChromeURLDataManager::DataSource::SetFontAndTextDirection( 153 DictionaryValue* localized_strings) { 154 localized_strings->SetString("fontfamily", 155 l10n_util::GetStringUTF16(IDS_WEB_FONT_FAMILY)); 156 157 int web_font_size_id = IDS_WEB_FONT_SIZE; 158#if defined(OS_WIN) 159 // Some fonts used for some languages changed a lot in terms of the font 160 // metric in Vista. So, we need to use different size before Vista. 161 if (base::win::GetVersion() < base::win::VERSION_VISTA) 162 web_font_size_id = IDS_WEB_FONT_SIZE_XP; 163#endif 164 localized_strings->SetString("fontsize", 165 l10n_util::GetStringUTF16(web_font_size_id)); 166 167 localized_strings->SetString("textdirection", 168 base::i18n::IsRTL() ? "rtl" : "ltr"); 169} 170 171void ChromeURLDataManager::DataSource::SendResponseOnIOThread( 172 int request_id, 173 scoped_refptr<RefCountedMemory> bytes) { 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 175 if (backend_) 176 backend_->DataAvailable(request_id, bytes); 177} 178