google_api_keys.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // Copyright (c) 2012 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. #include "google_apis/google_api_keys.h"
  5. // If you add more includes to this list, you also need to add them to
  6. // google_api_keys_unittest.cc and google_api_keys_mac_unittest.mm.
  7. #include <stddef.h>
  8. #include <memory>
  9. #include <string>
  10. #include "base/command_line.h"
  11. #include "base/environment.h"
  12. #include "base/lazy_instance.h"
  13. #include "base/logging.h"
  14. #include "base/strings/stringize_macros.h"
  15. #include "build/branding_buildflags.h"
  16. #include "google_apis/gaia/gaia_config.h"
  17. #include "google_apis/gaia/gaia_switches.h"
  18. #if BUILDFLAG(IS_APPLE)
  19. #include "google_apis/google_api_keys_mac.h"
  20. #endif
  21. #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
  22. #include "google_apis/internal/google_chrome_api_keys.h"
  23. #include "google_apis/internal/metrics_signing_key.h"
  24. #endif
  25. // Used to indicate an unset key/id/secret. This works better with
  26. // various unit tests than leaving the token empty.
  27. #define DUMMY_API_TOKEN "dummytoken"
  28. #if !defined(GOOGLE_API_KEY)
  29. #define GOOGLE_API_KEY DUMMY_API_TOKEN
  30. #endif
  31. #if !defined(GOOGLE_METRICS_SIGNING_KEY)
  32. #define GOOGLE_METRICS_SIGNING_KEY DUMMY_API_TOKEN
  33. #endif
  34. #if !defined(GOOGLE_CLIENT_ID_MAIN)
  35. #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
  36. #endif
  37. #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
  38. #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
  39. #endif
  40. #if !defined(GOOGLE_CLIENT_ID_REMOTING)
  41. #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
  42. #endif
  43. #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
  44. #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
  45. #endif
  46. #if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
  47. #define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
  48. #endif
  49. #if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
  50. #define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
  51. #endif
  52. #if !defined(GOOGLE_API_KEY_ANDROID_NON_STABLE)
  53. #define GOOGLE_API_KEY_ANDROID_NON_STABLE DUMMY_API_TOKEN
  54. #endif
  55. #if !defined(GOOGLE_API_KEY_REMOTING)
  56. #define GOOGLE_API_KEY_REMOTING DUMMY_API_TOKEN
  57. #endif
  58. // API key for SharingService.
  59. #if !defined(GOOGLE_API_KEY_SHARING)
  60. #define GOOGLE_API_KEY_SHARING DUMMY_API_TOKEN
  61. #endif
  62. // API key for the Speech On-Device API (SODA).
  63. #if !defined(GOOGLE_API_KEY_SODA)
  64. #define GOOGLE_API_KEY_SODA DUMMY_API_TOKEN
  65. #endif
  66. // API key for the ReadAloud API.
  67. #if !defined(GOOGLE_API_KEY_READ_ALOUD)
  68. #define GOOGLE_API_KEY_READ_ALOUD DUMMY_API_TOKEN
  69. #endif
  70. // API key for the Fresnel API.
  71. #if !defined(GOOGLE_API_KEY_FRESNEL)
  72. #define GOOGLE_API_KEY_FRESNEL DUMMY_API_TOKEN
  73. #endif
  74. // These are used as shortcuts for developers and users providing
  75. // OAuth credentials via preprocessor defines or environment
  76. // variables. If set, they will be used to replace any of the client
  77. // IDs and secrets above that have not been set (and only those; they
  78. // will not override already-set values).
  79. #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
  80. #define GOOGLE_DEFAULT_CLIENT_ID ""
  81. #endif
  82. #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
  83. #define GOOGLE_DEFAULT_CLIENT_SECRET ""
  84. #endif
  85. namespace google_apis {
  86. const char kAPIKeysDevelopersHowToURL[] =
  87. "https://www.chromium.org/developers/how-tos/api-keys";
  88. // This is used as a lazy instance to determine keys once and cache them.
  89. class APIKeyCache {
  90. public:
  91. APIKeyCache() {
  92. std::unique_ptr<base::Environment> environment(base::Environment::Create());
  93. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  94. GaiaConfig* gaia_config = GaiaConfig::GetInstance();
  95. api_key_ = CalculateKeyValue(
  96. GOOGLE_API_KEY, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY), nullptr,
  97. std::string(), environment.get(), command_line, gaia_config);
  98. // A special non-stable key is at the moment defined only for Android Chrome.
  99. #if BUILDFLAG(IS_ANDROID)
  100. api_key_non_stable_ = CalculateKeyValue(
  101. GOOGLE_API_KEY_ANDROID_NON_STABLE,
  102. STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_ANDROID_NON_STABLE), nullptr,
  103. std::string(), environment.get(), command_line, gaia_config);
  104. #else
  105. api_key_non_stable_ = api_key_;
  106. #endif
  107. api_key_remoting_ = CalculateKeyValue(
  108. GOOGLE_API_KEY_REMOTING,
  109. STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_REMOTING), nullptr, std::string(),
  110. environment.get(), command_line, gaia_config);
  111. api_key_sharing_ = CalculateKeyValue(
  112. GOOGLE_API_KEY_SHARING, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SHARING),
  113. nullptr, std::string(), environment.get(), command_line, gaia_config);
  114. api_key_soda_ = CalculateKeyValue(
  115. GOOGLE_API_KEY_SODA, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SODA),
  116. nullptr, std::string(), environment.get(), command_line, gaia_config);
  117. api_key_read_aloud_ = CalculateKeyValue(
  118. GOOGLE_API_KEY_READ_ALOUD,
  119. STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_READ_ALOUD), nullptr,
  120. std::string(), environment.get(), command_line, gaia_config);
  121. api_key_fresnel_ = CalculateKeyValue(
  122. GOOGLE_API_KEY_FRESNEL, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_FRESNEL),
  123. nullptr, std::string(), environment.get(), command_line, gaia_config);
  124. metrics_key_ = CalculateKeyValue(
  125. GOOGLE_METRICS_SIGNING_KEY,
  126. STRINGIZE_NO_EXPANSION(GOOGLE_METRICS_SIGNING_KEY), nullptr,
  127. std::string(), environment.get(), command_line, gaia_config);
  128. std::string default_client_id = CalculateKeyValue(
  129. GOOGLE_DEFAULT_CLIENT_ID,
  130. STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID), nullptr,
  131. std::string(), environment.get(), command_line, gaia_config);
  132. std::string default_client_secret = CalculateKeyValue(
  133. GOOGLE_DEFAULT_CLIENT_SECRET,
  134. STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET), nullptr,
  135. std::string(), environment.get(), command_line, gaia_config);
  136. // We currently only allow overriding the baked-in values for the
  137. // default OAuth2 client ID and secret using a command-line
  138. // argument and gaia config, since that is useful to enable testing against
  139. // staging servers, and since that was what was possible and
  140. // likely practiced by the QA team before this implementation was
  141. // written.
  142. client_ids_[CLIENT_MAIN] = CalculateKeyValue(
  143. GOOGLE_CLIENT_ID_MAIN, STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN),
  144. ::switches::kOAuth2ClientID, default_client_id, environment.get(),
  145. command_line, gaia_config);
  146. client_secrets_[CLIENT_MAIN] = CalculateKeyValue(
  147. GOOGLE_CLIENT_SECRET_MAIN,
  148. STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN),
  149. ::switches::kOAuth2ClientSecret, default_client_secret,
  150. environment.get(), command_line, gaia_config);
  151. client_ids_[CLIENT_REMOTING] = CalculateKeyValue(
  152. GOOGLE_CLIENT_ID_REMOTING,
  153. STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING), nullptr,
  154. default_client_id, environment.get(), command_line, gaia_config);
  155. client_secrets_[CLIENT_REMOTING] = CalculateKeyValue(
  156. GOOGLE_CLIENT_SECRET_REMOTING,
  157. STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING), nullptr,
  158. default_client_secret, environment.get(), command_line, gaia_config);
  159. client_ids_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
  160. GOOGLE_CLIENT_ID_REMOTING_HOST,
  161. STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST), nullptr,
  162. default_client_id, environment.get(), command_line, gaia_config);
  163. client_secrets_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
  164. GOOGLE_CLIENT_SECRET_REMOTING_HOST,
  165. STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST), nullptr,
  166. default_client_secret, environment.get(), command_line, gaia_config);
  167. }
  168. std::string api_key() const { return api_key_; }
  169. #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA)
  170. void set_api_key(const std::string& api_key) { api_key_ = api_key; }
  171. #endif
  172. std::string api_key_non_stable() const { return api_key_non_stable_; }
  173. std::string api_key_remoting() const { return api_key_remoting_; }
  174. std::string api_key_sharing() const { return api_key_sharing_; }
  175. std::string api_key_soda() const { return api_key_soda_; }
  176. std::string api_key_read_aloud() const { return api_key_read_aloud_; }
  177. std::string api_key_fresnel() const { return api_key_fresnel_; }
  178. std::string metrics_key() const { return metrics_key_; }
  179. std::string GetClientID(OAuth2Client client) const {
  180. DCHECK_LT(client, CLIENT_NUM_ITEMS);
  181. return client_ids_[client];
  182. }
  183. #if BUILDFLAG(IS_IOS)
  184. void SetClientID(OAuth2Client client, const std::string& client_id) {
  185. client_ids_[client] = client_id;
  186. }
  187. #endif
  188. std::string GetClientSecret(OAuth2Client client) const {
  189. DCHECK_LT(client, CLIENT_NUM_ITEMS);
  190. return client_secrets_[client];
  191. }
  192. #if BUILDFLAG(IS_IOS)
  193. void SetClientSecret(OAuth2Client client, const std::string& client_secret) {
  194. client_secrets_[client] = client_secret;
  195. }
  196. #endif
  197. std::string GetSpdyProxyAuthValue() {
  198. #if defined(SPDY_PROXY_AUTH_VALUE)
  199. return SPDY_PROXY_AUTH_VALUE;
  200. #else
  201. return std::string();
  202. #endif
  203. }
  204. private:
  205. // Gets a value for a key. In priority order, this will be the value
  206. // provided via:
  207. // 1. Command-line switch
  208. // 2. Config file
  209. // 3. Environment variable
  210. // 4. Baked into the build
  211. // |command_line_switch| may be NULL. Official Google Chrome builds will not
  212. // use the value provided by an environment variable.
  213. static std::string CalculateKeyValue(const char* baked_in_value,
  214. const char* environment_variable_name,
  215. const char* command_line_switch,
  216. const std::string& default_if_unset,
  217. base::Environment* environment,
  218. base::CommandLine* command_line,
  219. GaiaConfig* gaia_config) {
  220. std::string key_value = baked_in_value;
  221. std::string temp;
  222. #if BUILDFLAG(IS_APPLE)
  223. // macOS and iOS can also override the API key with a value from the
  224. // Info.plist.
  225. temp = ::google_apis::GetAPIKeyFromInfoPlist(environment_variable_name);
  226. if (!temp.empty()) {
  227. key_value = temp;
  228. VLOG(1) << "Overriding API key " << environment_variable_name
  229. << " with value " << key_value << " from Info.plist.";
  230. }
  231. #endif
  232. #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
  233. // Don't allow using the environment to override API keys for official
  234. // Google Chrome builds. There have been reports of mangled environments
  235. // affecting users (crbug.com/710575).
  236. if (environment->GetVar(environment_variable_name, &temp)) {
  237. key_value = temp;
  238. VLOG(1) << "Overriding API key " << environment_variable_name
  239. << " with value " << key_value << " from environment variable.";
  240. }
  241. #endif
  242. if (gaia_config &&
  243. gaia_config->GetAPIKeyIfExists(environment_variable_name, &temp)) {
  244. key_value = temp;
  245. VLOG(1) << "Overriding API key " << environment_variable_name
  246. << " with value " << key_value << " from gaia config.";
  247. }
  248. if (command_line_switch && command_line->HasSwitch(command_line_switch)) {
  249. key_value = command_line->GetSwitchValueASCII(command_line_switch);
  250. VLOG(1) << "Overriding API key " << environment_variable_name
  251. << " with value " << key_value << " from command-line switch.";
  252. }
  253. if (key_value == DUMMY_API_TOKEN) {
  254. #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_FUCHSIA)
  255. // No key should be unset in an official build except the
  256. // GOOGLE_DEFAULT_* keys. The default keys don't trigger this
  257. // check as their "unset" value is not DUMMY_API_TOKEN.
  258. // Exclude Fuchsia to match BUILD.gn.
  259. // TODO(crbug.com/1171510): Update Fuchsia exclusion when bug is fixed.
  260. CHECK(false);
  261. #endif
  262. if (default_if_unset.size() > 0) {
  263. VLOG(1) << "Using default value \"" << default_if_unset
  264. << "\" for API key " << environment_variable_name;
  265. key_value = default_if_unset;
  266. }
  267. }
  268. // This should remain a debug-only log.
  269. DVLOG(1) << "API key " << environment_variable_name << "=" << key_value;
  270. return key_value;
  271. }
  272. std::string api_key_;
  273. std::string api_key_non_stable_;
  274. std::string api_key_remoting_;
  275. std::string api_key_sharing_;
  276. std::string api_key_soda_;
  277. std::string api_key_read_aloud_;
  278. std::string api_key_fresnel_;
  279. std::string metrics_key_;
  280. std::string client_ids_[CLIENT_NUM_ITEMS];
  281. std::string client_secrets_[CLIENT_NUM_ITEMS];
  282. };
  283. static base::LazyInstance<APIKeyCache>::DestructorAtExit g_api_key_cache =
  284. LAZY_INSTANCE_INITIALIZER;
  285. bool HasAPIKeyConfigured() {
  286. return GetAPIKey() != DUMMY_API_TOKEN;
  287. }
  288. std::string GetAPIKey() {
  289. return g_api_key_cache.Get().api_key();
  290. }
  291. std::string GetNonStableAPIKey() {
  292. return g_api_key_cache.Get().api_key_non_stable();
  293. }
  294. std::string GetRemotingAPIKey() {
  295. return g_api_key_cache.Get().api_key_remoting();
  296. }
  297. std::string GetSharingAPIKey() {
  298. return g_api_key_cache.Get().api_key_sharing();
  299. }
  300. std::string GetSodaAPIKey() {
  301. return g_api_key_cache.Get().api_key_soda();
  302. }
  303. std::string GetReadAloudAPIKey() {
  304. return g_api_key_cache.Get().api_key_read_aloud();
  305. }
  306. std::string GetFresnelAPIKey() {
  307. return g_api_key_cache.Get().api_key_fresnel();
  308. }
  309. #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA)
  310. void SetAPIKey(const std::string& api_key) {
  311. g_api_key_cache.Get().set_api_key(api_key);
  312. }
  313. #endif
  314. std::string GetMetricsKey() {
  315. return g_api_key_cache.Get().metrics_key();
  316. }
  317. bool HasOAuthClientConfigured() {
  318. for (size_t client_id = 0; client_id < CLIENT_NUM_ITEMS; ++client_id) {
  319. OAuth2Client client = static_cast<OAuth2Client>(client_id);
  320. if (GetOAuth2ClientID(client) == DUMMY_API_TOKEN ||
  321. GetOAuth2ClientSecret(client) == DUMMY_API_TOKEN) {
  322. return false;
  323. }
  324. }
  325. return true;
  326. }
  327. std::string GetOAuth2ClientID(OAuth2Client client) {
  328. return g_api_key_cache.Get().GetClientID(client);
  329. }
  330. std::string GetOAuth2ClientSecret(OAuth2Client client) {
  331. return g_api_key_cache.Get().GetClientSecret(client);
  332. }
  333. #if BUILDFLAG(IS_IOS)
  334. void SetOAuth2ClientID(OAuth2Client client, const std::string& client_id) {
  335. g_api_key_cache.Get().SetClientID(client, client_id);
  336. }
  337. void SetOAuth2ClientSecret(OAuth2Client client,
  338. const std::string& client_secret) {
  339. g_api_key_cache.Get().SetClientSecret(client, client_secret);
  340. }
  341. #endif
  342. std::string GetSpdyProxyAuthValue() {
  343. return g_api_key_cache.Get().GetSpdyProxyAuthValue();
  344. }
  345. bool IsGoogleChromeAPIKeyUsed() {
  346. #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
  347. return true;
  348. #else
  349. return false;
  350. #endif
  351. }
  352. } // namespace google_apis