OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/nix/mime_util_xdg.h" | 5 #include "base/nix/mime_util_xdg.h" |
6 | 6 |
7 #include <cstdlib> | 7 #include <cstdlib> |
8 #include <list> | 8 #include <list> |
9 #include <map> | 9 #include <map> |
10 #include <vector> | 10 #include <vector> |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 namespace base { | 26 namespace base { |
27 namespace nix { | 27 namespace nix { |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 class IconTheme; | 31 class IconTheme; |
32 | 32 |
33 // None of the XDG stuff is thread-safe, so serialize all access under | 33 // None of the XDG stuff is thread-safe, so serialize all access under |
34 // this lock. | 34 // this lock. |
35 base::LazyInstance<base::Lock>::Leaky | 35 LazyInstance<Lock>::Leaky g_mime_util_xdg_lock = LAZY_INSTANCE_INITIALIZER; |
36 g_mime_util_xdg_lock = LAZY_INSTANCE_INITIALIZER; | |
37 | 36 |
38 class MimeUtilConstants { | 37 class MimeUtilConstants { |
39 public: | 38 public: |
40 typedef std::map<std::string, IconTheme*> IconThemeMap; | 39 typedef std::map<std::string, IconTheme*> IconThemeMap; |
41 typedef std::map<FilePath, base::Time> IconDirMtimeMap; | 40 typedef std::map<FilePath, Time> IconDirMtimeMap; |
42 typedef std::vector<std::string> IconFormats; | 41 typedef std::vector<std::string> IconFormats; |
43 | 42 |
44 // Specified by XDG icon theme specs. | 43 // Specified by XDG icon theme specs. |
45 static const int kUpdateIntervalInSeconds = 5; | 44 static const int kUpdateIntervalInSeconds = 5; |
46 | 45 |
47 static const size_t kDefaultThemeNum = 4; | 46 static const size_t kDefaultThemeNum = 4; |
48 | 47 |
49 static MimeUtilConstants* GetInstance() { | 48 static MimeUtilConstants* GetInstance() { |
50 return Singleton<MimeUtilConstants>::get(); | 49 return Singleton<MimeUtilConstants>::get(); |
51 } | 50 } |
52 | 51 |
53 // Store icon directories and their mtimes. | 52 // Store icon directories and their mtimes. |
54 IconDirMtimeMap icon_dirs_; | 53 IconDirMtimeMap icon_dirs_; |
55 | 54 |
56 // Store icon formats. | 55 // Store icon formats. |
57 IconFormats icon_formats_; | 56 IconFormats icon_formats_; |
58 | 57 |
59 // Store loaded icon_theme. | 58 // Store loaded icon_theme. |
60 IconThemeMap icon_themes_; | 59 IconThemeMap icon_themes_; |
61 | 60 |
62 // The default theme. | 61 // The default theme. |
63 IconTheme* default_themes_[kDefaultThemeNum]; | 62 IconTheme* default_themes_[kDefaultThemeNum]; |
64 | 63 |
65 base::TimeTicks last_check_time_; | 64 TimeTicks last_check_time_; |
66 | 65 |
67 // The current icon theme, usually set through GTK theme integration. | 66 // The current icon theme, usually set through GTK theme integration. |
68 std::string icon_theme_name_; | 67 std::string icon_theme_name_; |
69 | 68 |
70 private: | 69 private: |
71 MimeUtilConstants() { | 70 MimeUtilConstants() { |
72 icon_formats_.push_back(".png"); | 71 icon_formats_.push_back(".png"); |
73 icon_formats_.push_back(".svg"); | 72 icon_formats_.push_back(".svg"); |
74 icon_formats_.push_back(".xpm"); | 73 icon_formats_.push_back(".xpm"); |
75 | 74 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 std::list<FilePath> dirs_; | 151 std::list<FilePath> dirs_; |
153 | 152 |
154 // store the subdirs of this theme and array index of |info_array_|. | 153 // store the subdirs of this theme and array index of |info_array_|. |
155 std::map<std::string, int> subdirs_; | 154 std::map<std::string, int> subdirs_; |
156 scoped_ptr<SubDirInfo[]> info_array_; // List of sub-directories. | 155 scoped_ptr<SubDirInfo[]> info_array_; // List of sub-directories. |
157 std::string inherits_; // Name of the theme this one inherits from. | 156 std::string inherits_; // Name of the theme this one inherits from. |
158 }; | 157 }; |
159 | 158 |
160 IconTheme::IconTheme(const std::string& name) | 159 IconTheme::IconTheme(const std::string& name) |
161 : index_theme_loaded_(false) { | 160 : index_theme_loaded_(false) { |
162 base::ThreadRestrictions::AssertIOAllowed(); | 161 ThreadRestrictions::AssertIOAllowed(); |
163 // Iterate on all icon directories to find directories of the specified | 162 // Iterate on all icon directories to find directories of the specified |
164 // theme and load the first encountered index.theme. | 163 // theme and load the first encountered index.theme. |
165 MimeUtilConstants::IconDirMtimeMap::iterator iter; | 164 MimeUtilConstants::IconDirMtimeMap::iterator iter; |
166 FilePath theme_path; | 165 FilePath theme_path; |
167 MimeUtilConstants::IconDirMtimeMap* icon_dirs = | 166 MimeUtilConstants::IconDirMtimeMap* icon_dirs = |
168 &MimeUtilConstants::GetInstance()->icon_dirs_; | 167 &MimeUtilConstants::GetInstance()->icon_dirs_; |
169 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { | 168 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { |
170 theme_path = iter->first.Append(name); | 169 theme_path = iter->first.Append(name); |
171 if (!DirectoryExists(theme_path)) | 170 if (!DirectoryExists(theme_path)) |
172 continue; | 171 continue; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 continue; | 273 continue; |
275 } else if (entry[0] == '[' && info_array_.get()) { | 274 } else if (entry[0] == '[' && info_array_.get()) { |
276 current_info = NULL; | 275 current_info = NULL; |
277 std::string subdir = entry.substr(1, entry.length() - 2); | 276 std::string subdir = entry.substr(1, entry.length() - 2); |
278 if (subdirs_.find(subdir) != subdirs_.end()) | 277 if (subdirs_.find(subdir) != subdirs_.end()) |
279 current_info = &info_array_[subdirs_[subdir]]; | 278 current_info = &info_array_[subdirs_[subdir]]; |
280 } | 279 } |
281 | 280 |
282 std::string key, value; | 281 std::string key, value; |
283 std::vector<std::string> r; | 282 std::vector<std::string> r; |
284 base::SplitStringDontTrim(entry, '=', &r); | 283 SplitStringDontTrim(entry, '=', &r); |
285 if (r.size() < 2) | 284 if (r.size() < 2) |
286 continue; | 285 continue; |
287 | 286 |
288 TrimWhitespaceASCII(r[0], TRIM_ALL, &key); | 287 TrimWhitespaceASCII(r[0], TRIM_ALL, &key); |
289 for (size_t i = 1; i < r.size(); i++) | 288 for (size_t i = 1; i < r.size(); i++) |
290 value.append(r[i]); | 289 value.append(r[i]); |
291 TrimWhitespaceASCII(value, TRIM_ALL, &value); | 290 TrimWhitespaceASCII(value, TRIM_ALL, &value); |
292 | 291 |
293 if (current_info) { | 292 if (current_info) { |
294 if (key == "Size") { | 293 if (key == "Size") { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir); | 377 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir); |
379 if (dir.length() == 0) { | 378 if (dir.length() == 0) { |
380 DLOG(WARNING) << "Invalid index.theme: blank subdir"; | 379 DLOG(WARNING) << "Invalid index.theme: blank subdir"; |
381 return false; | 380 return false; |
382 } | 381 } |
383 subdirs_[dir] = num++; | 382 subdirs_[dir] = num++; |
384 info_array_.reset(new SubDirInfo[num]); | 383 info_array_.reset(new SubDirInfo[num]); |
385 return true; | 384 return true; |
386 } | 385 } |
387 | 386 |
388 bool CheckDirExistsAndGetMtime(const FilePath& dir, | 387 bool CheckDirExistsAndGetMtime(const FilePath& dir, Time* last_modified) { |
389 base::Time* last_modified) { | |
390 if (!DirectoryExists(dir)) | 388 if (!DirectoryExists(dir)) |
391 return false; | 389 return false; |
392 base::PlatformFileInfo file_info; | 390 PlatformFileInfo file_info; |
393 if (!file_util::GetFileInfo(dir, &file_info)) | 391 if (!GetFileInfo(dir, &file_info)) |
394 return false; | 392 return false; |
395 *last_modified = file_info.last_modified; | 393 *last_modified = file_info.last_modified; |
396 return true; | 394 return true; |
397 } | 395 } |
398 | 396 |
399 // Make sure |dir| exists and add it to the list of icon directories. | 397 // Make sure |dir| exists and add it to the list of icon directories. |
400 void TryAddIconDir(const FilePath& dir) { | 398 void TryAddIconDir(const FilePath& dir) { |
401 base::Time last_modified; | 399 Time last_modified; |
402 if (!CheckDirExistsAndGetMtime(dir, &last_modified)) | 400 if (!CheckDirExistsAndGetMtime(dir, &last_modified)) |
403 return; | 401 return; |
404 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = last_modified; | 402 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = last_modified; |
405 } | 403 } |
406 | 404 |
407 // For a xdg directory |dir|, add the appropriate icon sub-directories. | 405 // For a xdg directory |dir|, add the appropriate icon sub-directories. |
408 void AddXDGDataDir(const FilePath& dir) { | 406 void AddXDGDataDir(const FilePath& dir) { |
409 if (!DirectoryExists(dir)) | 407 if (!DirectoryExists(dir)) |
410 return; | 408 return; |
411 TryAddIconDir(dir.Append("icons")); | 409 TryAddIconDir(dir.Append("icons")); |
(...skipping 30 matching lines...) Expand all Loading... |
442 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos))); | 440 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos))); |
443 pos = epos + 1; | 441 pos = epos + 1; |
444 } | 442 } |
445 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); | 443 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); |
446 } | 444 } |
447 } | 445 } |
448 | 446 |
449 void EnsureUpdated() { | 447 void EnsureUpdated() { |
450 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); | 448 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); |
451 if (constants->last_check_time_.is_null()) { | 449 if (constants->last_check_time_.is_null()) { |
452 constants->last_check_time_ = base::TimeTicks::Now(); | 450 constants->last_check_time_ = TimeTicks::Now(); |
453 InitIconDir(); | 451 InitIconDir(); |
454 return; | 452 return; |
455 } | 453 } |
456 | 454 |
457 // Per xdg theme spec, we should check the icon directories every so often | 455 // Per xdg theme spec, we should check the icon directories every so often |
458 // for newly added icons. | 456 // for newly added icons. |
459 base::TimeDelta time_since_last_check = | 457 TimeDelta time_since_last_check = |
460 base::TimeTicks::Now() - constants->last_check_time_; | 458 TimeTicks::Now() - constants->last_check_time_; |
461 if (time_since_last_check.InSeconds() > constants->kUpdateIntervalInSeconds) { | 459 if (time_since_last_check.InSeconds() > constants->kUpdateIntervalInSeconds) { |
462 constants->last_check_time_ += time_since_last_check; | 460 constants->last_check_time_ += time_since_last_check; |
463 | 461 |
464 bool rescan_icon_dirs = false; | 462 bool rescan_icon_dirs = false; |
465 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_; | 463 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_; |
466 MimeUtilConstants::IconDirMtimeMap::iterator iter; | 464 MimeUtilConstants::IconDirMtimeMap::iterator iter; |
467 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { | 465 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) { |
468 base::Time last_modified; | 466 Time last_modified; |
469 if (!CheckDirExistsAndGetMtime(iter->first, &last_modified) || | 467 if (!CheckDirExistsAndGetMtime(iter->first, &last_modified) || |
470 last_modified != iter->second) { | 468 last_modified != iter->second) { |
471 rescan_icon_dirs = true; | 469 rescan_icon_dirs = true; |
472 break; | 470 break; |
473 } | 471 } |
474 } | 472 } |
475 | 473 |
476 if (rescan_icon_dirs) { | 474 if (rescan_icon_dirs) { |
477 constants->icon_dirs_.clear(); | 475 constants->icon_dirs_.clear(); |
478 constants->icon_themes_.clear(); | 476 constants->icon_themes_.clear(); |
(...skipping 16 matching lines...) Expand all Loading... |
495 } | 493 } |
496 } | 494 } |
497 return FilePath(); | 495 return FilePath(); |
498 } | 496 } |
499 | 497 |
500 // Initialize the list of default themes. | 498 // Initialize the list of default themes. |
501 void InitDefaultThemes() { | 499 void InitDefaultThemes() { |
502 IconTheme** default_themes = | 500 IconTheme** default_themes = |
503 MimeUtilConstants::GetInstance()->default_themes_; | 501 MimeUtilConstants::GetInstance()->default_themes_; |
504 | 502 |
505 scoped_ptr<base::Environment> env(base::Environment::Create()); | 503 scoped_ptr<Environment> env(Environment::Create()); |
506 base::nix::DesktopEnvironment desktop_env = | 504 base::nix::DesktopEnvironment desktop_env = |
507 base::nix::GetDesktopEnvironment(env.get()); | 505 base::nix::GetDesktopEnvironment(env.get()); |
508 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE3 || | 506 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE3 || |
509 desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) { | 507 desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) { |
510 // KDE | 508 // KDE |
511 std::string kde_default_theme; | 509 std::string kde_default_theme; |
512 std::string kde_fallback_theme; | 510 std::string kde_fallback_theme; |
513 | 511 |
514 // TODO(thestig): Figure out how to get the current icon theme on KDE. | 512 // TODO(thestig): Figure out how to get the current icon theme on KDE. |
515 // Setting stored in ~/.kde/share/config/kdeglobals under Icons -> Theme. | 513 // Setting stored in ~/.kde/share/config/kdeglobals under Icons -> Theme. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 MimeUtilConstants::~MimeUtilConstants() { | 568 MimeUtilConstants::~MimeUtilConstants() { |
571 for (size_t i = 0; i < kDefaultThemeNum; i++) | 569 for (size_t i = 0; i < kDefaultThemeNum; i++) |
572 delete default_themes_[i]; | 570 delete default_themes_[i]; |
573 } | 571 } |
574 | 572 |
575 } // namespace | 573 } // namespace |
576 | 574 |
577 std::string GetFileMimeType(const FilePath& filepath) { | 575 std::string GetFileMimeType(const FilePath& filepath) { |
578 if (filepath.empty()) | 576 if (filepath.empty()) |
579 return std::string(); | 577 return std::string(); |
580 base::ThreadRestrictions::AssertIOAllowed(); | 578 ThreadRestrictions::AssertIOAllowed(); |
581 base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); | 579 AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); |
582 return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str()); | 580 return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str()); |
583 } | 581 } |
584 | 582 |
585 std::string GetDataMimeType(const std::string& data) { | 583 std::string GetDataMimeType(const std::string& data) { |
586 base::ThreadRestrictions::AssertIOAllowed(); | 584 ThreadRestrictions::AssertIOAllowed(); |
587 base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); | 585 AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); |
588 return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL); | 586 return xdg_mime_get_mime_type_for_data(data.data(), data.length(), NULL); |
589 } | 587 } |
590 | 588 |
591 void SetIconThemeName(const std::string& name) { | 589 void SetIconThemeName(const std::string& name) { |
592 // If the theme name is already loaded, do nothing. Chrome doesn't respond | 590 // If the theme name is already loaded, do nothing. Chrome doesn't respond |
593 // to changes in the system theme, so we never need to set this more than | 591 // to changes in the system theme, so we never need to set this more than |
594 // once. | 592 // once. |
595 if (!MimeUtilConstants::GetInstance()->icon_theme_name_.empty()) | 593 if (!MimeUtilConstants::GetInstance()->icon_theme_name_.empty()) |
596 return; | 594 return; |
597 | 595 |
598 MimeUtilConstants::GetInstance()->icon_theme_name_ = name; | 596 MimeUtilConstants::GetInstance()->icon_theme_name_ = name; |
599 } | 597 } |
600 | 598 |
601 FilePath GetMimeIcon(const std::string& mime_type, size_t size) { | 599 FilePath GetMimeIcon(const std::string& mime_type, size_t size) { |
602 base::ThreadRestrictions::AssertIOAllowed(); | 600 ThreadRestrictions::AssertIOAllowed(); |
603 std::vector<std::string> icon_names; | 601 std::vector<std::string> icon_names; |
604 std::string icon_name; | 602 std::string icon_name; |
605 FilePath icon_file; | 603 FilePath icon_file; |
606 | 604 |
607 if (!mime_type.empty()) { | 605 if (!mime_type.empty()) { |
608 base::AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); | 606 AutoLock scoped_lock(g_mime_util_xdg_lock.Get()); |
609 const char *icon = xdg_mime_get_icon(mime_type.c_str()); | 607 const char *icon = xdg_mime_get_icon(mime_type.c_str()); |
610 icon_name = std::string(icon ? icon : ""); | 608 icon_name = std::string(icon ? icon : ""); |
611 } | 609 } |
612 | 610 |
613 if (icon_name.length()) | 611 if (icon_name.length()) |
614 icon_names.push_back(icon_name); | 612 icon_names.push_back(icon_name); |
615 | 613 |
616 // For text/plain, try text-plain. | 614 // For text/plain, try text-plain. |
617 icon_name = mime_type; | 615 icon_name = mime_type; |
618 for (size_t i = icon_name.find('/', 0); i != std::string::npos; | 616 for (size_t i = icon_name.find('/', 0); i != std::string::npos; |
(...skipping 27 matching lines...) Expand all Loading... |
646 icon_file = LookupIconInDefaultTheme(icon_names[i], size); | 644 icon_file = LookupIconInDefaultTheme(icon_names[i], size); |
647 if (!icon_file.empty()) | 645 if (!icon_file.empty()) |
648 return icon_file; | 646 return icon_file; |
649 } | 647 } |
650 } | 648 } |
651 return FilePath(); | 649 return FilePath(); |
652 } | 650 } |
653 | 651 |
654 } // namespace nix | 652 } // namespace nix |
655 } // namespace base | 653 } // namespace base |
OLD | NEW |