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

Unified 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 demo namespaces 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 side-by-side diff with in-line comments
Download patch
Index: services/authentication/accounts_db_manager.cc
diff --git a/services/authentication/accounts_db_manager.cc b/services/authentication/accounts_db_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a2a2f2a447b84168f59fe3335159c7e5703b3f16
--- /dev/null
+++ b/services/authentication/accounts_db_manager.cc
@@ -0,0 +1,183 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/authentication/accounts_db_manager.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_tokenizer.h"
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+#include "mojo/services/files/interfaces/files.mojom.h"
+
+namespace authentication {
+
+const char* kAccountsDbFileName = "accounts_db.txt";
+AccountsDbManager::AccountsDbManager()
+ : directory_(nullptr), contents_(nullptr) {}
+
+AccountsDbManager::AccountsDbManager(mojo::files::FilesPtr files) {
+ // TODO: Move to a file system with secure privileges as the accounts db needs
+ // to persist across multiple invocations and apps, and the temporary root
+ // solution here is just a short term path.
+ mojo::files::Error error = mojo::files::Error::INTERNAL;
+ files->OpenFileSystem(nullptr, GetProxy(&directory_), Capture(&error));
+ files.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ LOG(FATAL) << "Unable to initialize accounts DB";
+ }
+}
+
+AccountsDbManager::~AccountsDbManager() {}
+
+bool AccountsDbManager::UpdateAccount(const mojo::String& username,
+ const mojo::String& new_account_data) {
+ if (username.is_null() || new_account_data.is_null()) {
+ return false;
+ }
+
+ std::string buffer;
+ std::string new_contents(AccountsDbManager::contents_);
jln (very slow on Chromium) 2015/12/08 22:27:29 No need for AccountsDbManager:: qualifier.
ukode 2015/12/16 19:24:12 Done.
+ mojo::String existing_user_data;
+ AccountsDbManager::GetAccountDataForUser(username, existing_user_data);
+
+ if (existing_user_data.is_null()) { // new account to be added
jln (very slow on Chromium) 2015/12/08 22:27:29 I don't quite understand what's happening here yet
ukode 2015/12/16 19:24:12 This is very specific to account db functionality.
+ if (!AccountsDbManager::contents_.empty()) {
+ buffer += "\n";
+ }
+ buffer += new_account_data.get();
+ new_contents += buffer;
+ } else {
+ // Parse the existing account data and replace the token
+ base::StringTokenizer lines(AccountsDbManager::contents_, "\n");
+ std::string user_data;
+ while (lines.GetNext()) {
+ user_data = lines.token();
+ if (user_data.find(username) != std::string::npos) {
+ buffer += new_account_data.get(); // replace with new contents
+ } else {
+ buffer += user_data; // carry forward the existing user data
+ }
+ buffer += "\n";
+ }
+ if (!buffer.empty()) {
+ buffer.pop_back();
+ }
+ new_contents.assign(buffer.c_str(), buffer.size());
jln (very slow on Chromium) 2015/12/08 22:27:29 Why are new_contents and buffer both needed. It lo
ukode 2015/12/16 19:24:13 Fixed it as part of refactoring.
+ }
+
+ // Open accounts db file
+ mojo::files::FilePtr file;
+ mojo::files::Error error = mojo::files::Error::INTERNAL;
+ if (existing_user_data.is_null()) {
+ // Append to existing File
+ directory_->OpenFile(kAccountsDbFileName, GetProxy(&file),
+ mojo::files::kOpenFlagWrite |
+ mojo::files::kOpenFlagCreate |
+ mojo::files::kOpenFlagAppend,
+ Capture(&error));
+ } else {
+ // Rewrite the file contents with updated info
+ directory_->OpenFile(
+ kAccountsDbFileName, GetProxy(&file),
+ mojo::files::kOpenFlagWrite | mojo::files::kOpenFlagCreate,
+ Capture(&error));
+ }
+ directory_.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return false;
jln (very slow on Chromium) 2015/12/08 22:27:29 Looks like the opened file is not getting closed h
ukode 2015/12/16 19:24:12 Good catch. Fixed it.
+ }
+
+ // Write to it.
+ std::vector<uint8_t> bytes_to_write(buffer.begin(), buffer.end());
+ bytes_to_write.push_back('\0');
+ error = mojo::files::Error::INTERNAL;
+ uint32_t num_bytes_written = 0;
+ file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
+ mojo::files::Whence::FROM_CURRENT,
+ Capture(&error, &num_bytes_written));
+ file.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return false;
+ }
+
+ // Close the accounts db file
+ error = mojo::files::Error::INTERNAL;
+ file->Close(Capture(&error));
+ file.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return false;
+ }
+
+ // Update the existing contents with new data
+ AccountsDbManager::contents_.assign(new_contents.c_str(),
+ new_contents.size());
+ return true;
+}
+
+void AccountsDbManager::GetAccountDataForUser(const mojo::String& username,
+ mojo::String& user_data) {
+ if (username.is_null()) {
+ return;
+ }
+
+ if (AccountsDbManager::contents_.empty()) {
+ mojo::Array<uint8_t> all_accounts_data(
+ AccountsDbManager::FetchAllAccounts());
+ if (!all_accounts_data.size()) {
+ return;
+ }
+ }
+
+ base::StringTokenizer lines(AccountsDbManager::contents_, "\n");
+ std::string entry;
+ while (lines.GetNext()) {
+ entry = lines.token();
+ if (entry.find(username) != std::string::npos) {
+ user_data.Swap(&entry);
+ return;
+ }
+ }
+}
+
+mojo::Array<uint8_t> AccountsDbManager::FetchAllAccounts() {
+ const size_t kMaxReadSize = 1 * 1024 * 1024;
+
+ // Open accounts db file
+ mojo::files::FilePtr file;
+ mojo::files::Error error = mojo::files::Error::INTERNAL;
+ directory_->OpenFile(kAccountsDbFileName, GetProxy(&file),
+ mojo::files::kOpenFlagRead, Capture(&error));
+ directory_.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return mojo::Array<uint8_t>();
+ }
+
+ // Read from it.
+ mojo::Array<uint8_t> bytes_read;
+ error = mojo::files::Error::INTERNAL;
+ file->Read(kMaxReadSize - 1, 0, mojo::files::Whence::FROM_START,
+ Capture(&error, &bytes_read));
+
+ file.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return mojo::Array<uint8_t>();
+ }
+
+ // Close the accounts db file
+ error = mojo::files::Error::INTERNAL;
+ file->Close(Capture(&error));
+ file.WaitForIncomingResponse();
+ if (mojo::files::Error::OK != error) {
+ return mojo::Array<uint8_t>();
+ }
+
+ const std::vector<uint8_t> vec = bytes_read.storage();
jln (very slow on Chromium) 2015/12/08 22:27:29 I'm surprised if Mojo doesn't offer a better way t
ukode 2015/12/16 19:24:12 +vtl/mitch - do you have any other suggestion here
+ AccountsDbManager::contents_.assign((char*)vec.data(), vec.size());
+
+ return bytes_read.Pass();
+}
+
+} // namespace authentication

Powered by Google App Engine
This is Rietveld 408576698