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

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: 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 <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 #include <sys/time.h>
9 #include <time.h>
10 8
11 #include <cstdlib> 9 #include <cstdlib>
12 #include <list> 10 #include <list>
13 #include <map> 11 #include <map>
14 #include <vector> 12 #include <vector>
15 13
16 #include "base/environment.h" 14 #include "base/environment.h"
17 #include "base/file_util.h" 15 #include "base/file_util.h"
18 #include "base/lazy_instance.h" 16 #include "base/lazy_instance.h"
19 #include "base/logging.h" 17 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/singleton.h" 19 #include "base/memory/singleton.h"
22 #include "base/message_loop.h" 20 #include "base/message_loop.h"
23 #include "base/nix/xdg_util.h" 21 #include "base/nix/xdg_util.h"
24 #include "base/string_split.h" 22 #include "base/string_split.h"
25 #include "base/string_util.h" 23 #include "base/string_util.h"
26 #include "base/synchronization/lock.h" 24 #include "base/synchronization/lock.h"
27 #include "base/third_party/xdg_mime/xdgmime.h" 25 #include "base/third_party/xdg_mime/xdgmime.h"
28 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
27 #include "base/time.h"
29 28
30 namespace { 29 namespace {
31 30
32 // None of the XDG stuff is thread-safe, so serialize all access under 31 // None of the XDG stuff is thread-safe, so serialize all access under
33 // this lock. 32 // this lock.
34 static base::LazyInstance<base::Lock, 33 static base::LazyInstance<base::Lock,
35 base::LeakyLazyInstanceTraits<base::Lock> > 34 base::LeakyLazyInstanceTraits<base::Lock> >
36 g_mime_util_xdg_lock(base::LINKER_INITIALIZED); 35 g_mime_util_xdg_lock(base::LINKER_INITIALIZED);
37 36
38 class IconTheme; 37 class IconTheme;
39 38
40 class MimeUtilConstants { 39 class MimeUtilConstants {
41 public: 40 public:
42 typedef std::map<std::string, IconTheme*> IconThemeMap; 41 typedef std::map<std::string, IconTheme*> IconThemeMap;
43 typedef std::map<FilePath, int> IconDirMtimeMap; 42 typedef std::map<FilePath, base::Time> IconDirMtimeMap;
willchan no longer on Chromium 2011/11/07 21:37:06 Are you sure you don't want TimeTicks instead? The
Lei Zhang 2011/11/11 00:30:11 The time comes from a stat() call. It's always rel
44 typedef std::vector<std::string> IconFormats; 43 typedef std::vector<std::string> IconFormats;
45 44
46 // In seconds, specified by icon theme specs. 45 // Specified by XDG icon theme specs.
47 static const int kUpdateInterval = 5; 46 static const int kUpdateIntervalInSeconds = 5;
48 47
49 static const size_t kDefaultThemeNum = 4; 48 static const size_t kDefaultThemeNum = 4;
50 49
51 static MimeUtilConstants* GetInstance() { 50 static MimeUtilConstants* GetInstance() {
52 return Singleton<MimeUtilConstants>::get(); 51 return Singleton<MimeUtilConstants>::get();
53 } 52 }
54 53
55 // Store icon directories and their mtimes. 54 // Store icon directories and their mtimes.
56 IconDirMtimeMap icon_dirs_; 55 IconDirMtimeMap icon_dirs_;
57 56
58 // Store icon formats. 57 // Store icon formats.
59 IconFormats icon_formats_; 58 IconFormats icon_formats_;
60 59
61 // Store loaded icon_theme. 60 // Store loaded icon_theme.
62 IconThemeMap icon_themes_; 61 IconThemeMap icon_themes_;
63 62
64 // The default theme. 63 // The default theme.
65 IconTheme* default_themes_[kDefaultThemeNum]; 64 IconTheme* default_themes_[kDefaultThemeNum];
66 65
67 time_t last_check_time_; 66 base::Time last_check_time_;
68 67
69 // This is set by DetectGtkTheme(). We cache it so that we can access the 68 // This is set by DetectGtkTheme(). We cache it so that we can access the
70 // theme name from threads that aren't allowed to call 69 // theme name from threads that aren't allowed to call
71 // gtk_settings_get_default(). 70 // gtk_settings_get_default().
72 std::string gtk_theme_name_; 71 std::string gtk_theme_name_;
73 72
74 private: 73 private:
75 MimeUtilConstants() 74 MimeUtilConstants() {
76 : last_check_time_(0) {
77 icon_formats_.push_back(".png"); 75 icon_formats_.push_back(".png");
78 icon_formats_.push_back(".svg"); 76 icon_formats_.push_back(".svg");
79 icon_formats_.push_back(".xpm"); 77 icon_formats_.push_back(".xpm");
80 78
81 for (size_t i = 0; i < kDefaultThemeNum; ++i) 79 for (size_t i = 0; i < kDefaultThemeNum; ++i)
82 default_themes_[i] = NULL; 80 default_themes_[i] = NULL;
83 } 81 }
84 ~MimeUtilConstants(); 82 ~MimeUtilConstants();
85 83
86 friend struct DefaultSingletonTraits<MimeUtilConstants>; 84 friend struct DefaultSingletonTraits<MimeUtilConstants>;
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir); 382 TrimWhitespaceASCII(dirs.substr(pos), TRIM_ALL, &dir);
385 if (dir.length() == 0) { 383 if (dir.length() == 0) {
386 DLOG(WARNING) << "Invalid index.theme: blank subdir"; 384 DLOG(WARNING) << "Invalid index.theme: blank subdir";
387 return false; 385 return false;
388 } 386 }
389 subdirs_[dir] = num++; 387 subdirs_[dir] = num++;
390 info_array_.reset(new SubDirInfo[num]); 388 info_array_.reset(new SubDirInfo[num]);
391 return true; 389 return true;
392 } 390 }
393 391
392 bool CheckDirExistsAndGetMtime(const FilePath& dir,
393 base::Time* last_modified) {
394 if (!file_util::DirectoryExists(dir))
395 return false;
396 base::PlatformFileInfo file_info;
397 if (!file_util::GetFileInfo(dir, &file_info))
398 return false;
399 *last_modified = file_info.last_modified;
400 return true;
401 }
402
394 // Make sure |dir| exists and add it to the list of icon directories. 403 // Make sure |dir| exists and add it to the list of icon directories.
395 void TryAddIconDir(const FilePath& dir) { 404 void TryAddIconDir(const FilePath& dir) {
396 if (!file_util::DirectoryExists(dir)) 405 base::Time last_modified;
406 if (!CheckDirExistsAndGetMtime(dir, &last_modified))
397 return; 407 return;
398 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = 0; 408 MimeUtilConstants::GetInstance()->icon_dirs_[dir] = last_modified;
399 } 409 }
400 410
401 // For a xdg directory |dir|, add the appropriate icon sub-directories. 411 // For a xdg directory |dir|, add the appropriate icon sub-directories.
402 void AddXDGDataDir(const FilePath& dir) { 412 void AddXDGDataDir(const FilePath& dir) {
403 if (!file_util::DirectoryExists(dir)) 413 if (!file_util::DirectoryExists(dir))
404 return; 414 return;
405 TryAddIconDir(dir.Append("icons")); 415 TryAddIconDir(dir.Append("icons"));
406 TryAddIconDir(dir.Append("pixmaps")); 416 TryAddIconDir(dir.Append("pixmaps"));
407 } 417 }
408 418
409 // Add all the xdg icon directories. 419 // Add all the xdg icon directories.
410 void InitIconDir() { 420 void InitIconDir() {
411 MimeUtilConstants::GetInstance()->icon_dirs_.clear();
412 FilePath home = file_util::GetHomeDir(); 421 FilePath home = file_util::GetHomeDir();
413 if (!home.empty()) { 422 if (!home.empty()) {
414 FilePath legacy_data_dir(home); 423 FilePath legacy_data_dir(home);
415 legacy_data_dir = legacy_data_dir.AppendASCII(".icons"); 424 legacy_data_dir = legacy_data_dir.AppendASCII(".icons");
416 if (file_util::DirectoryExists(legacy_data_dir)) 425 if (file_util::DirectoryExists(legacy_data_dir))
417 TryAddIconDir(legacy_data_dir); 426 TryAddIconDir(legacy_data_dir);
418 } 427 }
419 const char* env = getenv("XDG_DATA_HOME"); 428 const char* env = getenv("XDG_DATA_HOME");
420 if (env) { 429 if (env) {
421 AddXDGDataDir(FilePath(env)); 430 AddXDGDataDir(FilePath(env));
(...skipping 12 matching lines...) Expand all
434 std::string xdg_data_dirs = env; 443 std::string xdg_data_dirs = env;
435 std::string::size_type pos = 0, epos; 444 std::string::size_type pos = 0, epos;
436 while ((epos = xdg_data_dirs.find(':', pos)) != std::string::npos) { 445 while ((epos = xdg_data_dirs.find(':', pos)) != std::string::npos) {
437 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos))); 446 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos, epos - pos)));
438 pos = epos + 1; 447 pos = epos + 1;
439 } 448 }
440 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos))); 449 AddXDGDataDir(FilePath(xdg_data_dirs.substr(pos)));
441 } 450 }
442 } 451 }
443 452
444 // Per xdg theme spec, we should check the icon directories every so often for
445 // newly added icons. This isn't quite right.
446 void EnsureUpdated() { 453 void EnsureUpdated() {
447 struct timeval t;
448 gettimeofday(&t, NULL);
449 time_t now = t.tv_sec;
450 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); 454 MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
455 if (constants->last_check_time_.is_null()) {
456 constants->last_check_time_ = base::Time::Now();
457 InitIconDir();
458 return;
459 }
451 460
452 if (constants->last_check_time_ == 0) { 461 // Per xdg theme spec, we should check the icon directories every so often
453 InitIconDir(); 462 // for newly added icons.
454 constants->last_check_time_ = now; 463 base::TimeDelta time_since_last_check =
455 } else { 464 base::Time::Now() - constants->last_check_time_;
456 // TODO(thestig): something changed. start over. Upstream fix to Google 465 if (time_since_last_check.InSeconds() > constants->kUpdateIntervalInSeconds) {
457 // Gadgets for Linux. 466 constants->last_check_time_ += time_since_last_check;
Lei Zhang 2011/11/02 02:02:10 Google Gadgets for Linux is kinda dead at this poi
458 if (now > constants->last_check_time_ + constants->kUpdateInterval) { 467
468 bool rescan_icon_dirs = false;
469 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
470 MimeUtilConstants::IconDirMtimeMap::iterator iter;
471 for (iter = icon_dirs->begin(); iter != icon_dirs->end(); ++iter) {
472 base::Time last_modified;
473 if (!CheckDirExistsAndGetMtime(iter->first, &last_modified) ||
474 last_modified != iter->second) {
475 rescan_icon_dirs = true;
476 break;
477 }
478 }
479
480 if (rescan_icon_dirs) {
481 constants->icon_dirs_.clear();
482 constants->icon_themes_.clear();
Lei Zhang 2011/11/02 02:02:10 Turns out I should clear this too, but it was not
483 InitIconDir();
459 } 484 }
460 } 485 }
461 } 486 }
462 487
463 // Find a fallback icon if we cannot find it in the default theme. 488 // Find a fallback icon if we cannot find it in the default theme.
464 FilePath LookupFallbackIcon(const std::string& icon_name) { 489 FilePath LookupFallbackIcon(const std::string& icon_name) {
465 MimeUtilConstants* constants = MimeUtilConstants::GetInstance(); 490 MimeUtilConstants* constants = MimeUtilConstants::GetInstance();
466 MimeUtilConstants::IconDirMtimeMap::iterator iter; 491 MimeUtilConstants::IconDirMtimeMap::iterator iter;
467 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_; 492 MimeUtilConstants::IconDirMtimeMap* icon_dirs = &constants->icon_dirs_;
468 MimeUtilConstants::IconFormats* icon_formats = &constants->icon_formats_; 493 MimeUtilConstants::IconFormats* icon_formats = &constants->icon_formats_;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 } else { 657 } else {
633 icon_file = LookupIconInDefaultTheme(icon_names[i], size); 658 icon_file = LookupIconInDefaultTheme(icon_names[i], size);
634 if (!icon_file.empty()) 659 if (!icon_file.empty())
635 return icon_file; 660 return icon_file;
636 } 661 }
637 } 662 }
638 return FilePath(); 663 return FilePath();
639 } 664 }
640 665
641 } // namespace mime_util 666 } // 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