OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/mime_util.h" | 5 #include "base/mime_util.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 #include <sys/time.h> | 8 #include <sys/time.h> |
9 #include <time.h> | 9 #include <time.h> |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/string_split.h" | 21 #include "base/string_split.h" |
22 #include "base/string_util.h" | 22 #include "base/string_util.h" |
23 #include "base/third_party/xdg_mime/xdgmime.h" | 23 #include "base/third_party/xdg_mime/xdgmime.h" |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 class IconTheme; | 27 class IconTheme; |
28 | 28 |
29 class MimeUtilConstants { | 29 class MimeUtilConstants { |
30 public: | 30 public: |
| 31 static MimeUtilConstants* GetInstance() { |
| 32 return Singleton<MimeUtilConstants>::get(); |
| 33 } |
31 | 34 |
32 // In seconds, specified by icon theme specs. | 35 // In seconds, specified by icon theme specs. |
33 const int kUpdateInterval; | 36 const int kUpdateInterval; |
34 | 37 |
35 // Store icon directories and their mtimes. | 38 // Store icon directories and their mtimes. |
36 std::map<FilePath, int>* icon_dirs_; | 39 std::map<FilePath, int>* icon_dirs_; |
37 | 40 |
38 // Store icon formats. | 41 // Store icon formats. |
39 std::vector<std::string> icon_formats_; | 42 std::vector<std::string> icon_formats_; |
40 | 43 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 }; | 153 }; |
151 | 154 |
152 IconTheme::IconTheme(const std::string& name) | 155 IconTheme::IconTheme(const std::string& name) |
153 : index_theme_loaded_(false), | 156 : index_theme_loaded_(false), |
154 info_array_(NULL) { | 157 info_array_(NULL) { |
155 // Iterate on all icon directories to find directories of the specified | 158 // Iterate on all icon directories to find directories of the specified |
156 // theme and load the first encountered index.theme. | 159 // theme and load the first encountered index.theme. |
157 std::map<FilePath, int>::iterator iter; | 160 std::map<FilePath, int>::iterator iter; |
158 FilePath theme_path; | 161 FilePath theme_path; |
159 std::map<FilePath, int>* icon_dirs = | 162 std::map<FilePath, int>* icon_dirs = |
160 Singleton<MimeUtilConstants>::get()->icon_dirs_; | 163 MimeUtilConstants::GetInstance()->icon_dirs_; |
161 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { | 164 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { |
162 theme_path = iter->first.Append(name); | 165 theme_path = iter->first.Append(name); |
163 if (!file_util::DirectoryExists(theme_path)) | 166 if (!file_util::DirectoryExists(theme_path)) |
164 continue; | 167 continue; |
165 FilePath theme_index = theme_path.Append("index.theme"); | 168 FilePath theme_index = theme_path.Append("index.theme"); |
166 if (!index_theme_loaded_ && file_util::PathExists(theme_index)) { | 169 if (!index_theme_loaded_ && file_util::PathExists(theme_index)) { |
167 if (!LoadIndexTheme(theme_index)) | 170 if (!LoadIndexTheme(theme_index)) |
168 return; | 171 return; |
169 index_theme_loaded_ = true; | 172 index_theme_loaded_ = true; |
170 } | 173 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 // Inheriting from itself means the theme is buggy but we shouldn't crash. | 214 // Inheriting from itself means the theme is buggy but we shouldn't crash. |
212 if (theme && theme != this) | 215 if (theme && theme != this) |
213 return theme->GetIconPath(icon_name, size, inherits); | 216 return theme->GetIconPath(icon_name, size, inherits); |
214 else | 217 else |
215 return FilePath(); | 218 return FilePath(); |
216 } | 219 } |
217 | 220 |
218 IconTheme* IconTheme::LoadTheme(const std::string& theme_name) { | 221 IconTheme* IconTheme::LoadTheme(const std::string& theme_name) { |
219 scoped_ptr<IconTheme> theme; | 222 scoped_ptr<IconTheme> theme; |
220 std::map<std::string, IconTheme*>* icon_themes = | 223 std::map<std::string, IconTheme*>* icon_themes = |
221 Singleton<MimeUtilConstants>::get()->icon_themes_; | 224 MimeUtilConstants::GetInstance()->icon_themes_; |
222 if (icon_themes->find(theme_name) != icon_themes->end()) { | 225 if (icon_themes->find(theme_name) != icon_themes->end()) { |
223 theme.reset((*icon_themes)[theme_name]); | 226 theme.reset((*icon_themes)[theme_name]); |
224 } else { | 227 } else { |
225 theme.reset(new IconTheme(theme_name)); | 228 theme.reset(new IconTheme(theme_name)); |
226 if (!theme->IsValid()) | 229 if (!theme->IsValid()) |
227 theme.reset(); | 230 theme.reset(); |
228 (*icon_themes)[theme_name] = theme.get(); | 231 (*icon_themes)[theme_name] = theme.get(); |
229 } | 232 } |
230 return theme.release(); | 233 return theme.release(); |
231 } | 234 } |
232 | 235 |
233 FilePath IconTheme::GetIconPathUnderSubdir(const std::string& icon_name, | 236 FilePath IconTheme::GetIconPathUnderSubdir(const std::string& icon_name, |
234 const std::string& subdir) { | 237 const std::string& subdir) { |
235 FilePath icon_path; | 238 FilePath icon_path; |
236 std::list<FilePath>::iterator dir_iter; | 239 std::list<FilePath>::iterator dir_iter; |
237 std::vector<std::string>* icon_formats = | 240 std::vector<std::string>* icon_formats = |
238 &Singleton<MimeUtilConstants>::get()->icon_formats_; | 241 &MimeUtilConstants::GetInstance()->icon_formats_; |
239 for (dir_iter = dirs_.begin(); dir_iter != dirs_.end(); ++dir_iter) { | 242 for (dir_iter = dirs_.begin(); dir_iter != dirs_.end(); ++dir_iter) { |
240 for (size_t i = 0; i < icon_formats->size(); ++i) { | 243 for (size_t i = 0; i < icon_formats->size(); ++i) { |
241 icon_path = dir_iter->Append(subdir); | 244 icon_path = dir_iter->Append(subdir); |
242 icon_path = icon_path.Append(icon_name + (*icon_formats)[i]); | 245 icon_path = icon_path.Append(icon_name + (*icon_formats)[i]); |
243 if (file_util::PathExists(icon_path)) | 246 if (file_util::PathExists(icon_path)) |
244 return icon_path; | 247 return icon_path; |
245 } | 248 } |
246 } | 249 } |
247 return FilePath(); | 250 return FilePath(); |
248 } | 251 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 } | 379 } |
377 subdirs_[dir] = num++; | 380 subdirs_[dir] = num++; |
378 info_array_ = new SubDirInfo[num]; | 381 info_array_ = new SubDirInfo[num]; |
379 return true; | 382 return true; |
380 } | 383 } |
381 | 384 |
382 // Make sure |dir| exists and add it to the list of icon directories. | 385 // Make sure |dir| exists and add it to the list of icon directories. |
383 void TryAddIconDir(const FilePath& dir) { | 386 void TryAddIconDir(const FilePath& dir) { |
384 if (!file_util::DirectoryExists(dir)) | 387 if (!file_util::DirectoryExists(dir)) |
385 return; | 388 return; |
386 (*Singleton<MimeUtilConstants>::get()->icon_dirs_)[dir] = 0; | 389 (*MimeUtilConstants::GetInstance()->icon_dirs_)[dir] = 0; |
387 } | 390 } |
388 | 391 |
389 // For a xdg directory |dir|, add the appropriate icon sub-directories. | 392 // For a xdg directory |dir|, add the appropriate icon sub-directories. |
390 void AddXDGDataDir(const FilePath& dir) { | 393 void AddXDGDataDir(const FilePath& dir) { |
391 if (!file_util::DirectoryExists(dir)) | 394 if (!file_util::DirectoryExists(dir)) |
392 return; | 395 return; |
393 TryAddIconDir(dir.Append("icons")); | 396 TryAddIconDir(dir.Append("icons")); |
394 TryAddIconDir(dir.Append("pixmaps")); | 397 TryAddIconDir(dir.Append("pixmaps")); |
395 } | 398 } |
396 | 399 |
397 // Add all the xdg icon directories. | 400 // Add all the xdg icon directories. |
398 void InitIconDir() { | 401 void InitIconDir() { |
399 Singleton<MimeUtilConstants>::get()->icon_dirs_->clear(); | 402 MimeUtilConstants::GetInstance()->icon_dirs_->clear(); |
400 FilePath home = file_util::GetHomeDir(); | 403 FilePath home = file_util::GetHomeDir(); |
401 if (!home.empty()) { | 404 if (!home.empty()) { |
402 FilePath legacy_data_dir(home); | 405 FilePath legacy_data_dir(home); |
403 legacy_data_dir = legacy_data_dir.AppendASCII(".icons"); | 406 legacy_data_dir = legacy_data_dir.AppendASCII(".icons"); |
404 if (file_util::DirectoryExists(legacy_data_dir)) | 407 if (file_util::DirectoryExists(legacy_data_dir)) |
405 TryAddIconDir(legacy_data_dir); | 408 TryAddIconDir(legacy_data_dir); |
406 } | 409 } |
407 const char* env = getenv("XDG_DATA_HOME"); | 410 const char* env = getenv("XDG_DATA_HOME"); |
408 if (env) { | 411 if (env) { |
409 AddXDGDataDir(FilePath(env)); | 412 AddXDGDataDir(FilePath(env)); |
(...skipping 18 matching lines...) Expand all Loading... |
428 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); | 431 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); |
429 } | 432 } |
430 } | 433 } |
431 | 434 |
432 // Per xdg theme spec, we should check the icon directories every so often for | 435 // Per xdg theme spec, we should check the icon directories every so often for |
433 // newly added icons. This isn't quite right. | 436 // newly added icons. This isn't quite right. |
434 void EnsureUpdated() { | 437 void EnsureUpdated() { |
435 struct timeval t; | 438 struct timeval t; |
436 gettimeofday(&t, NULL); | 439 gettimeofday(&t, NULL); |
437 time_t now = t.tv_sec; | 440 time_t now = t.tv_sec; |
438 MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get(); | 441 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); |
439 | 442 |
440 if (constants->last_check_time_ == 0) { | 443 if (constants->last_check_time_ == 0) { |
441 constants->icon_dirs_ = new std::map<FilePath, int>; | 444 constants->icon_dirs_ = new std::map<FilePath, int>; |
442 constants->icon_themes_ = new std::map<std::string, IconTheme*>; | 445 constants->icon_themes_ = new std::map<std::string, IconTheme*>; |
443 InitIconDir(); | 446 InitIconDir(); |
444 constants->last_check_time_ = now; | 447 constants->last_check_time_ = now; |
445 } else { | 448 } else { |
446 // TODO(thestig): something changed. start over. Upstream fix to Google | 449 // TODO(thestig): something changed. start over. Upstream fix to Google |
447 // Gadgets for Linux. | 450 // Gadgets for Linux. |
448 if (now > constants->last_check_time_ + constants->kUpdateInterval) { | 451 if (now > constants->last_check_time_ + constants->kUpdateInterval) { |
449 } | 452 } |
450 } | 453 } |
451 } | 454 } |
452 | 455 |
453 // Find a fallback icon if we cannot find it in the default theme. | 456 // Find a fallback icon if we cannot find it in the default theme. |
454 FilePath LookupFallbackIcon(const std::string& icon_name) { | 457 FilePath LookupFallbackIcon(const std::string& icon_name) { |
455 FilePath icon; | 458 FilePath icon; |
456 MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get(); | 459 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); |
457 std::map<FilePath, int>::iterator iter; | 460 std::map<FilePath, int>::iterator iter; |
458 std::map<FilePath, int>* icon_dirs = constants->icon_dirs_; | 461 std::map<FilePath, int>* icon_dirs = constants->icon_dirs_; |
459 std::vector<std::string>* icon_formats = &constants->icon_formats_; | 462 std::vector<std::string>* icon_formats = &constants->icon_formats_; |
460 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { | 463 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { |
461 for (size_t i = 0; i < icon_formats->size(); ++i) { | 464 for (size_t i = 0; i < icon_formats->size(); ++i) { |
462 icon = iter->first.Append(icon_name + (*icon_formats)[i]); | 465 icon = iter->first.Append(icon_name + (*icon_formats)[i]); |
463 if (file_util::PathExists(icon)) | 466 if (file_util::PathExists(icon)) |
464 return icon; | 467 return icon; |
465 } | 468 } |
466 } | 469 } |
467 return FilePath(); | 470 return FilePath(); |
468 } | 471 } |
469 | 472 |
470 // Initialize the list of default themes. | 473 // Initialize the list of default themes. |
471 void InitDefaultThemes() { | 474 void InitDefaultThemes() { |
472 IconTheme** default_themes = | 475 IconTheme** default_themes = |
473 Singleton<MimeUtilConstants>::get()->default_themes_; | 476 MimeUtilConstants::GetInstance()->default_themes_; |
474 | 477 |
475 char* env = getenv("KDE_FULL_SESSION"); | 478 char* env = getenv("KDE_FULL_SESSION"); |
476 if (env) { | 479 if (env) { |
477 // KDE | 480 // KDE |
478 std::string kde_default_theme; | 481 std::string kde_default_theme; |
479 std::string kde_fallback_theme; | 482 std::string kde_fallback_theme; |
480 | 483 |
481 // TODO(thestig): Figure out how to get the current icon theme on KDE. | 484 // TODO(thestig): Figure out how to get the current icon theme on KDE. |
482 // Setting stored in ~/.kde/share/config/kdeglobals under Icons -> Theme. | 485 // Setting stored in ~/.kde/share/config/kdeglobals under Icons -> Theme. |
483 default_themes[0] = NULL; | 486 default_themes[0] = NULL; |
484 | 487 |
485 // Try some reasonable defaults for KDE. | 488 // Try some reasonable defaults for KDE. |
486 env = getenv("KDE_SESSION_VERSION"); | 489 env = getenv("KDE_SESSION_VERSION"); |
487 if (!env || env[0] != '4') { | 490 if (!env || env[0] != '4') { |
488 // KDE 3 | 491 // KDE 3 |
489 kde_default_theme = "default.kde"; | 492 kde_default_theme = "default.kde"; |
490 kde_fallback_theme = "crystalsvg"; | 493 kde_fallback_theme = "crystalsvg"; |
491 } else { | 494 } else { |
492 // KDE 4 | 495 // KDE 4 |
493 kde_default_theme = "default.kde4"; | 496 kde_default_theme = "default.kde4"; |
494 kde_fallback_theme = "oxygen"; | 497 kde_fallback_theme = "oxygen"; |
495 } | 498 } |
496 default_themes[1] = IconTheme::LoadTheme(kde_default_theme); | 499 default_themes[1] = IconTheme::LoadTheme(kde_default_theme); |
497 default_themes[2] = IconTheme::LoadTheme(kde_fallback_theme); | 500 default_themes[2] = IconTheme::LoadTheme(kde_fallback_theme); |
498 } else { | 501 } else { |
499 // Assume it's Gnome and use GTK to figure out the theme. | 502 // Assume it's Gnome and use GTK to figure out the theme. |
500 default_themes[1] = IconTheme::LoadTheme( | 503 default_themes[1] = IconTheme::LoadTheme( |
501 Singleton<MimeUtilConstants>::get()->gtk_theme_name_); | 504 MimeUtilConstants::GetInstance()->gtk_theme_name_); |
502 default_themes[2] = IconTheme::LoadTheme("gnome"); | 505 default_themes[2] = IconTheme::LoadTheme("gnome"); |
503 } | 506 } |
504 // hicolor needs to be last per icon theme spec. | 507 // hicolor needs to be last per icon theme spec. |
505 default_themes[3] = IconTheme::LoadTheme("hicolor"); | 508 default_themes[3] = IconTheme::LoadTheme("hicolor"); |
506 | 509 |
507 for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) { | 510 for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) { |
508 if (default_themes[i] == NULL) | 511 if (default_themes[i] == NULL) |
509 continue; | 512 continue; |
510 // NULL out duplicate pointers. | 513 // NULL out duplicate pointers. |
511 for (size_t j = i + 1; j < MimeUtilConstants::kDefaultThemeNum; j++) { | 514 for (size_t j = i + 1; j < MimeUtilConstants::kDefaultThemeNum; j++) { |
512 if (default_themes[j] == default_themes[i]) | 515 if (default_themes[j] == default_themes[i]) |
513 default_themes[j] = NULL; | 516 default_themes[j] = NULL; |
514 } | 517 } |
515 } | 518 } |
516 } | 519 } |
517 | 520 |
518 // Try to find an icon with the name |icon_name| that's |size| pixels. | 521 // Try to find an icon with the name |icon_name| that's |size| pixels. |
519 FilePath LookupIconInDefaultTheme(const std::string& icon_name, int size) { | 522 FilePath LookupIconInDefaultTheme(const std::string& icon_name, int size) { |
520 EnsureUpdated(); | 523 EnsureUpdated(); |
521 MimeUtilConstants* constants = Singleton<MimeUtilConstants>::get(); | 524 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); |
522 std::map<std::string, IconTheme*>* icon_themes = constants->icon_themes_; | 525 std::map<std::string, IconTheme*>* icon_themes = constants->icon_themes_; |
523 if (icon_themes->size() == 0) | 526 if (icon_themes->size() == 0) |
524 InitDefaultThemes(); | 527 InitDefaultThemes(); |
525 | 528 |
526 FilePath icon_path; | 529 FilePath icon_path; |
527 IconTheme** default_themes = constants->default_themes_; | 530 IconTheme** default_themes = constants->default_themes_; |
528 for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) { | 531 for (size_t i = 0; i < MimeUtilConstants::kDefaultThemeNum; i++) { |
529 if (default_themes[i]) { | 532 if (default_themes[i]) { |
530 icon_path = default_themes[i]->GetIconPath(icon_name, size, true); | 533 icon_path = default_themes[i]->GetIconPath(icon_name, size, true); |
531 if (!icon_path.empty()) | 534 if (!icon_path.empty()) |
(...skipping 19 matching lines...) Expand all Loading... |
551 } | 554 } |
552 | 555 |
553 std::string GetDataMimeType(const std::string& data) { | 556 std::string GetDataMimeType(const std::string& data) { |
554 return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL); | 557 return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL); |
555 } | 558 } |
556 | 559 |
557 void DetectGtkTheme() { | 560 void DetectGtkTheme() { |
558 // If the theme name is already loaded, do nothing. Chrome doesn't respond | 561 // If the theme name is already loaded, do nothing. Chrome doesn't respond |
559 // to changes in the system theme, so we never need to set this more than | 562 // to changes in the system theme, so we never need to set this more than |
560 // once. | 563 // once. |
561 if (!Singleton<MimeUtilConstants>::get()->gtk_theme_name_.empty()) | 564 if (!MimeUtilConstants::GetInstance()->gtk_theme_name_.empty()) |
562 return; | 565 return; |
563 | 566 |
564 // We should only be called on the UI thread. | 567 // We should only be called on the UI thread. |
565 DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()); | 568 DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()); |
566 | 569 |
567 gchar* gtk_theme_name; | 570 gchar* gtk_theme_name; |
568 g_object_get(gtk_settings_get_default(), | 571 g_object_get(gtk_settings_get_default(), |
569 "gtk-icon-theme-name", | 572 "gtk-icon-theme-name", |
570 >k_theme_name, NULL); | 573 >k_theme_name, NULL); |
571 Singleton<MimeUtilConstants>::get()->gtk_theme_name_.assign(gtk_theme_name); | 574 MimeUtilConstants::GetInstance()->gtk_theme_name_.assign(gtk_theme_name); |
572 g_free(gtk_theme_name); | 575 g_free(gtk_theme_name); |
573 } | 576 } |
574 | 577 |
575 FilePath GetMimeIcon(const std::string& mime_type, size_t size) { | 578 FilePath GetMimeIcon(const std::string& mime_type, size_t size) { |
576 std::vector<std::string> icon_names; | 579 std::vector<std::string> icon_names; |
577 std::string icon_name; | 580 std::string icon_name; |
578 FilePath icon_file; | 581 FilePath icon_file; |
579 | 582 |
580 const char* icon = xdg_mime_get_icon(mime_type.c_str()); | 583 const char* icon = xdg_mime_get_icon(mime_type.c_str()); |
581 icon_name = std::string(icon ? icon : ""); | 584 icon_name = std::string(icon ? icon : ""); |
(...skipping 29 matching lines...) Expand all Loading... |
611 } else { | 614 } else { |
612 icon_file = LookupIconInDefaultTheme(icon_names[i], size); | 615 icon_file = LookupIconInDefaultTheme(icon_names[i], size); |
613 if (!icon_file.empty()) | 616 if (!icon_file.empty()) |
614 return icon_file; | 617 return icon_file; |
615 } | 618 } |
616 } | 619 } |
617 return FilePath(); | 620 return FilePath(); |
618 } | 621 } |
619 | 622 |
620 } // namespace mime_util | 623 } // namespace mime_util |
OLD | NEW |