• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
27 base::Lock ChromeURLDataManager::delete_lock_;
28 
29 // static
30 ChromeURLDataManager::DataSources* ChromeURLDataManager::data_sources_ = NULL;
31 
32 // Invoked on the IO thread to do the actual adding of the DataSource.
AddDataSourceOnIOThread(scoped_refptr<net::URLRequestContextGetter> context_getter,scoped_refptr<ChromeURLDataManager::DataSource> data_source)33 static 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 
ChromeURLDataManager(Profile * profile)42 ChromeURLDataManager::ChromeURLDataManager(Profile* profile)
43     : profile_(profile) {
44 }
45 
~ChromeURLDataManager()46 ChromeURLDataManager::~ChromeURLDataManager() {
47 }
48 
AddDataSource(DataSource * source)49 void 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
DeleteDataSources()59 void 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
DeleteDataSource(const DataSource * data_source)73 void 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
IsScheduledForDeletion(const DataSource * data_source)101 bool 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 
DataSource(const std::string & source_name,MessageLoop * message_loop)110 ChromeURLDataManager::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 
~DataSource()117 ChromeURLDataManager::DataSource::~DataSource() {
118 }
119 
SendResponse(int request_id,RefCountedMemory * bytes)120 void 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 
MessageLoopForRequestPath(const std::string & path) const142 MessageLoop* ChromeURLDataManager::DataSource::MessageLoopForRequestPath(
143     const std::string& path) const {
144   return message_loop_;
145 }
146 
ShouldReplaceExistingSource() const147 bool ChromeURLDataManager::DataSource::ShouldReplaceExistingSource() const {
148   return true;
149 }
150 
151 // static
SetFontAndTextDirection(DictionaryValue * localized_strings)152 void 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 
SendResponseOnIOThread(int request_id,scoped_refptr<RefCountedMemory> bytes)171 void 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