Chromium Code Reviews| 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 |