blob: f9c6b647f038cfbe5f0f77c8eabafe70975a8f72 [file] [log] [blame]
// Copyright 2020 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.
#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_TOKEN_CACHE_H_
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_TOKEN_CACHE_H_
#include <map>
#include <set>
#include <string>
#include "base/time/time.h"
#include "chrome/browser/extensions/api/identity/extension_token_key.h"
#include "google_apis/gaia/oauth2_mint_token_flow.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace extensions {
class IdentityTokenCacheValue {
public:
IdentityTokenCacheValue();
IdentityTokenCacheValue(const IdentityTokenCacheValue& other);
IdentityTokenCacheValue& operator=(const IdentityTokenCacheValue& other);
~IdentityTokenCacheValue();
static IdentityTokenCacheValue CreateRemoteConsent(
const RemoteConsentResolutionData& resolution_data);
static IdentityTokenCacheValue CreateRemoteConsentApproved(
const std::string& consent_result);
static IdentityTokenCacheValue CreateToken(
const std::string& token,
const std::set<std::string>& granted_scopes,
base::TimeDelta time_to_live);
// Order of these entries is used to determine whether or not new
// entries supersede older ones in SetCachedToken.
enum CacheValueStatus {
CACHE_STATUS_NOTFOUND,
CACHE_STATUS_REMOTE_CONSENT,
CACHE_STATUS_REMOTE_CONSENT_APPROVED,
CACHE_STATUS_TOKEN
};
CacheValueStatus status() const;
const base::Time& expiration_time() const;
// These getters should be used only if `status()` returns a value
// corresponding to the type. Otherwise, the application will crash.
// CACHE_STATUS_REMOTE_CONSENT:
const RemoteConsentResolutionData& resolution_data() const;
// CACHE_STATUS_REMOTE_CONSENT_APPROVED:
const std::string& consent_result() const;
// CACHE_STATUS_TOKEN:
const std::string& token() const;
const std::set<std::string>& granted_scopes() const;
private:
struct TokenValue {
TokenValue(const std::string& token,
const std::set<std::string>& granted_scopes);
TokenValue(const TokenValue& other);
TokenValue& operator=(const TokenValue& other);
~TokenValue();
std::string token;
std::set<std::string> granted_scopes;
};
CacheValueStatus GetStatusInternal() const;
bool is_expired() const;
base::Time expiration_time_;
absl::variant<absl::monostate,
RemoteConsentResolutionData,
std::string,
TokenValue>
value_;
};
// In-memory cache of OAuth2 access tokens that are requested by extensions
// through the `getAuthToken` API. Also caches intermediate short-lived values
// used at different stages of the `getAuthToken` flow before a token is
// obtained. The cache automatically handles token expiration. Extensions can
// manually remove tokens from the cache using `removeCachedAuthToken` API.
//
// chrome://identity-internals provides a view of cache's content for debugging.
class IdentityTokenCache {
public:
IdentityTokenCache();
~IdentityTokenCache();
IdentityTokenCache(const IdentityTokenCache& other) = delete;
IdentityTokenCache& operator=(const IdentityTokenCache& other) = delete;
// Used to order the cached scopes based on their sizes. This allows subset
// matching to prioritize returning tokens with the smallest superset scope.
// So, if there is an exact match for the requested scopes, the corresponding
// cached token will be found first and returned.
struct ScopesSizeCompare {
bool operator()(const IdentityTokenCacheValue& lhs,
const IdentityTokenCacheValue& rhs) const;
};
struct AccessTokensKey {
explicit AccessTokensKey(const ExtensionTokenKey& key);
AccessTokensKey(const std::string& extension_id,
const CoreAccountId& account_id);
bool operator<(const AccessTokensKey& rhs) const;
std::string extension_id;
CoreAccountId account_id;
};
using AccessTokensValue =
std::set<IdentityTokenCacheValue, ScopesSizeCompare>;
using AccessTokensCache = std::map<AccessTokensKey, AccessTokensValue>;
void SetToken(const ExtensionTokenKey& key,
const IdentityTokenCacheValue& token_data);
void EraseAccessToken(const std::string& extension_id,
const std::string& token);
void EraseAllTokensForExtension(const std::string& extension_id);
void EraseAllTokens();
const IdentityTokenCacheValue& GetToken(const ExtensionTokenKey& key);
const AccessTokensCache& access_tokens_cache();
private:
void EraseStaleTokens();
AccessTokensCache access_tokens_cache_;
std::map<ExtensionTokenKey, IdentityTokenCacheValue>
intermediate_value_cache_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_TOKEN_CACHE_H_