123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- // Copyright (c) 2012 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 "google_apis/google_api_keys.h"
- // If you add more includes to this list, you also need to add them to
- // google_api_keys_unittest.cc and google_api_keys_mac_unittest.mm.
- #include <stddef.h>
- #include <memory>
- #include <string>
- #include "base/command_line.h"
- #include "base/environment.h"
- #include "base/lazy_instance.h"
- #include "base/logging.h"
- #include "base/strings/stringize_macros.h"
- #include "build/branding_buildflags.h"
- #include "google_apis/gaia/gaia_config.h"
- #include "google_apis/gaia/gaia_switches.h"
- #if BUILDFLAG(IS_APPLE)
- #include "google_apis/google_api_keys_mac.h"
- #endif
- #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
- #include "google_apis/internal/google_chrome_api_keys.h"
- #include "google_apis/internal/metrics_signing_key.h"
- #endif
- // Used to indicate an unset key/id/secret. This works better with
- // various unit tests than leaving the token empty.
- #define DUMMY_API_TOKEN "dummytoken"
- #if !defined(GOOGLE_API_KEY)
- #define GOOGLE_API_KEY DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_METRICS_SIGNING_KEY)
- #define GOOGLE_METRICS_SIGNING_KEY DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_ID_MAIN)
- #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
- #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_ID_REMOTING)
- #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
- #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
- #define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
- #define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_API_KEY_ANDROID_NON_STABLE)
- #define GOOGLE_API_KEY_ANDROID_NON_STABLE DUMMY_API_TOKEN
- #endif
- #if !defined(GOOGLE_API_KEY_REMOTING)
- #define GOOGLE_API_KEY_REMOTING DUMMY_API_TOKEN
- #endif
- // API key for SharingService.
- #if !defined(GOOGLE_API_KEY_SHARING)
- #define GOOGLE_API_KEY_SHARING DUMMY_API_TOKEN
- #endif
- // API key for the Speech On-Device API (SODA).
- #if !defined(GOOGLE_API_KEY_SODA)
- #define GOOGLE_API_KEY_SODA DUMMY_API_TOKEN
- #endif
- // API key for the ReadAloud API.
- #if !defined(GOOGLE_API_KEY_READ_ALOUD)
- #define GOOGLE_API_KEY_READ_ALOUD DUMMY_API_TOKEN
- #endif
- // API key for the Fresnel API.
- #if !defined(GOOGLE_API_KEY_FRESNEL)
- #define GOOGLE_API_KEY_FRESNEL DUMMY_API_TOKEN
- #endif
- // These are used as shortcuts for developers and users providing
- // OAuth credentials via preprocessor defines or environment
- // variables. If set, they will be used to replace any of the client
- // IDs and secrets above that have not been set (and only those; they
- // will not override already-set values).
- #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
- #define GOOGLE_DEFAULT_CLIENT_ID ""
- #endif
- #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
- #define GOOGLE_DEFAULT_CLIENT_SECRET ""
- #endif
- namespace google_apis {
- const char kAPIKeysDevelopersHowToURL[] =
- "https://www.chromium.org/developers/how-tos/api-keys";
- // This is used as a lazy instance to determine keys once and cache them.
- class APIKeyCache {
- public:
- APIKeyCache() {
- std::unique_ptr<base::Environment> environment(base::Environment::Create());
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- GaiaConfig* gaia_config = GaiaConfig::GetInstance();
- api_key_ = CalculateKeyValue(
- GOOGLE_API_KEY, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- // A special non-stable key is at the moment defined only for Android Chrome.
- #if BUILDFLAG(IS_ANDROID)
- api_key_non_stable_ = CalculateKeyValue(
- GOOGLE_API_KEY_ANDROID_NON_STABLE,
- STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_ANDROID_NON_STABLE), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- #else
- api_key_non_stable_ = api_key_;
- #endif
- api_key_remoting_ = CalculateKeyValue(
- GOOGLE_API_KEY_REMOTING,
- STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_REMOTING), nullptr, std::string(),
- environment.get(), command_line, gaia_config);
- api_key_sharing_ = CalculateKeyValue(
- GOOGLE_API_KEY_SHARING, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SHARING),
- nullptr, std::string(), environment.get(), command_line, gaia_config);
- api_key_soda_ = CalculateKeyValue(
- GOOGLE_API_KEY_SODA, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SODA),
- nullptr, std::string(), environment.get(), command_line, gaia_config);
- api_key_read_aloud_ = CalculateKeyValue(
- GOOGLE_API_KEY_READ_ALOUD,
- STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_READ_ALOUD), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- api_key_fresnel_ = CalculateKeyValue(
- GOOGLE_API_KEY_FRESNEL, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_FRESNEL),
- nullptr, std::string(), environment.get(), command_line, gaia_config);
- metrics_key_ = CalculateKeyValue(
- GOOGLE_METRICS_SIGNING_KEY,
- STRINGIZE_NO_EXPANSION(GOOGLE_METRICS_SIGNING_KEY), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- std::string default_client_id = CalculateKeyValue(
- GOOGLE_DEFAULT_CLIENT_ID,
- STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- std::string default_client_secret = CalculateKeyValue(
- GOOGLE_DEFAULT_CLIENT_SECRET,
- STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET), nullptr,
- std::string(), environment.get(), command_line, gaia_config);
- // We currently only allow overriding the baked-in values for the
- // default OAuth2 client ID and secret using a command-line
- // argument and gaia config, since that is useful to enable testing against
- // staging servers, and since that was what was possible and
- // likely practiced by the QA team before this implementation was
- // written.
- client_ids_[CLIENT_MAIN] = CalculateKeyValue(
- GOOGLE_CLIENT_ID_MAIN, STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN),
- ::switches::kOAuth2ClientID, default_client_id, environment.get(),
- command_line, gaia_config);
- client_secrets_[CLIENT_MAIN] = CalculateKeyValue(
- GOOGLE_CLIENT_SECRET_MAIN,
- STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN),
- ::switches::kOAuth2ClientSecret, default_client_secret,
- environment.get(), command_line, gaia_config);
- client_ids_[CLIENT_REMOTING] = CalculateKeyValue(
- GOOGLE_CLIENT_ID_REMOTING,
- STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING), nullptr,
- default_client_id, environment.get(), command_line, gaia_config);
- client_secrets_[CLIENT_REMOTING] = CalculateKeyValue(
- GOOGLE_CLIENT_SECRET_REMOTING,
- STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING), nullptr,
- default_client_secret, environment.get(), command_line, gaia_config);
- client_ids_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
- GOOGLE_CLIENT_ID_REMOTING_HOST,
- STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST), nullptr,
- default_client_id, environment.get(), command_line, gaia_config);
- client_secrets_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
- GOOGLE_CLIENT_SECRET_REMOTING_HOST,
- STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST), nullptr,
- default_client_secret, environment.get(), command_line, gaia_config);
- }
- std::string api_key() const { return api_key_; }
- #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA)
- void set_api_key(const std::string& api_key) { api_key_ = api_key; }
- #endif
- std::string api_key_non_stable() const { return api_key_non_stable_; }
- std::string api_key_remoting() const { return api_key_remoting_; }
- std::string api_key_sharing() const { return api_key_sharing_; }
- std::string api_key_soda() const { return api_key_soda_; }
- std::string api_key_read_aloud() const { return api_key_read_aloud_; }
- std::string api_key_fresnel() const { return api_key_fresnel_; }
- std::string metrics_key() const { return metrics_key_; }
- std::string GetClientID(OAuth2Client client) const {
- DCHECK_LT(client, CLIENT_NUM_ITEMS);
- return client_ids_[client];
- }
- #if BUILDFLAG(IS_IOS)
- void SetClientID(OAuth2Client client, const std::string& client_id) {
- client_ids_[client] = client_id;
- }
- #endif
- std::string GetClientSecret(OAuth2Client client) const {
- DCHECK_LT(client, CLIENT_NUM_ITEMS);
- return client_secrets_[client];
- }
- #if BUILDFLAG(IS_IOS)
- void SetClientSecret(OAuth2Client client, const std::string& client_secret) {
- client_secrets_[client] = client_secret;
- }
- #endif
- std::string GetSpdyProxyAuthValue() {
- #if defined(SPDY_PROXY_AUTH_VALUE)
- return SPDY_PROXY_AUTH_VALUE;
- #else
- return std::string();
- #endif
- }
- private:
- // Gets a value for a key. In priority order, this will be the value
- // provided via:
- // 1. Command-line switch
- // 2. Config file
- // 3. Environment variable
- // 4. Baked into the build
- // |command_line_switch| may be NULL. Official Google Chrome builds will not
- // use the value provided by an environment variable.
- static std::string CalculateKeyValue(const char* baked_in_value,
- const char* environment_variable_name,
- const char* command_line_switch,
- const std::string& default_if_unset,
- base::Environment* environment,
- base::CommandLine* command_line,
- GaiaConfig* gaia_config) {
- std::string key_value = baked_in_value;
- std::string temp;
- #if BUILDFLAG(IS_APPLE)
- // macOS and iOS can also override the API key with a value from the
- // Info.plist.
- temp = ::google_apis::GetAPIKeyFromInfoPlist(environment_variable_name);
- if (!temp.empty()) {
- key_value = temp;
- VLOG(1) << "Overriding API key " << environment_variable_name
- << " with value " << key_value << " from Info.plist.";
- }
- #endif
- #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
- // Don't allow using the environment to override API keys for official
- // Google Chrome builds. There have been reports of mangled environments
- // affecting users (crbug.com/710575).
- if (environment->GetVar(environment_variable_name, &temp)) {
- key_value = temp;
- VLOG(1) << "Overriding API key " << environment_variable_name
- << " with value " << key_value << " from environment variable.";
- }
- #endif
- if (gaia_config &&
- gaia_config->GetAPIKeyIfExists(environment_variable_name, &temp)) {
- key_value = temp;
- VLOG(1) << "Overriding API key " << environment_variable_name
- << " with value " << key_value << " from gaia config.";
- }
- if (command_line_switch && command_line->HasSwitch(command_line_switch)) {
- key_value = command_line->GetSwitchValueASCII(command_line_switch);
- VLOG(1) << "Overriding API key " << environment_variable_name
- << " with value " << key_value << " from command-line switch.";
- }
- if (key_value == DUMMY_API_TOKEN) {
- #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_FUCHSIA)
- // No key should be unset in an official build except the
- // GOOGLE_DEFAULT_* keys. The default keys don't trigger this
- // check as their "unset" value is not DUMMY_API_TOKEN.
- // Exclude Fuchsia to match BUILD.gn.
- // TODO(crbug.com/1171510): Update Fuchsia exclusion when bug is fixed.
- CHECK(false);
- #endif
- if (default_if_unset.size() > 0) {
- VLOG(1) << "Using default value \"" << default_if_unset
- << "\" for API key " << environment_variable_name;
- key_value = default_if_unset;
- }
- }
- // This should remain a debug-only log.
- DVLOG(1) << "API key " << environment_variable_name << "=" << key_value;
- return key_value;
- }
- std::string api_key_;
- std::string api_key_non_stable_;
- std::string api_key_remoting_;
- std::string api_key_sharing_;
- std::string api_key_soda_;
- std::string api_key_read_aloud_;
- std::string api_key_fresnel_;
- std::string metrics_key_;
- std::string client_ids_[CLIENT_NUM_ITEMS];
- std::string client_secrets_[CLIENT_NUM_ITEMS];
- };
- static base::LazyInstance<APIKeyCache>::DestructorAtExit g_api_key_cache =
- LAZY_INSTANCE_INITIALIZER;
- bool HasAPIKeyConfigured() {
- return GetAPIKey() != DUMMY_API_TOKEN;
- }
- std::string GetAPIKey() {
- return g_api_key_cache.Get().api_key();
- }
- std::string GetNonStableAPIKey() {
- return g_api_key_cache.Get().api_key_non_stable();
- }
- std::string GetRemotingAPIKey() {
- return g_api_key_cache.Get().api_key_remoting();
- }
- std::string GetSharingAPIKey() {
- return g_api_key_cache.Get().api_key_sharing();
- }
- std::string GetSodaAPIKey() {
- return g_api_key_cache.Get().api_key_soda();
- }
- std::string GetReadAloudAPIKey() {
- return g_api_key_cache.Get().api_key_read_aloud();
- }
- std::string GetFresnelAPIKey() {
- return g_api_key_cache.Get().api_key_fresnel();
- }
- #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA)
- void SetAPIKey(const std::string& api_key) {
- g_api_key_cache.Get().set_api_key(api_key);
- }
- #endif
- std::string GetMetricsKey() {
- return g_api_key_cache.Get().metrics_key();
- }
- bool HasOAuthClientConfigured() {
- for (size_t client_id = 0; client_id < CLIENT_NUM_ITEMS; ++client_id) {
- OAuth2Client client = static_cast<OAuth2Client>(client_id);
- if (GetOAuth2ClientID(client) == DUMMY_API_TOKEN ||
- GetOAuth2ClientSecret(client) == DUMMY_API_TOKEN) {
- return false;
- }
- }
- return true;
- }
- std::string GetOAuth2ClientID(OAuth2Client client) {
- return g_api_key_cache.Get().GetClientID(client);
- }
- std::string GetOAuth2ClientSecret(OAuth2Client client) {
- return g_api_key_cache.Get().GetClientSecret(client);
- }
- #if BUILDFLAG(IS_IOS)
- void SetOAuth2ClientID(OAuth2Client client, const std::string& client_id) {
- g_api_key_cache.Get().SetClientID(client, client_id);
- }
- void SetOAuth2ClientSecret(OAuth2Client client,
- const std::string& client_secret) {
- g_api_key_cache.Get().SetClientSecret(client, client_secret);
- }
- #endif
- std::string GetSpdyProxyAuthValue() {
- return g_api_key_cache.Get().GetSpdyProxyAuthValue();
- }
- bool IsGoogleChromeAPIKeyUsed() {
- #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
- return true;
- #else
- return false;
- #endif
- }
- } // namespace google_apis
|