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/memory/weak_ptr.h" | |
| 11 #include "base/strings/string_tokenizer.h" | |
| 12 #include "mojo/public/cpp/bindings/array.h" | |
| 13 #include "mojo/public/cpp/bindings/type_converter.h" | |
| 14 #include "mojo/services/files/interfaces/files.mojom.h" | |
| 15 #include "services/authentication/authentication_impl_db.mojom.h" | |
| 16 #include "services/authentication/credentials_impl_db.mojom.h" | |
| 17 | |
| 18 namespace authentication { | |
| 19 | |
| 20 char kAccountsDbFileName[] = "creds_db"; | |
| 21 char kAuthDbFileName[] = "auth_db"; | |
| 22 const uint32 kAuthDbVersion = 1; | |
| 23 const uint32 kCredsDbVersion = 1; | |
| 24 | |
| 25 AccountsDbManager::AccountsDbManager(const mojo::files::DirectoryPtr directory) | |
| 26 : creds_db_file_(nullptr), auth_db_file_(nullptr), weak_ptr_factory_(this) { | |
| 27 // Initialize in-memory contents from existing DB file | |
| 28 directory->OpenFile( | |
| 29 kAccountsDbFileName, GetProxy(&creds_db_file_), | |
| 30 mojo::files::kOpenFlagCreate | mojo::files::kOpenFlagRead | | |
| 31 mojo::files::kOpenFlagWrite, | |
| 32 [this](mojo::files::Error error) { | |
| 33 if (mojo::files::Error::OK != error) { | |
| 34 LOG(ERROR) << "Open() error on credentials db:" << error; | |
| 35 delete this; | |
| 36 return; | |
| 37 } | |
| 38 }); | |
| 39 directory->OpenFile(kAuthDbFileName, GetProxy(&auth_db_file_), | |
| 40 mojo::files::kOpenFlagCreate | | |
| 41 mojo::files::kOpenFlagRead | | |
| 42 mojo::files::kOpenFlagWrite, | |
| 43 [this](mojo::files::Error error) { | |
| 44 if (mojo::files::Error::OK != error) { | |
| 45 LOG(ERROR) << "Open() error on auth db:" << error; | |
| 46 delete this; | |
| 47 return; | |
| 48 } | |
| 49 }); | |
| 50 Initialize(); | |
| 51 } | |
| 52 | |
| 53 AccountsDbManager::~AccountsDbManager() { | |
| 54 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 55 delete this; | |
| 56 } | |
| 57 | |
| 58 base::WeakPtr<AccountsDbManager> AccountsDbManager::GetWeakPtr() { | |
| 59 return weak_ptr_factory_.GetWeakPtr(); | |
| 60 } | |
| 61 | |
| 62 authentication::CredentialsPtr AccountsDbManager::GetCredentials( | |
| 63 const mojo::String& username) { | |
| 64 ensureCredsDbInit(); | |
| 65 | |
| 66 authentication::CredentialsPtr creds = authentication::Credentials::New(); | |
| 67 if (username.is_null()) { | |
| 68 return creds.Pass(); | |
| 69 } | |
| 70 | |
| 71 auto it = creds_store_.credentials.find(username); | |
| 72 if (it != creds_store_.credentials.end()) { | |
| 73 creds->token = it.GetValue()->token; | |
| 74 creds->auth_provider = it.GetValue()->auth_provider; | |
| 75 creds->scopes = it.GetValue()->scopes; | |
| 76 creds->credential_type = it.GetValue()->credential_type; | |
| 77 } | |
| 78 return creds.Pass(); | |
| 79 } | |
| 80 | |
| 81 mojo::Array<mojo::String> AccountsDbManager::GetAllUsers() { | |
| 82 ensureCredsDbInit(); | |
| 83 | |
| 84 mojo::Array<mojo::String> users = | |
| 85 mojo::Array<mojo::String>::New(creds_store_.credentials.size()); | |
| 86 size_t i = 0; | |
| 87 for (auto it = creds_store_.credentials.begin(); | |
| 88 it != creds_store_.credentials.end(); it++) { | |
|
qsr
2016/03/04 15:06:45
Why not use a for each loop? Doesn't it work on mo
ukode
2016/03/11 22:48:52
I get this error on using for each: indirection re
| |
| 89 users[i++] = it.GetKey().get(); | |
| 90 } | |
| 91 return users.Pass(); | |
| 92 } | |
| 93 | |
| 94 void AccountsDbManager::UpdateCredentials( | |
| 95 const mojo::String& username, | |
| 96 const authentication::CredentialsPtr creds) { | |
| 97 ensureCredsDbInit(); | |
| 98 | |
| 99 if (username.is_null()) { | |
| 100 return; | |
| 101 } | |
| 102 | |
| 103 // Set the creds db version | |
| 104 if (!creds_store_.version) { | |
| 105 creds_store_.version = kCredsDbVersion; | |
|
qsr
2016/03/04 15:06:45
This should be done during init.
ukode
2016/03/11 22:48:51
Done.
| |
| 106 } | |
| 107 | |
| 108 // Update contents cache with new data | |
| 109 creds_store_.credentials[username] = authentication::Credentials::New(); | |
| 110 creds_store_.credentials[username]->token = creds->token; | |
| 111 creds_store_.credentials[username]->auth_provider = creds->auth_provider; | |
| 112 creds_store_.credentials[username]->scopes = creds->scopes; | |
| 113 creds_store_.credentials[username]->credential_type = creds->credential_type; | |
| 114 | |
| 115 size_t buf_size = creds_store_.GetSerializedSize(); | |
| 116 char buf[buf_size]; | |
| 117 MOJO_CHECK(creds_store_.Serialize(buf, buf_size)); | |
| 118 | |
| 119 std::vector<uint8_t> bytes_to_write(buf, buf + buf_size); | |
| 120 mojo::files::Whence whence; | |
| 121 whence = mojo::files::Whence::FROM_START; | |
| 122 | |
| 123 creds_db_file_->Write( | |
| 124 mojo::Array<uint8_t>::From(bytes_to_write), 0, whence, | |
| 125 [this](mojo::files::Error error, uint32_t num_bytes_written) { | |
| 126 this->OnCredFileWriteResponse(error, num_bytes_written); | |
| 127 }); | |
| 128 } | |
| 129 | |
| 130 void AccountsDbManager::OnCredFileWriteResponse( | |
| 131 const mojo::files::Error error, | |
| 132 const uint32_t num_bytes_written) { | |
| 133 if (mojo::files::Error::OK != error) { | |
| 134 LOG(ERROR) << "Write() error on accounts db:" << error; | |
| 135 delete this; | |
| 136 return; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 void AccountsDbManager::ensureCredsDbInit() { | |
| 141 if ((db_init_option_ & CREDS_DB_INIT_SUCCESS) != CREDS_DB_INIT_SUCCESS) { | |
| 142 CHECK(creds_db_file_.WaitForIncomingResponse()); | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 void AccountsDbManager::ensureAuthDbInit() { | |
| 147 if ((db_init_option_ & AUTH_DB_INIT_SUCCESS) != AUTH_DB_INIT_SUCCESS) { | |
| 148 CHECK(auth_db_file_.WaitForIncomingResponse()); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 void AccountsDbManager::Initialize() { | |
| 153 auth_grants_.version = kAuthDbVersion; | |
|
qsr
2016/03/04 15:06:45
Why is this necessary? Shouldn't you do this when
ukode
2016/03/11 22:48:51
Done, moved it below inside file read operation.
| |
| 154 | |
| 155 const size_t kMaxReadSize = 1 * 1024 * 1024; | |
| 156 mojo::Array<uint8_t> cred_bytes_read; | |
| 157 creds_db_file_->Read( | |
| 158 kMaxReadSize - 1, 0, mojo::files::Whence::FROM_START, | |
| 159 [this](mojo::files::Error error, mojo::Array<uint8_t> cred_bytes_read) { | |
| 160 this->OnCredFileReadResponse(error, cred_bytes_read.Pass()); | |
| 161 }); | |
| 162 | |
| 163 mojo::Array<uint8_t> auth_bytes_read; | |
| 164 auth_db_file_->Read( | |
| 165 kMaxReadSize - 1, 0, mojo::files::Whence::FROM_START, | |
| 166 [this](mojo::files::Error error, mojo::Array<uint8_t> auth_bytes_read) { | |
| 167 this->OnAuthFileReadResponse(error, auth_bytes_read.Pass()); | |
| 168 }); | |
| 169 } | |
| 170 | |
| 171 void AccountsDbManager::OnCredFileReadResponse( | |
| 172 const mojo::files::Error error, | |
| 173 const mojo::Array<uint8_t> bytes_read) { | |
| 174 if (error != mojo::files::Error::OK) { | |
| 175 LOG(ERROR) << "Read() error on accounts db: " << error; | |
| 176 delete this; | |
| 177 return; | |
| 178 } | |
| 179 | |
| 180 if (bytes_read.size() != 0) { | |
| 181 // Deserialize data from file | |
| 182 const char* data = reinterpret_cast<const char*>(&bytes_read[0]); | |
| 183 creds_store_.Deserialize((void*)data); | |
| 184 CHECK_EQ(creds_store_.version, kCredsDbVersion); | |
|
qsr
2016/03/04 15:06:45
Maybe put a comment that when we have multiple ver
ukode
2016/03/11 22:48:51
Acknowledged.
| |
| 185 CHECK(creds_store_.credentials.size() > 0); | |
|
qsr
2016/03/04 15:06:45
Why do you have this check? Isn't it possible that
ukode
2016/03/11 22:48:52
Good catch. Yes, that's possible. Removed the chec
| |
| 186 } | |
| 187 | |
| 188 db_init_option_ |= CREDS_DB_INIT_SUCCESS; | |
| 189 } | |
| 190 | |
| 191 void AccountsDbManager::OnAuthFileReadResponse( | |
| 192 const mojo::files::Error error, | |
| 193 const mojo::Array<uint8_t> bytes_read) { | |
| 194 if (error != mojo::files::Error::OK) { | |
| 195 LOG(ERROR) << "Read() error on auth db: " << error; | |
| 196 delete this; | |
| 197 return; | |
| 198 } | |
| 199 | |
| 200 if (bytes_read.size() != 0) { | |
| 201 // Deserialize data from file | |
| 202 const char* data = reinterpret_cast<const char*>(&bytes_read[0]); | |
| 203 auth_grants_.Deserialize((void*)data); | |
|
qsr
2016/03/04 15:06:45
You want to use Validate before calling Deserializ
ukode
2016/03/11 22:48:52
Done.
| |
| 204 CHECK_EQ(auth_grants_.version, kAuthDbVersion); | |
| 205 CHECK(!auth_grants_.last_selected_accounts.is_null()); | |
| 206 } | |
| 207 | |
| 208 db_init_option_ |= AUTH_DB_INIT_SUCCESS; | |
| 209 } | |
| 210 | |
| 211 mojo::String AccountsDbManager::GetAuthorizedUserForApp(mojo::String app_url) { | |
| 212 ensureAuthDbInit(); | |
| 213 | |
| 214 if (app_url.is_null()) { | |
| 215 return nullptr; | |
| 216 } | |
| 217 auto it = auth_grants_.last_selected_accounts.find(app_url); | |
| 218 if (it == auth_grants_.last_selected_accounts.end()) { | |
| 219 return nullptr; | |
| 220 } | |
| 221 return mojo::String(it.GetValue()); | |
| 222 } | |
| 223 | |
| 224 void AccountsDbManager::UpdateAuthorization(mojo::String app_url, | |
| 225 mojo::String username) { | |
| 226 if (app_url.is_null() || username.is_null()) { | |
| 227 return; | |
| 228 } | |
| 229 auth_grants_.last_selected_accounts[app_url] = username; | |
| 230 | |
| 231 size_t buf_size = auth_grants_.GetSerializedSize(); | |
| 232 char buf[buf_size]; | |
|
qsr
2016/03/04 15:06:45
Why not directly creating a mojo::Array<uint8_t> o
ukode
2016/03/11 22:48:51
Done.
| |
| 233 MOJO_CHECK(auth_grants_.Serialize(buf, buf_size)); | |
| 234 | |
| 235 std::vector<uint8_t> bytes_to_write(buf, buf + buf_size); | |
| 236 mojo::files::Whence whence; | |
| 237 whence = mojo::files::Whence::FROM_START; | |
| 238 | |
| 239 auth_db_file_->Write( | |
| 240 mojo::Array<uint8_t>::From(bytes_to_write), 0, whence, | |
| 241 [this](mojo::files::Error error, uint32_t num_bytes_written) { | |
| 242 this->OnAuthFileWriteResponse(error, num_bytes_written); | |
| 243 }); | |
| 244 } | |
| 245 | |
| 246 void AccountsDbManager::OnAuthFileWriteResponse( | |
| 247 const mojo::files::Error error, | |
| 248 const uint32_t num_bytes_written) { | |
| 249 if (mojo::files::Error::OK != error) { | |
| 250 LOG(ERROR) << "Write() error on auth db:" << error; | |
| 251 delete this; | |
| 252 return; | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 } // namespace authentication | |
| OLD | NEW |