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

Side by Side Diff: device/time_zone_monitor/time_zone_monitor_linux.cc

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

Powered by Google App Engine
This is Rietveld 408576698