- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / font_settings / font_settings_api.cc
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 // Font Settings Extension API implementation.
6
7 #include "chrome/browser/extensions/api/font_settings/font_settings_api.h"
8
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/prefs/pref_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/values.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/extensions/api/preference/preference_api.h"
19 #include "chrome/browser/extensions/api/preference/preference_helpers.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_system.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/extensions/api/font_settings.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/pref_names_util.h"
26 #include "content/public/browser/font_list_async.h"
27 #include "content/public/browser/notification_details.h"
28 #include "content/public/browser/notification_source.h"
29 #include "extensions/common/error_utils.h"
30
31 #if defined(OS_WIN)
32 #include "ui/gfx/font.h"
33 #include "ui/gfx/platform_font_win.h"
34 #endif
35
36 namespace extensions {
37
38 namespace fonts = api::font_settings;
39
40 namespace {
41
42 const char kFontIdKey[] = "fontId";
43 const char kGenericFamilyKey[] = "genericFamily";
44 const char kLevelOfControlKey[] = "levelOfControl";
45 const char kDisplayNameKey[] = "displayName";
46 const char kPixelSizeKey[] = "pixelSize";
47 const char kScriptKey[] = "script";
48
49 const char kSetFromIncognitoError[] =
50     "Can't modify regular settings from an incognito context.";
51
52 // Format for font name preference paths.
53 const char kWebKitFontPrefFormat[] = "webkit.webprefs.fonts.%s.%s";
54
55 // Gets the font name preference path for |generic_family| and |script|. If
56 // |script| is NULL, uses prefs::kWebKitCommonScript.
57 std::string GetFontNamePrefPath(fonts::GenericFamily generic_family_enum,
58                                 fonts::ScriptCode script_enum) {
59   std::string script = fonts::ToString(script_enum);
60   if (script.empty())
61     script = prefs::kWebKitCommonScript;
62   std::string generic_family = fonts::ToString(generic_family_enum);
63   return base::StringPrintf(kWebKitFontPrefFormat,
64                             generic_family.c_str(),
65                             script.c_str());
66 }
67
68 // Returns the localized name of a font so that it can be matched within the
69 // list of system fonts. On Windows, the list of system fonts has names only
70 // for the system locale, but the pref value may be in the English name.
71 std::string MaybeGetLocalizedFontName(const std::string& font_name) {
72 #if defined(OS_WIN)
73   if (!font_name.empty()) {
74     gfx::Font font(font_name, 12);  // dummy font size
75     return static_cast<gfx::PlatformFontWin*>(font.platform_font())->
76         GetLocalizedFontName();
77   }
78 #endif
79   return font_name;
80 }
81
82 // Registers |obs| to observe per-script font prefs under the path |map_name|.
83 void RegisterFontFamilyMapObserver(
84     PrefChangeRegistrar* registrar,
85     const char* map_name,
86     const PrefChangeRegistrar::NamedChangeCallback& callback) {
87   for (size_t i = 0; i < prefs::kWebKitScriptsForFontFamilyMapsLength; ++i) {
88     const char* script = prefs::kWebKitScriptsForFontFamilyMaps[i];
89     std::string pref_name = base::StringPrintf("%s.%s", map_name, script);
90     registrar->Add(pref_name.c_str(), callback);
91   }
92 }
93
94 }  // namespace
95
96 FontSettingsEventRouter::FontSettingsEventRouter(
97     Profile* profile) : profile_(profile) {
98   registrar_.Init(profile_->GetPrefs());
99
100   AddPrefToObserve(prefs::kWebKitDefaultFixedFontSize,
101                    fonts::OnDefaultFixedFontSizeChanged::kEventName,
102                    kPixelSizeKey);
103   AddPrefToObserve(prefs::kWebKitDefaultFontSize,
104                    fonts::OnDefaultFontSizeChanged::kEventName,
105                    kPixelSizeKey);
106   AddPrefToObserve(prefs::kWebKitMinimumFontSize,
107                    fonts::OnMinimumFontSizeChanged::kEventName,
108                    kPixelSizeKey);
109
110   PrefChangeRegistrar::NamedChangeCallback callback =
111       base::Bind(&FontSettingsEventRouter::OnFontFamilyMapPrefChanged,
112                  base::Unretained(this));
113   RegisterFontFamilyMapObserver(&registrar_,
114                                 prefs::kWebKitStandardFontFamilyMap, callback);
115   RegisterFontFamilyMapObserver(&registrar_,
116                                 prefs::kWebKitSerifFontFamilyMap, callback);
117   RegisterFontFamilyMapObserver(&registrar_,
118                                 prefs::kWebKitSansSerifFontFamilyMap, callback);
119   RegisterFontFamilyMapObserver(&registrar_,
120                                 prefs::kWebKitFixedFontFamilyMap, callback);
121   RegisterFontFamilyMapObserver(&registrar_,
122                                 prefs::kWebKitCursiveFontFamilyMap, callback);
123   RegisterFontFamilyMapObserver(&registrar_,
124                                 prefs::kWebKitFantasyFontFamilyMap, callback);
125   RegisterFontFamilyMapObserver(&registrar_,
126                                 prefs::kWebKitPictographFontFamilyMap,
127                                 callback);
128 }
129
130 FontSettingsEventRouter::~FontSettingsEventRouter() {}
131
132 void FontSettingsEventRouter::AddPrefToObserve(const char* pref_name,
133                                                const char* event_name,
134                                                const char* key) {
135   registrar_.Add(pref_name,
136                  base::Bind(&FontSettingsEventRouter::OnFontPrefChanged,
137                             base::Unretained(this),
138                             event_name, key));
139 }
140
141 void FontSettingsEventRouter::OnFontFamilyMapPrefChanged(
142     const std::string& pref_name) {
143   std::string generic_family;
144   std::string script;
145   if (pref_names_util::ParseFontNamePrefPath(pref_name, &generic_family,
146                                              &script)) {
147     OnFontNamePrefChanged(pref_name, generic_family, script);
148     return;
149   }
150
151   NOTREACHED();
152 }
153
154 void FontSettingsEventRouter::OnFontNamePrefChanged(
155     const std::string& pref_name,
156     const std::string& generic_family,
157     const std::string& script) {
158   const PrefService::Preference* pref = registrar_.prefs()->FindPreference(
159       pref_name.c_str());
160   CHECK(pref);
161
162   std::string font_name;
163   if (!pref->GetValue()->GetAsString(&font_name)) {
164     NOTREACHED();
165     return;
166   }
167   font_name = MaybeGetLocalizedFontName(font_name);
168
169   base::ListValue args;
170   base::DictionaryValue* dict = new base::DictionaryValue();
171   args.Append(dict);
172   dict->SetString(kFontIdKey, font_name);
173   dict->SetString(kGenericFamilyKey, generic_family);
174   dict->SetString(kScriptKey, script);
175
176   extensions::preference_helpers::DispatchEventToExtensions(
177       profile_,
178       fonts::OnFontChanged::kEventName,
179       &args,
180       APIPermission::kFontSettings,
181       false,
182       pref_name);
183 }
184
185 void FontSettingsEventRouter::OnFontPrefChanged(
186     const std::string& event_name,
187     const std::string& key,
188     const std::string& pref_name) {
189   const PrefService::Preference* pref = registrar_.prefs()->FindPreference(
190       pref_name.c_str());
191   CHECK(pref);
192
193   base::ListValue args;
194   base::DictionaryValue* dict = new base::DictionaryValue();
195   args.Append(dict);
196   dict->Set(key, pref->GetValue()->DeepCopy());
197
198   extensions::preference_helpers::DispatchEventToExtensions(
199       profile_,
200       event_name,
201       &args,
202       APIPermission::kFontSettings,
203       false,
204       pref_name);
205 }
206
207 FontSettingsAPI::FontSettingsAPI(Profile* profile)
208     : font_settings_event_router_(new FontSettingsEventRouter(profile)) {
209 }
210
211 FontSettingsAPI::~FontSettingsAPI() {
212 }
213
214 static base::LazyInstance<ProfileKeyedAPIFactory<FontSettingsAPI> >
215 g_factory = LAZY_INSTANCE_INITIALIZER;
216
217 // static
218 ProfileKeyedAPIFactory<FontSettingsAPI>* FontSettingsAPI::GetFactoryInstance() {
219   return &g_factory.Get();
220 }
221
222 bool FontSettingsClearFontFunction::RunImpl() {
223   if (GetProfile()->IsOffTheRecord()) {
224     error_ = kSetFromIncognitoError;
225     return false;
226   }
227
228   scoped_ptr<fonts::ClearFont::Params> params(
229       fonts::ClearFont::Params::Create(*args_));
230   EXTENSION_FUNCTION_VALIDATE(params.get());
231
232   std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
233                                               params->details.script);
234
235   // Ensure |pref_path| really is for a registered per-script font pref.
236   EXTENSION_FUNCTION_VALIDATE(
237       GetProfile()->GetPrefs()->FindPreference(pref_path.c_str()));
238
239   PreferenceAPI::Get(GetProfile())->RemoveExtensionControlledPref(
240       extension_id(), pref_path.c_str(), kExtensionPrefsScopeRegular);
241   return true;
242 }
243
244 bool FontSettingsGetFontFunction::RunImpl() {
245   scoped_ptr<fonts::GetFont::Params> params(
246       fonts::GetFont::Params::Create(*args_));
247   EXTENSION_FUNCTION_VALIDATE(params.get());
248
249   std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
250                                               params->details.script);
251
252   PrefService* prefs = GetProfile()->GetPrefs();
253   const PrefService::Preference* pref =
254       prefs->FindPreference(pref_path.c_str());
255
256   std::string font_name;
257   EXTENSION_FUNCTION_VALIDATE(
258       pref && pref->GetValue()->GetAsString(&font_name));
259   font_name = MaybeGetLocalizedFontName(font_name);
260
261   // We don't support incognito-specific font prefs, so don't consider them when
262   // getting level of control.
263   const bool kIncognito = false;
264   std::string level_of_control =
265       extensions::preference_helpers::GetLevelOfControl(
266           GetProfile(), extension_id(), pref_path, kIncognito);
267
268   base::DictionaryValue* result = new base::DictionaryValue();
269   result->SetString(kFontIdKey, font_name);
270   result->SetString(kLevelOfControlKey, level_of_control);
271   SetResult(result);
272   return true;
273 }
274
275 bool FontSettingsSetFontFunction::RunImpl() {
276   if (GetProfile()->IsOffTheRecord()) {
277     error_ = kSetFromIncognitoError;
278     return false;
279   }
280
281   scoped_ptr<fonts::SetFont::Params> params(
282       fonts::SetFont::Params::Create(*args_));
283   EXTENSION_FUNCTION_VALIDATE(params.get());
284
285   std::string pref_path = GetFontNamePrefPath(params->details.generic_family,
286                                               params->details.script);
287
288   // Ensure |pref_path| really is for a registered font pref.
289   EXTENSION_FUNCTION_VALIDATE(
290       GetProfile()->GetPrefs()->FindPreference(pref_path.c_str()));
291
292   PreferenceAPI::Get(GetProfile())->SetExtensionControlledPref(
293       extension_id(),
294       pref_path.c_str(),
295       kExtensionPrefsScopeRegular,
296       new base::StringValue(params->details.font_id));
297   return true;
298 }
299
300 bool FontSettingsGetFontListFunction::RunImpl() {
301   content::GetFontListAsync(
302       Bind(&FontSettingsGetFontListFunction::FontListHasLoaded, this));
303   return true;
304 }
305
306 void FontSettingsGetFontListFunction::FontListHasLoaded(
307     scoped_ptr<base::ListValue> list) {
308   bool success = CopyFontsToResult(list.get());
309   SendResponse(success);
310 }
311
312 bool FontSettingsGetFontListFunction::CopyFontsToResult(
313     base::ListValue* fonts) {
314   scoped_ptr<base::ListValue> result(new base::ListValue());
315   for (base::ListValue::iterator it = fonts->begin();
316        it != fonts->end(); ++it) {
317     base::ListValue* font_list_value;
318     if (!(*it)->GetAsList(&font_list_value)) {
319       NOTREACHED();
320       return false;
321     }
322
323     std::string name;
324     if (!font_list_value->GetString(0, &name)) {
325       NOTREACHED();
326       return false;
327     }
328
329     std::string localized_name;
330     if (!font_list_value->GetString(1, &localized_name)) {
331       NOTREACHED();
332       return false;
333     }
334
335     base::DictionaryValue* font_name = new base::DictionaryValue();
336     font_name->Set(kFontIdKey, new base::StringValue(name));
337     font_name->Set(kDisplayNameKey, new base::StringValue(localized_name));
338     result->Append(font_name);
339   }
340
341   SetResult(result.release());
342   return true;
343 }
344
345 bool ClearFontPrefExtensionFunction::RunImpl() {
346   if (GetProfile()->IsOffTheRecord()) {
347     error_ = kSetFromIncognitoError;
348     return false;
349   }
350
351   PreferenceAPI::Get(GetProfile())->RemoveExtensionControlledPref(
352       extension_id(), GetPrefName(), kExtensionPrefsScopeRegular);
353   return true;
354 }
355
356 bool GetFontPrefExtensionFunction::RunImpl() {
357   PrefService* prefs = GetProfile()->GetPrefs();
358   const PrefService::Preference* pref = prefs->FindPreference(GetPrefName());
359   EXTENSION_FUNCTION_VALIDATE(pref);
360
361   // We don't support incognito-specific font prefs, so don't consider them when
362   // getting level of control.
363   const bool kIncognito = false;
364
365   std::string level_of_control =
366       extensions::preference_helpers::GetLevelOfControl(
367           GetProfile(), extension_id(), GetPrefName(), kIncognito);
368
369   base::DictionaryValue* result = new base::DictionaryValue();
370   result->Set(GetKey(), pref->GetValue()->DeepCopy());
371   result->SetString(kLevelOfControlKey, level_of_control);
372   SetResult(result);
373   return true;
374 }
375
376 bool SetFontPrefExtensionFunction::RunImpl() {
377   if (GetProfile()->IsOffTheRecord()) {
378     error_ = kSetFromIncognitoError;
379     return false;
380   }
381
382   base::DictionaryValue* details = NULL;
383   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
384
385   Value* value;
386   EXTENSION_FUNCTION_VALIDATE(details->Get(GetKey(), &value));
387
388   PreferenceAPI::Get(GetProfile())
389       ->SetExtensionControlledPref(extension_id(),
390                                    GetPrefName(),
391                                    kExtensionPrefsScopeRegular,
392                                    value->DeepCopy());
393   return true;
394 }
395
396 const char* FontSettingsClearDefaultFontSizeFunction::GetPrefName() {
397   return prefs::kWebKitDefaultFontSize;
398 }
399
400 const char* FontSettingsGetDefaultFontSizeFunction::GetPrefName() {
401   return prefs::kWebKitDefaultFontSize;
402 }
403
404 const char* FontSettingsGetDefaultFontSizeFunction::GetKey() {
405   return kPixelSizeKey;
406 }
407
408 const char* FontSettingsSetDefaultFontSizeFunction::GetPrefName() {
409   return prefs::kWebKitDefaultFontSize;
410 }
411
412 const char* FontSettingsSetDefaultFontSizeFunction::GetKey() {
413   return kPixelSizeKey;
414 }
415
416 const char* FontSettingsClearDefaultFixedFontSizeFunction::GetPrefName() {
417   return prefs::kWebKitDefaultFixedFontSize;
418 }
419
420 const char* FontSettingsGetDefaultFixedFontSizeFunction::GetPrefName() {
421   return prefs::kWebKitDefaultFixedFontSize;
422 }
423
424 const char* FontSettingsGetDefaultFixedFontSizeFunction::GetKey() {
425   return kPixelSizeKey;
426 }
427
428 const char* FontSettingsSetDefaultFixedFontSizeFunction::GetPrefName() {
429   return prefs::kWebKitDefaultFixedFontSize;
430 }
431
432 const char* FontSettingsSetDefaultFixedFontSizeFunction::GetKey() {
433   return kPixelSizeKey;
434 }
435
436 const char* FontSettingsClearMinimumFontSizeFunction::GetPrefName() {
437   return prefs::kWebKitMinimumFontSize;
438 }
439
440 const char* FontSettingsGetMinimumFontSizeFunction::GetPrefName() {
441   return prefs::kWebKitMinimumFontSize;
442 }
443
444 const char* FontSettingsGetMinimumFontSizeFunction::GetKey() {
445   return kPixelSizeKey;
446 }
447
448 const char* FontSettingsSetMinimumFontSizeFunction::GetPrefName() {
449   return prefs::kWebKitMinimumFontSize;
450 }
451
452 const char* FontSettingsSetMinimumFontSizeFunction::GetKey() {
453   return kPixelSizeKey;
454 }
455
456 }  // namespace extensions