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

Side by Side Diff: content/browser/time_zone_monitor_linux.cc

Issue 251613002: Broadcast NotifyTimezoneChange to all RenderProcessHosts when the system time zone changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months 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
OLDNEW
(Empty)
1 // Copyright 2014 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 #include "content/browser/time_zone_monitor.h"
6
7 #include <stdlib.h>
8
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_path_watcher.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/stl_util.h"
17 #include "content/public/browser/browser_thread.h"
18
19 #if !defined(OS_CHROMEOS)
20
21 namespace content {
22
23 namespace {
24 class TimeZoneMonitorLinuxImpl;
25 } // namespace
26
27 class TimeZoneMonitorLinux : public TimeZoneMonitor {
28 public:
29 TimeZoneMonitorLinux();
30 virtual ~TimeZoneMonitorLinux();
31
32 void NotifyRenderersFromImpl() {
33 NotifyRenderers();
34 }
35
36 private:
37 scoped_refptr<TimeZoneMonitorLinuxImpl> impl_;
38
39 DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorLinux);
40 };
41
42 namespace {
43
44 // FilePathWatcher needs to run on the FILE thread, but TimeZoneMonitor runs
45 // on the UI thread. TimeZoneMonitorLinuxImpl is the bridge between these
46 // threads.
47 class TimeZoneMonitorLinuxImpl
48 : public base::RefCountedThreadSafe<TimeZoneMonitorLinuxImpl> {
49 public:
50 explicit TimeZoneMonitorLinuxImpl(TimeZoneMonitorLinux* owner)
51 : base::RefCountedThreadSafe<TimeZoneMonitorLinuxImpl>(),
52 file_path_watchers_(),
53 owner_(owner) {
54 BrowserThread::PostTask(
55 BrowserThread::FILE,
56 FROM_HERE,
57 base::Bind(&TimeZoneMonitorLinuxImpl::StartWatchingOnFileThread, this));
58 }
59
60 void StopWatching() {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62 owner_ = NULL;
63 BrowserThread::PostTask(
64 BrowserThread::FILE,
65 FROM_HERE,
66 base::Bind(&TimeZoneMonitorLinuxImpl::StopWatchingOnFileThread, this));
67 }
68
69 private:
70 friend class base::RefCountedThreadSafe<TimeZoneMonitorLinuxImpl>;
71
72 ~TimeZoneMonitorLinuxImpl() {
73 DCHECK(!owner_);
74 STLDeleteElements(&file_path_watchers_);
75 }
76
77 void StartWatchingOnFileThread() {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
79
80 // There is no true standard for where time zone information is actually
81 // stored. glibc uses /etc/localtime, uClibc uses /etc/TZ, and some older
82 // systems store the name of the time zone file within /usr/share/zoneinfo
83 // in /etc/timezone. Different libraries and custom builds may mean that
84 // still more paths are used. Just watch all three of these paths, because
85 // false positives are harmless, assuming the false positive rate is
86 // reasonable.
87 const char* kFilesToWatch[] = {
88 "/etc/localtime",
89 "/etc/timezone",
90 "/etc/TZ",
91 };
92
93 for (size_t index = 0; index < arraysize(kFilesToWatch); ++index) {
94 file_path_watchers_.push_back(new base::FilePathWatcher());
95 file_path_watchers_.back()->Watch(
96 base::FilePath(kFilesToWatch[index]),
97 false,
98 base::Bind(&TimeZoneMonitorLinuxImpl::OnTimeZoneFileChanged, this));
99 }
100 }
101
102 void StopWatchingOnFileThread() {
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
104 STLDeleteElements(&file_path_watchers_);
105 }
106
107 void OnTimeZoneFileChanged(const base::FilePath& path, bool error) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
109 BrowserThread::PostTask(
110 BrowserThread::UI,
111 FROM_HERE,
112 base::Bind(&TimeZoneMonitorLinuxImpl::OnTimeZoneFileChangedOnUIThread,
113 this));
114 }
115
116 void OnTimeZoneFileChangedOnUIThread() {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118 if (owner_) {
119 owner_->NotifyRenderersFromImpl();
120 }
121 }
122
123 std::vector<base::FilePathWatcher*> file_path_watchers_;
124 TimeZoneMonitorLinux* owner_;
125
126 DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorLinuxImpl);
127 };
128
129 } // namespace
130
131 TimeZoneMonitorLinux::TimeZoneMonitorLinux()
132 : TimeZoneMonitor(),
133 impl_() {
134 // If the TZ environment variable is set, its value specifies the time zone
135 // specification, and it's pointless to monitor any files in /etc for
136 // changes because such changes would have no effect on the TZ environment
137 // variable and thus the interpretation of the local time zone in the
138 // or renderer processes.
139 //
140 // The system-specific format for the TZ environment variable beginning with
141 // a colon is implemented by glibc as the path to a time zone data file, and
142 // it would be possible to monitor this file for changes if a TZ variable of
143 // this format was encountered, but this is not necessary: when loading a
144 // time zone specification in this way, glibc does not reload the file when
145 // it changes, so it's pointless to respond to a notification that it has
146 // changed.
147 if (!getenv("TZ")) {
148 impl_ = new TimeZoneMonitorLinuxImpl(this);
149 }
150 }
151
152 TimeZoneMonitorLinux::~TimeZoneMonitorLinux() {
153 if (impl_) {
154 impl_->StopWatching();
155 }
156 }
157
158 // static
159 scoped_ptr<TimeZoneMonitor> TimeZoneMonitor::Create() {
160 return scoped_ptr<TimeZoneMonitor>(new TimeZoneMonitorLinux());
161 }
162
163 } // namespace content
164
165 #endif // !OS_CHROMEOS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698