OLD | NEW |
---|---|
(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"; | |
viettrungluu
2016/01/11 21:23:44
nit: This isn't as const as you think it is. You p
ukode
2016/02/09 00:20:17
Thanks for the tip. Done.
| |
18 | |
19 AccountsDbManager::AccountsDbManager() : file_(nullptr), contents_(nullptr) {} | |
20 | |
21 AccountsDbManager::AccountsDbManager(mojo::files::DirectoryPtr& directory) { | |
viettrungluu
2016/01/11 21:23:45
Depending on how this is used, this should either
ukode
2016/02/09 00:20:17
Done.
| |
22 // Open accounts db file | |
23 mojo::files::Error error = mojo::files::Error::INTERNAL; | |
24 directory.Pass()->OpenFile(kAccountsDbFileName, GetProxy(&file_), | |
viettrungluu
2016/01/11 21:23:44
No |.Pass()| here.
ukode
2016/02/09 00:20:17
Done.
| |
25 mojo::files::kOpenFlagCreate | | |
26 mojo::files::kOpenFlagRead | | |
27 mojo::files::kOpenFlagWrite, | |
28 Capture(&error)); | |
29 directory.WaitForIncomingResponse(); | |
viettrungluu
2016/01/11 21:23:44
Instead of waiting for the response (esp. since yo
ukode
2016/02/09 00:20:17
Done.
| |
30 if (mojo::files::Error::OK != error) { | |
31 LOG(FATAL) << "Not able to open accounts database file."; | |
32 } | |
33 } | |
34 | |
35 AccountsDbManager::~AccountsDbManager() { | |
36 // Close the accounts db file | |
37 mojo::files::Error error = mojo::files::Error::INTERNAL; | |
38 file_->Close(Capture(&error)); | |
39 file_.WaitForIncomingResponse(); | |
viettrungluu
2016/01/11 21:23:45
Ditto here. Note that closing the file is optional
ukode
2016/02/09 00:20:17
Ok,removing the file close functionality for now.
| |
40 if (mojo::files::Error::OK != error) { | |
41 LOG(FATAL) << "Not able to close accounts database file."; | |
42 } | |
43 } | |
44 | |
45 void AccountsDbManager::GetUpdatedDbContents( | |
46 const mojo::String& username, | |
47 const mojo::String& new_account_data, | |
48 bool user_exists, | |
49 mojo::String& new_db_contents) { | |
viettrungluu
2016/01/11 21:23:44
For this method, you should probably just return a
ukode
2016/02/09 00:20:18
Done.
| |
50 if (username.is_null() || new_account_data.is_null()) { | |
51 return; | |
52 } | |
53 std::string buffer; | |
54 if (user_exists) { | |
55 // Remove existing user record | |
56 base::StringTokenizer lines(AccountsDbManager::contents_, "\n"); | |
viettrungluu
2016/01/11 21:23:44
(Here and below....) |AccountsDbManager::| not nee
ukode
2016/02/09 00:20:18
Done.
| |
57 std::string user_record; | |
58 while (lines.GetNext()) { | |
59 user_record = lines.token(); | |
60 if (user_record.find(username) == std::string::npos) { | |
viettrungluu
2016/01/11 21:23:44
What's the format of contents_? Does this properly
ukode
2016/02/09 00:20:17
Good catch. Added necessary checks and removed fil
| |
61 buffer += user_record; | |
62 buffer += "\n"; | |
63 } | |
64 } | |
65 } else { | |
66 if (!AccountsDbManager::contents_.empty()) { // first account | |
67 buffer += "\n"; | |
viettrungluu
2016/01/11 21:23:45
Why is this needed? (It results in |buffer| beginn
ukode
2016/02/09 00:20:17
This is the line separator between records in the
| |
68 } | |
69 } | |
70 buffer += new_account_data; | |
71 new_db_contents = buffer; | |
72 return; | |
viettrungluu
2016/01/11 21:23:44
nit: no |return| needed here
ukode
2016/02/09 00:20:17
Done.
| |
73 } | |
74 | |
75 bool AccountsDbManager::UpdateAccount(const mojo::String& username, | |
76 const mojo::String& new_account_data) { | |
77 if (username.is_null() || new_account_data.is_null()) { | |
78 return false; | |
79 } | |
80 bool user_exists = | |
81 (AccountsDbManager::contents_.find(username) != std::string::npos) | |
82 ? true | |
viettrungluu
2016/01/11 21:23:44
|? true : false| is unnecessary.
ukode
2016/02/09 00:20:18
Done.
| |
83 : false; | |
84 | |
85 mojo::String new_db_contents; | |
86 GetUpdatedDbContents(username, new_account_data, user_exists, | |
87 new_db_contents); | |
88 if (new_db_contents.is_null()) { | |
89 return false; | |
90 } | |
91 | |
92 // Rewrite the file each time with updated info. | |
93 std::vector<uint8_t> bytes_to_write(new_db_contents.get().begin(), | |
94 new_db_contents.get().end()); | |
95 bytes_to_write.push_back('\0'); | |
96 mojo::files::Error error = mojo::files::Error::INTERNAL; | |
97 uint32_t num_bytes_written = 0; | |
98 mojo::files::Whence whence; | |
99 if (user_exists) { | |
100 whence = mojo::files::Whence::FROM_START; | |
101 } else { | |
102 whence = mojo::files::Whence::FROM_CURRENT; | |
103 } | |
104 file_->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0, whence, | |
105 Capture(&error, &num_bytes_written)); | |
106 file_.WaitForIncomingResponse(); | |
viettrungluu
2016/01/11 21:23:44
You shouldn't do a blocking write like this. In ge
ukode
2016/02/09 00:20:17
Acknowledged. MOved to async method.
| |
107 if (mojo::files::Error::OK != error) { | |
108 return false; | |
109 } | |
110 | |
111 // Update the contents cache with new data | |
112 if (user_exists) { | |
113 AccountsDbManager::contents_.assign(new_db_contents.data(), | |
viettrungluu
2016/01/11 21:23:44
Keeping contents_ in sync with the actual contents
ukode
2016/02/09 00:20:18
Acknowledged.
| |
114 new_db_contents.size()); | |
115 } else { | |
116 AccountsDbManager::contents_ += new_db_contents; | |
117 } | |
118 return true; | |
119 } | |
120 | |
121 void AccountsDbManager::GetAccountDataForUser(const mojo::String& username, | |
122 mojo::String& user_data) { | |
123 if (username.is_null()) { | |
124 return; | |
125 } | |
126 | |
127 if (AccountsDbManager::contents_.empty()) { | |
128 mojo::Array<uint8_t> all_accounts_data( | |
129 AccountsDbManager::FetchAllAccounts()); | |
130 if (!all_accounts_data.size()) { | |
131 return; | |
132 } | |
133 } | |
134 | |
135 base::StringTokenizer lines(AccountsDbManager::contents_, "\n"); | |
136 std::string entry; | |
137 while (lines.GetNext()) { | |
138 entry = lines.token(); | |
139 if (entry.find(username) != std::string::npos) { | |
140 user_data.Swap(&entry); | |
141 return; | |
142 } | |
143 } | |
144 } | |
145 | |
146 mojo::Array<uint8_t> AccountsDbManager::FetchAllAccounts() { | |
147 const size_t kMaxReadSize = 1 * 1024 * 1024; | |
148 mojo::Array<uint8_t> bytes_read; | |
149 | |
150 mojo::files::Error error = mojo::files::Error::INTERNAL; | |
151 file_->Read(kMaxReadSize - 1, 0, mojo::files::Whence::FROM_START, | |
152 Capture(&error, &bytes_read)); | |
153 file_.WaitForIncomingResponse(); | |
154 if (mojo::files::Error::OK != error) { | |
155 return mojo::Array<uint8_t>(); | |
156 } | |
157 | |
158 const std::vector<uint8_t> vec = bytes_read.storage(); | |
159 AccountsDbManager::contents_.assign((char*)vec.data(), vec.size()); | |
160 | |
161 return bytes_read.Pass(); | |
162 } | |
163 | |
164 } // namespace authentication | |
OLD | NEW |