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

Side by Side Diff: services/authentication/accounts_db_manager.cc

Issue 1466733002: Google OAuth Device Flow support for FNL (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Updated comments for authentication.mojom Created 5 years 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 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 "services/authentication/accounts_db_manager.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/strings/string_tokenizer.h"
11 #include "mojo/public/cpp/bindings/array.h"
12 #include "mojo/public/cpp/bindings/type_converter.h"
13 #include "mojo/services/files/interfaces/files.mojom.h"
14
15 namespace authentication {
16
17 const char* kAccountsDbFileName = "accounts_db.txt";
18
19 AccountsDbManager::AccountsDbManager()
20 : directory_(nullptr), contents_(nullptr) {}
21
22 AccountsDbManager::AccountsDbManager(mojo::files::FilesPtr files) {
23 // TODO: Move to a file system with secure privileges as the accounts db needs
24 // to persist across multiple invocations and apps, and the temporary root
25 // solution here is just a short term path.
26 mojo::files::Error error = mojo::files::Error::INTERNAL;
27 files->OpenFileSystem(nullptr, GetProxy(&directory_), Capture(&error));
viettrungluu 2015/12/18 20:59:49 I don't think you should block the thread (and eve
ukode 2016/01/06 23:52:59 Good point. Made the change.
28 files.WaitForIncomingResponse();
29 if (mojo::files::Error::OK != error) {
30 LOG(FATAL) << "Unable to initialize accounts DB";
31 }
32 }
33
34 AccountsDbManager::~AccountsDbManager() {}
35
36 void AccountsDbManager::GetUpdatedDbContents(
37 const mojo::String& username,
38 const mojo::String& new_account_data,
39 const bool user_exists,
40 mojo::String& new_db_contents) {
41 if (username.is_null() || new_account_data.is_null()) {
42 return;
43 }
44 std::string buffer;
45 if (user_exists) {
46 // Account identified as new user, add a fresh record for this user in
47 // accounts DB in Append mode.
48 if (!AccountsDbManager::contents_.empty()) {
49 buffer += "\n";
50 }
51 buffer += new_account_data;
52 } else {
53 // Existing user account, replace the credentials/tokens to newly
54 // generated auth tokens in-place.
55 base::StringTokenizer lines(AccountsDbManager::contents_, "\n");
56 std::string user_record;
57 while (lines.GetNext()) {
58 user_record = lines.token();
59 if (!new_db_contents.is_null() || !user_record.empty()) {
60 buffer += "\n";
61 }
62 if (user_record.find(username) != std::string::npos) {
63 buffer += new_account_data; // replace with new auth data
64 } else {
65 buffer += user_record;
66 }
67 }
68 }
69
70 new_db_contents = buffer;
71 return;
72 }
73
74 bool AccountsDbManager::UpdateAccount(const mojo::String& username,
75 const mojo::String& new_account_data) {
76 if (username.is_null() || new_account_data.is_null()) {
77 return false;
78 }
79 mojo::String existing_user_data;
80 AccountsDbManager::GetAccountDataForUser(username, existing_user_data);
81 mojo::String new_db_contents;
82 GetUpdatedDbContents(username, new_account_data, existing_user_data.is_null(),
83 new_db_contents);
84 if (new_db_contents.is_null()) {
85 return false;
86 }
87
88 // Open accounts db file
89 mojo::files::FilePtr file;
90 mojo::files::Error error = mojo::files::Error::INTERNAL;
91 bool write_failed = false;
92 if (existing_user_data.is_null()) {
93 // Append to existing file
94 directory_->OpenFile(kAccountsDbFileName, GetProxy(&file),
95 mojo::files::kOpenFlagWrite |
96 mojo::files::kOpenFlagCreate |
97 mojo::files::kOpenFlagAppend,
98 Capture(&error));
viettrungluu 2015/12/18 20:59:49 In general, you shouldn't do synchronous I/O (i.e.
ukode 2016/01/06 23:52:59 Moved the opening and closing files to ctor and dt
99 } else {
100 // Rewrite the file contents with updated info
101 directory_->OpenFile(
102 kAccountsDbFileName, GetProxy(&file),
103 mojo::files::kOpenFlagWrite | mojo::files::kOpenFlagCreate,
104 Capture(&error));
105 }
106 directory_.WaitForIncomingResponse();
107 if (mojo::files::Error::OK != error) {
108 write_failed = true;
109 } else {
110 // Write to it.
111 std::vector<uint8_t> bytes_to_write(new_db_contents.get().begin(),
112 new_db_contents.get().end());
113 bytes_to_write.push_back('\0');
114 error = mojo::files::Error::INTERNAL;
115 uint32_t num_bytes_written = 0;
116 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
117 mojo::files::Whence::FROM_CURRENT,
118 Capture(&error, &num_bytes_written));
119 file.WaitForIncomingResponse();
120
121 if (mojo::files::Error::OK != error) {
122 write_failed = true;
123 }
124 }
125
126 // Close the accounts db file
127 error = mojo::files::Error::INTERNAL;
128 file->Close(Capture(&error));
129 file.WaitForIncomingResponse();
130 if (mojo::files::Error::OK != error) {
131 return false;
132 }
133
134 if (write_failed) {
135 return false;
136 }
137
138 // Update the existing contents with new data
139 AccountsDbManager::contents_.assign(new_db_contents.data(),
140 new_db_contents.size());
141 return true;
142 }
143
144 void AccountsDbManager::GetAccountDataForUser(const mojo::String& username,
145 mojo::String& user_data) {
146 if (username.is_null()) {
147 return;
148 }
149
150 if (AccountsDbManager::contents_.empty()) {
151 mojo::Array<uint8_t> all_accounts_data(
152 AccountsDbManager::FetchAllAccounts());
153 if (!all_accounts_data.size()) {
154 return;
155 }
156 }
157
158 base::StringTokenizer lines(AccountsDbManager::contents_, "\n");
159 std::string entry;
160 while (lines.GetNext()) {
161 entry = lines.token();
162 if (entry.find(username) != std::string::npos) {
163 user_data.Swap(&entry);
164 return;
165 }
166 }
167 }
168
169 mojo::Array<uint8_t> AccountsDbManager::FetchAllAccounts() {
170 const size_t kMaxReadSize = 1 * 1024 * 1024;
171 bool read_failed = false;
172 mojo::Array<uint8_t> bytes_read;
173
174 // Open accounts db file
175 mojo::files::FilePtr file;
176 mojo::files::Error error = mojo::files::Error::INTERNAL;
177 directory_->OpenFile(kAccountsDbFileName, GetProxy(&file),
178 mojo::files::kOpenFlagRead, Capture(&error));
179 directory_.WaitForIncomingResponse();
180 if (mojo::files::Error::OK != error) {
181 read_failed = true;
182 } else {
183 // Read from it.
184 error = mojo::files::Error::INTERNAL;
185 file->Read(kMaxReadSize - 1, 0, mojo::files::Whence::FROM_START,
186 Capture(&error, &bytes_read));
187
188 file.WaitForIncomingResponse();
189 if (mojo::files::Error::OK != error) {
190 read_failed = true;
191 }
192 }
193
194 // Close the accounts db file
195 error = mojo::files::Error::INTERNAL;
196 file->Close(Capture(&error));
197 file.WaitForIncomingResponse();
198 if (mojo::files::Error::OK != error) {
199 return mojo::Array<uint8_t>();
200 }
201
202 if (read_failed) {
203 return mojo::Array<uint8_t>();
204 }
205
206 const std::vector<uint8_t> vec = bytes_read.storage();
207 AccountsDbManager::contents_.assign((char*)vec.data(), vec.size());
208
209 return bytes_read.Pass();
210 }
211
212 } // namespace authentication
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698