Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: base/mime_util_xdg.cc

Issue 8437039: Linux: Periodically check for changes to the icon directories and refresh icons for mime types pe... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 <sys/time.h>
8 #include <time.h>
9 7
10 #include <cstdlib> 8 #include <cstdlib>
11 #include <list> 9 #include <list>
12 #include <map> 10 #include <map>
13 #include <vector> 11 #include <vector>
14 12
15 #include "base/environment.h" 13 #include "base/environment.h"
16 #include "base/file_util.h" 14 #include "base/file_util.h"
17 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
18 #include "base/logging.h" 16 #include "base/logging.h"
19 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
20 #include "base/memory/singleton.h" 18 #include "base/memory/singleton.h"
21 #include "base/message_loop.h" 19 #include "base/message_loop.h"
22 #include "base/nix/xdg_util.h" 20 #include "base/nix/xdg_util.h"
23 #include "base/string_split.h" 21 #include "base/string_split.h"
24 #include "base/string_util.h" 22 #include "base/string_util.h"
25 #include "base/synchronization/lock.h" 23 #include "base/synchronization/lock.h"
26 #include "base/third_party/xdg_mime/xdgmime.h" 24 #include "base/third_party/xdg_mime/xdgmime.h"
27 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
26 #include "base/time.h"
28 27
29 #if defined(TOOLKIT_USES_GTK) 28 #if defined(TOOLKIT_USES_GTK)
30 #include <gtk/gtk.h> 29 #include <gtk/gtk.h>
31 #endif 30 #endif
32 31
33 namespace { 32 namespace {
34 33
35 // None of the XDG stuff is thread-safe, so serialize all access under 34 // None of the XDG stuff is thread-safe, so serialize all access under
36 // this lock. 35 // this lock.
37 static base::LazyInstance<base::Lock, 36 static base::LazyInstance<base::Lock,
38 base::LeakyLazyInstanceTraits<base::Lock> > 37 base::LeakyLazyInstanceTraits<base::Lock> >
39 g_mime_util_xdg_lock(base::LINKER_INITIALIZED); 38 g_mime_util_xdg_lock(base::LINKER_INITIALIZED);
40 39
41 class IconTheme; 40 class IconTheme;
42 41
43 class MimeUtilConstants { 42 class MimeUtilConstants {
44 public: 43 public:
45 typedef std::map<std::string, IconTheme*> IconThemeMap; 44 typedef std::map<std::string, IconTheme*> IconThemeMap;
46 typedef std::map<FilePath, int> IconDirMtimeMap; 45 typedef std::map<FilePath, base::Time> IconDirMtimeMap;
47 typedef std::vector<std::string> IconFormats; 46 typedef std::vector<std::string> IconFormats;
48 47
49 // In seconds, specified by icon theme specs. 48 // Specified by XDG icon theme specs.
50 static const int kUpdateInterval = 5; 49 static const int kUpdateIntervalInSeconds = 5;
51 50
52 static const size_t kDefaultThemeNum = 4; 51 static const size_t kDefaultThemeNum = 4;
53 52
54 static MimeUtilConstants* GetInstance() { 53 static MimeUtilConstants* GetInstance() {
55 return Singleton<MimeUtilConstants>::get(); 54 return Singleton<MimeUtilConstants>::get();
56 } 55 }
57 56
58 // Store icon directories and their mtimes. 57 // Store icon directories and their mtimes.
59 IconDirMtimeMap icon_dirs_; 58 IconDirMtimeMap icon_dirs_;
60 59
61 // Store icon formats. 60 // Store icon formats.
62 IconFormats icon_formats_; 61 IconFormats icon_formats_;
63 62
64 // Store loaded icon_theme. 63 // Store loaded icon_theme.
65 IconThemeMap icon_themes_; 64 IconThemeMap icon_themes_;
66 65
67 // The default theme. 66 // The default theme.
68 IconTheme* default_themes_[kDefaultThemeNum]; 67 IconTheme* default_themes_[kDefaultThemeNum];
69 68
70 time_t last_check_time_; 69 base::TimeTicks last_check_time_;
71 70
72 #if defined(TOOLKIT_USES_GTK) 71 #if defined(TOOLKIT_USES_GTK)
73 // This is set by DetectGtkTheme(). We cache it so that we can access the 72 // This is set by DetectGtkTheme(). We cache it so that we can access the
74 // theme name from threads that aren't allowed to call 73 // theme name from threads that aren't allowed to call
75 // gtk_settings_get_default(). 74 // gtk_settings_get_default().
76 std::string gtk_theme_name_; 75 std::string gtk_theme_name_;
77 #endif 76 #endif
78 77
79 private: 78 private:
80 MimeUtilConstants() 79 MimeUtilConstants() {
81 : last_check_time_(0) {
82 icon_formats_.push_back(".png"); 80 icon_formats_.push_back(".png");
83 icon_formats_.push_back(".svg"); 81 icon_formats_.push_back(".svg");
84 icon_formats_.push_back(".xpm"); 82 icon_formats_.push_back(".xpm");
85 83
86 for (size_t i = 0; i < kDefaultThemeNum; ++i) 84 for (size_t i = 0; i < kDefaultThemeNum; ++i)
87 default_themes_[i] = NULL; 85 default_themes_[i] = NULL;
88 } 86 }
89 ~MimeUtilConstants(); 87 ~MimeUtilConstants();
90 88
91 friend struct DefaultSingletonTraits<MimeUtilConstants>; 89 friend struct DefaultSingletonTraits<MimeUtilConstants>;
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir); 387 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir);
390 if (dir.length() == 0) { 388 if (dir.length() == 0) {
391 DLOG(WARNING) << "Invalid index.theme: blank subdir"; 389 DLOG(WARNING) << "Invalid index.theme: blank subdir";
392 return false; 390 return false;
393 } 391 }
394 subdirs_[dir] = num++; 392 subdirs_[dir] = num++;
395 info_array_.reset(new SubDirInfo[num]); 393 info_array_.reset(new SubDirInfo[num]);
396 return true; 394 return true;
397 } 395 }
398 396
397 bool CheckDirExistsAndGetMtime(const FilePath& dir,
398 base::Time* last_modified) {
399 if (!file_util::DirectoryExists(dir))
400 return false;
401 base::PlatformFileInfo file_info;
402 if (!file_util::GetFileInfo(dir, &file_info))
403 return false;
404 *last_modified = file_info.last_modified;
405 return true;
406 }
407
399 // Make sure |dir| exists and add it to the list of icon directories. 408 // Make sure |dir| exists and add it to the list of icon directories.
400 void TryAddIconDir(const FilePath& dir) { 409 void TryAddIconDir(const FilePath& dir) {
401 if (!file_util::DirectoryExists(dir)) 410 base::Time last_modified;
411 if (!CheckDirExistsAndGetMtime(dir, &last_modified))
402 return; 412 return;
403 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = 0; 413 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = last_modified;
404 } 414 }
405 415
406 // For a xdg directory |dir|, add the appropriate icon sub-directories. 416 // For a xdg directory |dir|, add the appropriate icon sub-directories.
407 void AddXDGDataDir(const FilePath& dir) { 417 void AddXDGDataDir(const FilePath& dir) {
408 if (!file_util::DirectoryExists(dir)) 418 if (!file_util::DirectoryExists(dir))
409 return; 419 return;
410 TryAddIconDir(dir.Append("icons")); 420 TryAddIconDir(dir.Append("icons"));
411 TryAddIconDir(dir.Append("pixmaps")); 421 TryAddIconDir(dir.Append("pixmaps"));
412 } 422 }
413 423
414 // Add all the xdg icon directories. 424 // Add all the xdg icon directories.
415 void InitIconDir() { 425 void InitIconDir() {
416 MimeUtilConstants::GetInstance()->icon_dirs_.clear();
417 FilePath home = file_util::GetHomeDir(); 426 FilePath home = file_util::GetHomeDir();
418 if (!home.empty()) { 427 if (!home.empty()) {
419 FilePath legacy_data_dir(home); 428 FilePath legacy_data_dir(home);
420 legacy_data_dir = legacy_data_dir.AppendASCII(".icons"); 429 legacy_data_dir = legacy_data_dir.AppendASCII(".icons");
421 if (file_util::DirectoryExists(legacy_data_dir)) 430 if (file_util::DirectoryExists(legacy_data_dir))
422 TryAddIconDir(legacy_data_dir); 431 TryAddIconDir(legacy_data_dir);
423 } 432 }
424 const char* env = getenv("XDG_DATA_HOME"); 433 const char* env = getenv("XDG_DATA_HOME");
425 if (env) { 434 if (env) {
426 AddXDGDataDir(FilePath(env)); 435 AddXDGDataDir(FilePath(env));
(...skipping 12 matching lines...) Expand all
439 std::string xdg_data_dirs = env; 448 std::string xdg_data_dirs = env;
440 std::string::size_type pos = 0, epos; 449 std::string::size_type pos = 0, epos;
441 while ((epos = xdg_data_dirs.find(':', pos)) != std::string::npos) { 450 while ((epos = xdg_data_dirs.find(':', pos)) != std::string::npos) {
442 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos))); 451 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos)));
443 pos = epos + 1; 452 pos = epos + 1;
444 } 453 }
445 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); 454 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos)));
446 } 455 }
447 } 456 }
448 457
449 // Per xdg theme spec, we should check the icon directories every so often for
450 // newly added icons. This isn't quite right.
451 void EnsureUpdated() { 458 void EnsureUpdated() {
452 struct timeval t;
453 gettimeofday(&t, NULL);
454 time_t now = t.tv_sec;
455 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); 459 MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
460 if (constants->last_check_time_.is_null()) {
461 constants->last_check_time_ = base::TimeTicks::Now();
462 InitIconDir();
463 return;
464 }
456 465
457 if (constants->last_check_time_ == 0) { 466 // Per xdg theme spec, we should check the icon directories every so often
458 InitIconDir(); 467 // for newly added icons.
459 constants->last_check_time_ = now; 468 base::TimeDelta time_since_last_check =
460 } else { 469 base::TimeTicks::Now() - constants->last_check_time_;
461 // TODO(thestig): something changed. start over. Upstream fix to Google 470 if (time_since_last_check.InSeconds() > constants->kUpdateIntervalInSeconds) {
462 // Gadgets for Linux. 471 constants->last_check_time_ += time_since_last_check;
463 if (now > constants->last_check_time_ + constants->kUpdateInterval) { 472
473 bool rescan_icon_dirs = false;
474 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
475 MimeUtilConstants::IconDirMtimeMap::iterator iter;
476 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
477 base::Time last_modified;
478 if (!CheckDirExistsAndGetMtime(iter->first, &last_modified) ||
479 last_modified != iter->second) {
480 rescan_icon_dirs = true;
481 break;
482 }
483 }
484
485 if (rescan_icon_dirs) {
486 constants->icon_dirs_.clear();
487 constants->icon_themes_.clear();
488 InitIconDir();
464 } 489 }
465 } 490 }
466 } 491 }
467 492
468 // Find a fallback icon if we cannot find it in the default theme. 493 // Find a fallback icon if we cannot find it in the default theme.
469 FilePath LookupFallbackIcon(const std::string& icon_name) { 494 FilePath LookupFallbackIcon(const std::string& icon_name) {
470 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); 495 MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
471 MimeUtilConstants::IconDirMtimeMap::iterator iter; 496 MimeUtilConstants::IconDirMtimeMap::iterator iter;
472 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_; 497 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
473 MimeUtilConstants::IconFormats* icon_formats = &constants->icon_formats_; 498 MimeUtilConstants::IconFormats* icon_formats = &constants->icon_formats_;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 } else { 666 } else {
642 icon_file = LookupIconInDefaultTheme(icon_names[i], size); 667 icon_file = LookupIconInDefaultTheme(icon_names[i], size);
643 if (!icon_file.empty()) 668 if (!icon_file.empty())
644 return icon_file; 669 return icon_file;
645 } 670 }
646 } 671 }
647 return FilePath(); 672 return FilePath();
648 } 673 }
649 674
650 } // namespace mime_util 675 } // namespace mime_util
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698