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

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

Powered by Google App Engine
This is Rietveld 408576698