Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / remoting / test / refresh_token_store.cc
blobc7ef0e71693f3b537aa479a132f31f3eb99dc11e
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.
5 #include "remoting/test/refresh_token_store.h"
7 #include "base/files/file_util.h"
8 #include "base/files/important_file_writer.h"
9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "base/values.h"
14 namespace {
15 const base::FilePath::CharType kTokenFileName[] =
16 FILE_PATH_LITERAL("refresh_tokens.json");
17 const base::FilePath::CharType kRemotingFolder[] =
18 FILE_PATH_LITERAL("remoting");
19 const base::FilePath::CharType kRefreshTokenStoreFolder[] =
20 FILE_PATH_LITERAL("token_store");
21 } // namespace
23 namespace remoting {
24 namespace test {
26 // Provides functionality to write a refresh token to a local folder on disk and
27 // read it back during subsequent tool runs.
28 class RefreshTokenStoreOnDisk : public RefreshTokenStore {
29 public:
30 RefreshTokenStoreOnDisk(const std::string& user_name,
31 const base::FilePath& refresh_token_file_path);
32 ~RefreshTokenStoreOnDisk() override;
34 // RefreshTokenStore interface.
35 std::string FetchRefreshToken() override;
36 bool StoreRefreshToken(const std::string& refresh_token) override;
38 private:
39 // Returns the path for the file used to read from or store a refresh token
40 // for the user.
41 base::FilePath GetPathForRefreshTokenFile();
43 // Used to access the user specific token file.
44 std::string user_name_;
46 // Path used to retrieve the refresh token file.
47 base::FilePath refresh_token_file_path_;
49 DISALLOW_COPY_AND_ASSIGN(RefreshTokenStoreOnDisk);
52 RefreshTokenStoreOnDisk::RefreshTokenStoreOnDisk(
53 const std::string& user_name,
54 const base::FilePath& refresh_token_path)
55 : user_name_(user_name),
56 refresh_token_file_path_(base::MakeAbsoluteFilePath(refresh_token_path)) {
59 RefreshTokenStoreOnDisk::~RefreshTokenStoreOnDisk() {
62 std::string RefreshTokenStoreOnDisk::FetchRefreshToken() {
63 base::FilePath refresh_token_file_path(GetPathForRefreshTokenFile());
64 DCHECK(!refresh_token_file_path.empty());
65 VLOG(1) << "Reading token from: " << refresh_token_file_path.value();
67 std::string file_contents;
68 if (!base::ReadFileToString(refresh_token_file_path, &file_contents)) {
69 VLOG(1) << "Couldn't read token file: " << refresh_token_file_path.value();
70 return std::string();
73 scoped_ptr<base::Value> token_data(base::JSONReader::Read(file_contents));
74 base::DictionaryValue* tokens = nullptr;
75 if (!token_data || !token_data->GetAsDictionary(&tokens)) {
76 LOG(ERROR) << "Refresh token file contents were not valid JSON, "
77 << "could not retrieve token.";
78 return std::string();
81 std::string refresh_token;
82 if (!tokens->GetStringWithoutPathExpansion(user_name_, &refresh_token)) {
83 // This may not be an error as the file could exist but contain refresh
84 // tokens for other users.
85 VLOG(1) << "Could not find token for: " << user_name_;
86 return std::string();
89 return refresh_token;
92 bool RefreshTokenStoreOnDisk::StoreRefreshToken(
93 const std::string& refresh_token) {
94 DCHECK(!refresh_token.empty());
96 base::FilePath file_path(GetPathForRefreshTokenFile());
97 DCHECK(!file_path.empty());
98 VLOG(2) << "Storing token to: " << file_path.value();
100 base::FilePath refresh_token_file_dir(file_path.DirName());
101 if (!base::DirectoryExists(refresh_token_file_dir) &&
102 !base::CreateDirectory(refresh_token_file_dir)) {
103 LOG(ERROR) << "Failed to create directory, refresh token not stored.";
104 return false;
107 std::string file_contents("{}");
108 if (base::PathExists(file_path)) {
109 if (!base::ReadFileToString(file_path, &file_contents)) {
110 LOG(ERROR) << "Invalid token file: " << file_path.value();
111 return false;
115 scoped_ptr<base::Value> token_data(base::JSONReader::Read(file_contents));
116 base::DictionaryValue* tokens = nullptr;
117 if (!token_data || !token_data->GetAsDictionary(&tokens)) {
118 LOG(ERROR) << "Invalid refresh token file format, could not store token.";
119 return false;
122 std::string json_string;
123 tokens->SetStringWithoutPathExpansion(user_name_, refresh_token);
124 if (!base::JSONWriter::Write(*token_data, &json_string)) {
125 LOG(ERROR) << "Couldn't convert JSON data to string";
126 return false;
129 if (!base::ImportantFileWriter::WriteFileAtomically(file_path, json_string)) {
130 LOG(ERROR) << "Failed to save refresh token to the file on disk.";
131 return false;
134 return true;
137 base::FilePath RefreshTokenStoreOnDisk::GetPathForRefreshTokenFile() {
138 base::FilePath refresh_token_file_path(refresh_token_file_path_);
140 // If we weren't given a specific file path, then use the default path.
141 if (refresh_token_file_path.empty()) {
142 if (!GetTempDir(&refresh_token_file_path)) {
143 LOG(WARNING) << "Failed to retrieve temporary directory path.";
144 return base::FilePath();
147 refresh_token_file_path = refresh_token_file_path.Append(kRemotingFolder);
148 refresh_token_file_path =
149 refresh_token_file_path.Append(kRefreshTokenStoreFolder);
152 // If no file has been specified, then we will use a default file name.
153 if (refresh_token_file_path.Extension().empty()) {
154 refresh_token_file_path = refresh_token_file_path.Append(kTokenFileName);
157 return refresh_token_file_path;
160 scoped_ptr<RefreshTokenStore> RefreshTokenStore::OnDisk(
161 const std::string& user_name,
162 const base::FilePath& refresh_token_file_path) {
163 return make_scoped_ptr<RefreshTokenStore>(
164 new RefreshTokenStoreOnDisk(user_name, refresh_token_file_path));
167 } // namespace test
168 } // namespace remoting