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

Side by Side Diff: client/settings.cc

Issue 988063003: Define the Settings interface for a CrashReportDatabase and provide a Mac implementation. (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Drop plist, use binary Created 5 years, 9 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 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "client/settings.h"
16
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <uuid/uuid.h>
20
21 #include "base/logging.h"
22 #include "base/posix/eintr_wrapper.h"
23
24 namespace crashpad {
25
26 namespace {
27
28 const uint16_t kSettingsVersion = 1;
Mark Mentovai 2015/03/09 19:12:36 Why not make this a static const inside Settings::
Robert Sesek 2015/03/09 21:16:27 Done.
29
30 } // namespace
31
32 struct Settings::Data {
33 Data() : version(kSettingsVersion),
34 client_id(),
35 uploads_enabled(false),
36 last_upload_attempt_time(0) {}
37
38 uint16_t version;
Mark Mentovai 2015/03/09 19:12:36 Revise the struct order for better packing, to ens
Robert Sesek 2015/03/09 21:16:27 Done.
39 UUID client_id;
40 bool uploads_enabled;
41 time_t last_upload_attempt_time;
Mark Mentovai 2015/03/09 19:12:35 time_t has a variable size in 32-bit and 64-bit en
Robert Sesek 2015/03/09 21:16:27 Done.
42 };
43
44 Settings::Settings(const base::FilePath& file_path)
45 : file_path_(file_path) {
46 }
47
48 Settings::~Settings() {
49 }
50
51 bool Settings::Initialize() {
Mark Mentovai 2015/03/09 19:12:35 InitializationStateDcheck here and in public entry
Robert Sesek 2015/03/09 21:16:27 I think that clutters up Initialize more than it h
Mark Mentovai 2015/03/09 22:00:57 Robert Sesek wrote:
Robert Sesek 2015/03/09 22:11:00 Sure, but it means not being able to return the re
Mark Mentovai 2015/03/09 22:26:29 Robert Sesek wrote:
52 ScopedFileHandle handle(HANDLE_EINTR(
53 open(file_path(),
54 O_CREAT | O_EXCL | O_WRONLY | O_EXLOCK,
55 0644)));
56
57 // The file was created, so this is a new database that needs to be
58 // initialized with a client ID.
59 if (handle.is_valid()) {
60 return InitializeSettings(handle.get());
61 }
62
63 // The file wasn't created, try opening it for a write operation.
Mark Mentovai 2015/03/09 19:12:36 Since you only do a read in most cases, say in the
Robert Sesek 2015/03/09 21:16:27 Done.
64 handle.reset(OpenForWriting().release());
65 if (!handle.is_valid()) {
66 return false;
67 }
68
69 // Ensure that the file is valid. If it fails to read, re-initialize the
70 // settings.
71 Data settings;
72 if (!ReadSettings(handle.get(), &settings)) {
73 return RecoverSettings(handle.get(), &settings);
74 }
75
76 return true;
77 }
78
79 bool Settings::GetClientID(UUID* client_id) {
80 Data settings;
81 if (!OpenAndReadSettings(&settings)) {
82 return false;
83 }
84
85 *client_id = settings.client_id;
86 return true;
87 }
88
89 bool Settings::GetUploadsEnabled(bool* enabled) {
90 Data settings;
91 if (!OpenAndReadSettings(&settings)) {
92 return false;
93 }
94
95 *enabled = settings.uploads_enabled;
96 return true;
97 }
98
99 bool Settings::SetUploadsEnabled(bool enabled) {
100 ScopedFileHandle handle = OpenForWriting();
101 if (!handle.is_valid())
102 return false;
103
104 Data settings;
105 if (!ReadSettings(handle.get(), &settings)) {
106 if (!RecoverSettings(handle.get(), &settings))
107 return false;
108 }
109
110 settings.uploads_enabled = enabled;
111
112 return WriteSettings(handle.get(), &settings);
113 }
114
115 bool Settings::GetLastUploadAttemptTime(time_t* time) {
116 Data settings;
117 if (!OpenAndReadSettings(&settings))
118 return false;
119
120 *time = settings.last_upload_attempt_time;
121 return true;
122 }
123
124 bool Settings::SetLastUploadAttemptTime(time_t time) {
125 ScopedFileHandle handle = OpenForWriting();
Mark Mentovai 2015/03/09 19:12:35 The bulk of this function is identical to SetUploa
Robert Sesek 2015/03/09 21:16:27 Done.
126 if (!handle.is_valid())
127 return false;
128
129 Data settings;
130 if (!ReadSettings(handle.get(), &settings)) {
131 if (!RecoverSettings(handle.get(), &settings))
132 return false;
133 }
134
135 settings.last_upload_attempt_time = time;
136
137 return WriteSettings(handle.get(), &settings);
138 }
139
140 ScopedFileHandle Settings::OpenForReading() {
141 ScopedFileHandle handle(HANDLE_EINTR(open(file_path(), O_RDONLY | O_SHLOCK)));
142 PLOG_IF(ERROR, !handle.is_valid()) << "open for reading";
143 return handle.Pass();
144 }
145
146 ScopedFileHandle Settings::OpenForWriting() {
147 ScopedFileHandle handle(HANDLE_EINTR(open(file_path(), O_RDWR | O_EXLOCK)));
Mark Mentovai 2015/03/09 19:12:36 Add O_CREAT so that we can recover when the file g
Robert Sesek 2015/03/09 21:16:27 Done.
148 PLOG_IF(ERROR, !handle.is_valid()) << "open for writing";
149 return handle.Pass();
150 }
151
152 bool Settings::OpenAndReadSettings(Data* out_data) {
153 ScopedFileHandle handle = OpenForReading();
154 if (!handle.is_valid())
155 return false;
156
157 if (ReadSettings(handle.get(), out_data))
158 return true;
159
160 // The settings file is corrupt, so reinitialize it.
161 handle.reset();
162
163 // The settings failed to be read, so re-initialize them.
164 return RecoverSettings(kInvalidFileHandle, out_data);
165 }
166
167 bool Settings::ReadSettings(FileHandle handle, Data* out_data) {
168 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
169 return false;
170
171 if (!LoggingReadFile(handle, out_data, sizeof(*out_data)))
172 return false;
173
174 if (out_data->version != kSettingsVersion) {
175 LOG(ERROR) << "Settings version is not " << kSettingsVersion;
176 return false;
177 }
178
179 return true;
180 }
181
182 bool Settings::WriteSettings(FileHandle handle, const Data* data) {
183 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
184 return false;
185
186 if (HANDLE_EINTR(ftruncate(handle, 0)) != 0) {
187 PLOG(ERROR) << "ftruncate settings file";
188 return false;
189 }
190
191 return LoggingWriteFile(handle, data, sizeof(*data));
192 }
193
194 bool Settings::RecoverSettings(FileHandle handle, Data* out_data) {
195 LOG(INFO) << "Recovering settings file " << file_path();
196
197 ScopedFileHandle scoped_handle;
198 if (handle == kInvalidFileHandle) {
199 scoped_handle.reset(OpenForWriting().release());
Mark Mentovai 2015/03/09 19:12:35 If you open the handle yourself here, you need to
Robert Sesek 2015/03/09 21:16:27 Done.
200 handle = scoped_handle.get();
201 }
202
203 if (handle == kInvalidFileHandle) {
204 LOG(ERROR) << "Invalid file handle";
205 return false;
206 }
207
208 if (!InitializeSettings(handle))
Mark Mentovai 2015/03/09 19:12:35 You can make InitializeSettings() accept a Data* o
Robert Sesek 2015/03/09 21:16:27 It would be unnecessary to do that for the other c
209 return false;
210
211 return ReadSettings(handle, out_data);
212 }
213
214 bool Settings::InitializeSettings(FileHandle handle) {
215 uuid_t uuid;
216 uuid_generate(uuid);
217
218 Data settings;
219 settings.client_id.InitializeFromBytes(uuid);
220
221 return WriteSettings(handle, &settings);
222 }
223
224 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698