Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / extensions / api / font_settings / font_settings_api.cc
blob4f0d7c913831bc81f7a8bae53b1fa14e9f3c217c
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.
5 // Font Settings Extension API implementation.
7 #include "chrome/browser/extensions/api/font_settings/font_settings_api.h"
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/json/json_writer.h"
12 #include "base/lazy_instance.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/trace_event/trace_event.h"
18 #include "base/values.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/extensions/api/preference/preference_api.h"
21 #include "chrome/browser/extensions/api/preference/preference_helpers.h"
22 #include "chrome/browser/extensions/extension_service.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/extensions/api/font_settings.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/pref_names_util.h"
27 #include "content/public/browser/font_list_async.h"
28 #include "content/public/browser/notification_details.h"
29 #include "content/public/browser/notification_source.h"
30 #include "extensions/browser/extension_system.h"
31 #include "extensions/common/error_utils.h"
33 #if defined(OS_WIN)
34 #include "ui/gfx/font.h"
35 #include "ui/gfx/platform_font_win.h"
36 #endif
38 namespace extensions {
40 namespace fonts = api::font_settings;
42 namespace {
44 const char kFontIdKey[] = "fontId";
45 const char kGenericFamilyKey[] = "genericFamily";
46 const char kLevelOfControlKey[] = "levelOfControl";
47 const char kDisplayNameKey[] = "displayName";
48 const char kPixelSizeKey[] = "pixelSize";
49 const char kScriptKey[] = "script";
51 const char kSetFromIncognitoError[] =
52 "Can't modify regular settings from an incognito context.";
54 // Format for font name preference paths.
55 const char kWebKitFontPrefFormat[] = "webkit.webprefs.fonts.%s.%s";
57 // Gets the font name preference path for |generic_family| and |script|. If
58 // |script| is NULL, uses prefs::kWebKitCommonScript.
59 std::string GetFontNamePrefPath(fonts::GenericFamily generic_family_enum,
60 fonts::ScriptCode script_enum) {
61 std::string script = fonts::ToString(script_enum);
62 if (script.empty())
63 script = prefs::kWebKitCommonScript;
64 std::string generic_family = fonts::ToString(generic_family_enum);
65 return base::StringPrintf(kWebKitFontPrefFormat,
66 generic_family.c_str(),
67 script.c_str());
70 // Returns the localized name of a font so that it can be matched within the
71 // list of system fonts. On Windows, the list of system fonts has names only
72 // for the system locale, but the pref value may be in the English name.
73 std::string MaybeGetLocalizedFontName(const std::string& font_name) {
74 #if defined(OS_WIN)
75 if (!font_name.empty()) {
76 gfx::Font font(font_name, 12); // dummy font size
77 return static_cast<gfx::PlatformFontWin*>(font.platform_font())->
78 GetLocalizedFontName();
80 #endif
81 return font_name;
84 // Registers |obs| to observe per-script font prefs under the path |map_name|.
85 void RegisterFontFamilyMapObserver(
86 PrefChangeRegistrar* registrar,
87 const char* map_name,
88 const PrefChangeRegistrar::NamedChangeCallback& callback) {
89 for (size_t i = 0; i < prefs::kWebKitScriptsForFontFamilyMapsLength; ++i) {
90 const char* script = prefs::kWebKitScriptsForFontFamilyMaps[i];
91 registrar->Add(base::StringPrintf("%s.%s", map_name, script), callback);
95 } // namespace
97 FontSettingsEventRouter::FontSettingsEventRouter(
98 Profile* profile) : profile_(profile) {
99 TRACE_EVENT0("browser,startup", "FontSettingsEventRouter::ctor")
100 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.FontSettingsEventRouterCtorTime");
102 registrar_.Init(profile_->GetPrefs());
104 AddPrefToObserve(prefs::kWebKitDefaultFixedFontSize,
105 events::FONT_SETTINGS_ON_DEFAULT_FIXED_FONT_SIZE_CHANGED,
106 fonts::OnDefaultFixedFontSizeChanged::kEventName,
107 kPixelSizeKey);
108 AddPrefToObserve(prefs::kWebKitDefaultFontSize,
109 events::FONT_SETTINGS_ON_DEFAULT_FONT_SIZE_CHANGED,
110 fonts::OnDefaultFontSizeChanged::kEventName, kPixelSizeKey);
111 AddPrefToObserve(prefs::kWebKitMinimumFontSize,
112 events::FONT_SETTINGS_ON_MINIMUM_FONT_SIZE_CHANGED,
113 fonts::OnMinimumFontSizeChanged::kEventName, kPixelSizeKey);
115 PrefChangeRegistrar::NamedChangeCallback callback =
116 base::Bind(&FontSettingsEventRouter::OnFontFamilyMapPrefChanged,
117 base::Unretained(this));
118 RegisterFontFamilyMapObserver(&registrar_,
119 prefs::kWebKitStandardFontFamilyMap, callback);
120 RegisterFontFamilyMapObserver(&registrar_,
121 prefs::kWebKitSerifFontFamilyMap, callback);
122 RegisterFontFamilyMapObserver(&registrar_,
123 prefs::kWebKitSansSerifFontFamilyMap, callback);
124 RegisterFontFamilyMapObserver(&registrar_,
125 prefs::kWebKitFixedFontFamilyMap, callback);
126 RegisterFontFamilyMapObserver(&registrar_,
127 prefs::kWebKitCursiveFontFamilyMap, callback);
128 RegisterFontFamilyMapObserver(&registrar_,
129 prefs::kWebKitFantasyFontFamilyMap, callback);
130 RegisterFontFamilyMapObserver(&registrar_,
131 prefs::kWebKitPictographFontFamilyMap,
132 callback);
135 FontSettingsEventRouter::~FontSettingsEventRouter() {}
137 void FontSettingsEventRouter::AddPrefToObserve(
138 const char* pref_name,
139 events::HistogramValue histogram_value,
140 const char* event_name,
141 const char* key) {
142 registrar_.Add(
143 pref_name,
144 base::Bind(&FontSettingsEventRouter::OnFontPrefChanged,
145 base::Unretained(this), histogram_value, event_name, key));
148 void FontSettingsEventRouter::OnFontFamilyMapPrefChanged(
149 const std::string& pref_name) {
150 std::string generic_family;
151 std::string script;
152 if (pref_names_util::ParseFontNamePrefPath(pref_name, &generic_family,
153 &script)) {
154 OnFontNamePrefChanged(pref_name, generic_family, script);
155 return;
158 NOTREACHED();
161 void FontSettingsEventRouter::OnFontNamePrefChanged(
162 const std::string& pref_name,
163 const std::string& generic_family,
164 const std::string& script) {
165 const PrefService::Preference* pref = registrar_.prefs()->FindPreference(
166 pref_name);
167 CHECK(pref);
169 std::string font_name;
170 if (!pref->GetValue()->GetAsString(&font_name)) {
171 NOTREACHED();
172 return;
174 font_name = MaybeGetLocalizedFontName(font_name);
176 base::ListValue args;
177 base::DictionaryValue* dict = new base::DictionaryValue();
178 args.Append(dict);
179 dict->SetString(kFontIdKey, font_name);
180 dict->SetString(kGenericFamilyKey, generic_family);
181 dict->SetString(kScriptKey, script);
183 extensions::preference_helpers::DispatchEventToExtensions(
184 profile_, events::FONT_SETTINGS_ON_FONT_CHANGED,
185 fonts::OnFontChanged::kEventName, &args, APIPermission::kFontSettings,
186 false, pref_name);
189 void FontSettingsEventRouter::OnFontPrefChanged(
190 events::HistogramValue histogram_value,
191 const std::string& event_name,
192 const std::string& key,
193 const std::string& pref_name) {
194 const PrefService::Preference* pref = registrar_.prefs()->FindPreference(
195 pref_name);
196 CHECK(pref);
198 base::ListValue args;
199 base::DictionaryValue* dict = new base::DictionaryValue();
200 args.Append(dict);
201 dict->Set(key, pref->GetValue()->DeepCopy());
203 extensions::preference_helpers::DispatchEventToExtensions(
204 profile_, histogram_value, event_name, &args,
205 APIPermission::kFontSettings, false, pref_name);
208 FontSettingsAPI::FontSettingsAPI(content::BrowserContext* context)
209 : font_settings_event_router_(
210 new FontSettingsEventRouter(Profile::FromBrowserContext(context))) {}
212 FontSettingsAPI::~FontSettingsAPI() {
215 static base::LazyInstance<BrowserContextKeyedAPIFactory<FontSettingsAPI> >
216 g_factory = LAZY_INSTANCE_INITIALIZER;
218 // static
219 BrowserContextKeyedAPIFactory<FontSettingsAPI>*
220 FontSettingsAPI::GetFactoryInstance() {
221 return g_factory.Pointer();
224 bool FontSettingsClearFontFunction::RunSync() {
225 if (GetProfile()->IsOffTheRecord()) {
226 error_ = kSetFromIncognitoError;
227 return false;
230 scoped_ptr<fonts::ClearFont::Params> params(
231 fonts::ClearFont::Params::Create(*args_));
232 EXTENSION_FUNCTION_VALIDATE(params.get());
234 std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
235 params->details.script);
237 // Ensure |pref_path| really is for a registered per-script font pref.
238 EXTENSION_FUNCTION_VALIDATE(
239 GetProfile()->GetPrefs()->FindPreference(pref_path));
241 PreferenceAPI::Get(GetProfile())->RemoveExtensionControlledPref(
242 extension_id(), pref_path, kExtensionPrefsScopeRegular);
243 return true;
246 bool FontSettingsGetFontFunction::RunSync() {
247 scoped_ptr<fonts::GetFont::Params> params(
248 fonts::GetFont::Params::Create(*args_));
249 EXTENSION_FUNCTION_VALIDATE(params.get());
251 std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
252 params->details.script);
254 PrefService* prefs = GetProfile()->GetPrefs();
255 const PrefService::Preference* pref =
256 prefs->FindPreference(pref_path);
258 std::string font_name;
259 EXTENSION_FUNCTION_VALIDATE(
260 pref && pref->GetValue()->GetAsString(&font_name));
261 font_name = MaybeGetLocalizedFontName(font_name);
263 // We don't support incognito-specific font prefs, so don't consider them when
264 // getting level of control.
265 const bool kIncognito = false;
266 std::string level_of_control =
267 extensions::preference_helpers::GetLevelOfControl(
268 GetProfile(), extension_id(), pref_path, kIncognito);
270 base::DictionaryValue* result = new base::DictionaryValue();
271 result->SetString(kFontIdKey, font_name);
272 result->SetString(kLevelOfControlKey, level_of_control);
273 SetResult(result);
274 return true;
277 bool FontSettingsSetFontFunction::RunSync() {
278 if (GetProfile()->IsOffTheRecord()) {
279 error_ = kSetFromIncognitoError;
280 return false;
283 scoped_ptr<fonts::SetFont::Params> params(
284 fonts::SetFont::Params::Create(*args_));
285 EXTENSION_FUNCTION_VALIDATE(params.get());
287 std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
288 params->details.script);
290 // Ensure |pref_path| really is for a registered font pref.
291 EXTENSION_FUNCTION_VALIDATE(
292 GetProfile()->GetPrefs()->FindPreference(pref_path));
294 PreferenceAPI::Get(GetProfile())->SetExtensionControlledPref(
295 extension_id(),
296 pref_path,
297 kExtensionPrefsScopeRegular,
298 new base::StringValue(params->details.font_id));
299 return true;
302 bool FontSettingsGetFontListFunction::RunAsync() {
303 content::GetFontListAsync(
304 Bind(&FontSettingsGetFontListFunction::FontListHasLoaded, this));
305 return true;
308 void FontSettingsGetFontListFunction::FontListHasLoaded(
309 scoped_ptr<base::ListValue> list) {
310 bool success = CopyFontsToResult(list.get());
311 SendResponse(success);
314 bool FontSettingsGetFontListFunction::CopyFontsToResult(
315 base::ListValue* fonts) {
316 scoped_ptr<base::ListValue> result(new base::ListValue());
317 for (base::ListValue::iterator it = fonts->begin();
318 it != fonts->end(); ++it) {
319 base::ListValue* font_list_value;
320 if (!(*it)->GetAsList(&font_list_value)) {
321 NOTREACHED();
322 return false;
325 std::string name;
326 if (!font_list_value->GetString(0, &name)) {
327 NOTREACHED();
328 return false;
331 std::string localized_name;
332 if (!font_list_value->GetString(1, &localized_name)) {
333 NOTREACHED();
334 return false;
337 base::DictionaryValue* font_name = new base::DictionaryValue();
338 font_name->Set(kFontIdKey, new base::StringValue(name));
339 font_name->Set(kDisplayNameKey, new base::StringValue(localized_name));
340 result->Append(font_name);
343 SetResult(result.release());
344 return true;
347 bool ClearFontPrefExtensionFunction::RunSync() {
348 if (GetProfile()->IsOffTheRecord()) {
349 error_ = kSetFromIncognitoError;
350 return false;
353 PreferenceAPI::Get(GetProfile())->RemoveExtensionControlledPref(
354 extension_id(), GetPrefName(), kExtensionPrefsScopeRegular);
355 return true;
358 bool GetFontPrefExtensionFunction::RunSync() {
359 PrefService* prefs = GetProfile()->GetPrefs();
360 const PrefService::Preference* pref = prefs->FindPreference(GetPrefName());
361 EXTENSION_FUNCTION_VALIDATE(pref);
363 // We don't support incognito-specific font prefs, so don't consider them when
364 // getting level of control.
365 const bool kIncognito = false;
367 std::string level_of_control =
368 extensions::preference_helpers::GetLevelOfControl(
369 GetProfile(), extension_id(), GetPrefName(), kIncognito);
371 base::DictionaryValue* result = new base::DictionaryValue();
372 result->Set(GetKey(), pref->GetValue()->DeepCopy());
373 result->SetString(kLevelOfControlKey, level_of_control);
374 SetResult(result);
375 return true;
378 bool SetFontPrefExtensionFunction::RunSync() {
379 if (GetProfile()->IsOffTheRecord()) {
380 error_ = kSetFromIncognitoError;
381 return false;
384 base::DictionaryValue* details = NULL;
385 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
387 base::Value* value;
388 EXTENSION_FUNCTION_VALIDATE(details->Get(GetKey(), &value));
390 PreferenceAPI::Get(GetProfile())
391 ->SetExtensionControlledPref(extension_id(),
392 GetPrefName(),
393 kExtensionPrefsScopeRegular,
394 value->DeepCopy());
395 return true;
398 const char* FontSettingsClearDefaultFontSizeFunction::GetPrefName() {
399 return prefs::kWebKitDefaultFontSize;
402 const char* FontSettingsGetDefaultFontSizeFunction::GetPrefName() {
403 return prefs::kWebKitDefaultFontSize;
406 const char* FontSettingsGetDefaultFontSizeFunction::GetKey() {
407 return kPixelSizeKey;
410 const char* FontSettingsSetDefaultFontSizeFunction::GetPrefName() {
411 return prefs::kWebKitDefaultFontSize;
414 const char* FontSettingsSetDefaultFontSizeFunction::GetKey() {
415 return kPixelSizeKey;
418 const char* FontSettingsClearDefaultFixedFontSizeFunction::GetPrefName() {
419 return prefs::kWebKitDefaultFixedFontSize;
422 const char* FontSettingsGetDefaultFixedFontSizeFunction::GetPrefName() {
423 return prefs::kWebKitDefaultFixedFontSize;
426 const char* FontSettingsGetDefaultFixedFontSizeFunction::GetKey() {
427 return kPixelSizeKey;
430 const char* FontSettingsSetDefaultFixedFontSizeFunction::GetPrefName() {
431 return prefs::kWebKitDefaultFixedFontSize;
434 const char* FontSettingsSetDefaultFixedFontSizeFunction::GetKey() {
435 return kPixelSizeKey;
438 const char* FontSettingsClearMinimumFontSizeFunction::GetPrefName() {
439 return prefs::kWebKitMinimumFontSize;
442 const char* FontSettingsGetMinimumFontSizeFunction::GetPrefName() {
443 return prefs::kWebKitMinimumFontSize;
446 const char* FontSettingsGetMinimumFontSizeFunction::GetKey() {
447 return kPixelSizeKey;
450 const char* FontSettingsSetMinimumFontSizeFunction::GetPrefName() {
451 return prefs::kWebKitMinimumFontSize;
454 const char* FontSettingsSetMinimumFontSizeFunction::GetKey() {
455 return kPixelSizeKey;
458 } // namespace extensions