1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "google_apis/google_api_keys.h"
7 // If you add more includes to this list, you also need to add them to
8 // google_api_keys_unittest.cc and google_api_keys_mac_unittest.mm.
15 #include "base/command_line.h"
16 #include "base/environment.h"
17 #include "base/lazy_instance.h"
18 #include "base/logging.h"
19 #include "base/strings/stringize_macros.h"
20 #include "build/branding_buildflags.h"
21 #include "google_apis/buildflags.h"
22 #include "google_apis/gaia/gaia_config.h"
23 #include "google_apis/gaia/gaia_switches.h"
25 #if BUILDFLAG(IS_APPLE)
26 #include "google_apis/google_api_keys_mac.h"
29 #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
30 #include "google_apis/internal/google_chrome_api_keys.h"
31 #include "google_apis/internal/metrics_signing_key.h"
34 // Used to indicate an unset key/id/secret. This works better with
35 // various unit tests than leaving the token empty.
36 #define DUMMY_API_TOKEN "dummytoken"
38 #if !defined(GOOGLE_API_KEY)
39 #define GOOGLE_API_KEY DUMMY_API_TOKEN
42 #if !defined(GOOGLE_METRICS_SIGNING_KEY)
43 #define GOOGLE_METRICS_SIGNING_KEY DUMMY_API_TOKEN
46 #if !defined(GOOGLE_CLIENT_ID_MAIN)
47 #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
50 #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
51 #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
54 #if !defined(GOOGLE_CLIENT_ID_REMOTING)
55 #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
58 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
59 #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
62 #if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
63 #define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
66 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
67 #define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
70 #if !defined(GOOGLE_API_KEY_ANDROID_NON_STABLE)
71 #define GOOGLE_API_KEY_ANDROID_NON_STABLE DUMMY_API_TOKEN
74 #if !defined(GOOGLE_API_KEY_REMOTING)
75 #define GOOGLE_API_KEY_REMOTING DUMMY_API_TOKEN
78 // API key for SharingService.
79 #if !defined(GOOGLE_API_KEY_SHARING)
80 #define GOOGLE_API_KEY_SHARING DUMMY_API_TOKEN
83 // API key for the Speech On-Device API (SODA).
84 #if !defined(GOOGLE_API_KEY_SODA)
85 #define GOOGLE_API_KEY_SODA DUMMY_API_TOKEN
88 // API key for the ReadAloud API.
89 #if !defined(GOOGLE_API_KEY_READ_ALOUD)
90 #define GOOGLE_API_KEY_READ_ALOUD DUMMY_API_TOKEN
93 // API key for the Fresnel API.
94 #if !defined(GOOGLE_API_KEY_FRESNEL)
95 #define GOOGLE_API_KEY_FRESNEL DUMMY_API_TOKEN
98 // These are used as shortcuts for developers and users providing
99 // OAuth credentials via preprocessor defines or environment
100 // variables. If set, they will be used to replace any of the client
101 // IDs and secrets above that have not been set (and only those; they
102 // will not override already-set values).
103 #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
104 #define GOOGLE_DEFAULT_CLIENT_ID ""
106 #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
107 #define GOOGLE_DEFAULT_CLIENT_SECRET ""
110 namespace google_apis {
112 const char kAPIKeysDevelopersHowToURL[] =
113 "https://www.chromium.org/developers/how-tos/api-keys";
115 // This is used as a lazy instance to determine keys once and cache them.
119 std::unique_ptr<base::Environment> environment(base::Environment::Create());
120 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
121 GaiaConfig* gaia_config = GaiaConfig::GetInstance();
123 api_key_ = CalculateKeyValue(
124 GOOGLE_API_KEY, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY), nullptr,
125 std::string(), environment.get(), command_line, gaia_config);
127 // A special non-stable key is at the moment defined only for Android Chrome.
128 #if BUILDFLAG(IS_ANDROID)
129 api_key_non_stable_ = CalculateKeyValue(
130 GOOGLE_API_KEY_ANDROID_NON_STABLE,
131 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_ANDROID_NON_STABLE), nullptr,
132 std::string(), environment.get(), command_line, gaia_config);
134 api_key_non_stable_ = api_key_;
137 api_key_remoting_ = CalculateKeyValue(
138 GOOGLE_API_KEY_REMOTING,
139 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_REMOTING), nullptr, std::string(),
140 environment.get(), command_line, gaia_config);
142 api_key_sharing_ = CalculateKeyValue(
143 GOOGLE_API_KEY_SHARING, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SHARING),
144 nullptr, std::string(), environment.get(), command_line, gaia_config);
146 api_key_soda_ = CalculateKeyValue(
147 GOOGLE_API_KEY_SODA, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_SODA),
148 nullptr, std::string(), environment.get(), command_line, gaia_config);
150 api_key_read_aloud_ = CalculateKeyValue(
151 GOOGLE_API_KEY_READ_ALOUD,
152 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_READ_ALOUD), nullptr,
153 std::string(), environment.get(), command_line, gaia_config);
155 api_key_fresnel_ = CalculateKeyValue(
156 GOOGLE_API_KEY_FRESNEL, STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY_FRESNEL),
157 nullptr, std::string(), environment.get(), command_line, gaia_config);
159 metrics_key_ = CalculateKeyValue(
160 GOOGLE_METRICS_SIGNING_KEY,
161 STRINGIZE_NO_EXPANSION(GOOGLE_METRICS_SIGNING_KEY), nullptr,
162 std::string(), environment.get(), command_line, gaia_config);
164 std::string default_client_id = CalculateKeyValue(
165 GOOGLE_DEFAULT_CLIENT_ID,
166 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID), nullptr,
167 std::string(), environment.get(), command_line, gaia_config);
168 std::string default_client_secret = CalculateKeyValue(
169 GOOGLE_DEFAULT_CLIENT_SECRET,
170 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET), nullptr,
171 std::string(), environment.get(), command_line, gaia_config);
173 // We currently only allow overriding the baked-in values for the
174 // default OAuth2 client ID and secret using a command-line
175 // argument and gaia config, since that is useful to enable testing against
176 // staging servers, and since that was what was possible and
177 // likely practiced by the QA team before this implementation was
179 client_ids_[CLIENT_MAIN] = CalculateKeyValue(
180 GOOGLE_CLIENT_ID_MAIN, STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN),
181 ::switches::kOAuth2ClientID, default_client_id, environment.get(),
182 command_line, gaia_config);
183 client_secrets_[CLIENT_MAIN] = CalculateKeyValue(
184 GOOGLE_CLIENT_SECRET_MAIN,
185 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN),
186 ::switches::kOAuth2ClientSecret, default_client_secret,
187 environment.get(), command_line, gaia_config);
189 client_ids_[CLIENT_REMOTING] = CalculateKeyValue(
190 GOOGLE_CLIENT_ID_REMOTING,
191 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING), nullptr,
192 default_client_id, environment.get(), command_line, gaia_config);
193 client_secrets_[CLIENT_REMOTING] = CalculateKeyValue(
194 GOOGLE_CLIENT_SECRET_REMOTING,
195 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING), nullptr,
196 default_client_secret, environment.get(), command_line, gaia_config);
198 client_ids_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
199 GOOGLE_CLIENT_ID_REMOTING_HOST,
200 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST), nullptr,
201 default_client_id, environment.get(), command_line, gaia_config);
202 client_secrets_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
203 GOOGLE_CLIENT_SECRET_REMOTING_HOST,
204 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST), nullptr,
205 default_client_secret, environment.get(), command_line, gaia_config);
208 std::string api_key() const { return api_key_; }
209 #if BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)
210 void set_api_key(const std::string& api_key) { api_key_ = api_key; }
212 std::string api_key_non_stable() const { return api_key_non_stable_; }
213 std::string api_key_remoting() const { return api_key_remoting_; }
214 std::string api_key_sharing() const { return api_key_sharing_; }
215 std::string api_key_soda() const { return api_key_soda_; }
216 std::string api_key_read_aloud() const { return api_key_read_aloud_; }
217 std::string api_key_fresnel() const { return api_key_fresnel_; }
219 std::string metrics_key() const { return metrics_key_; }
221 std::string GetClientID(OAuth2Client client) const {
222 DCHECK_LT(client, CLIENT_NUM_ITEMS);
223 return client_ids_[client];
226 #if BUILDFLAG(IS_IOS)
227 void SetClientID(OAuth2Client client, const std::string& client_id) {
228 client_ids_[client] = client_id;
232 std::string GetClientSecret(OAuth2Client client) const {
233 DCHECK_LT(client, CLIENT_NUM_ITEMS);
234 return client_secrets_[client];
237 #if BUILDFLAG(IS_IOS)
238 void SetClientSecret(OAuth2Client client, const std::string& client_secret) {
239 client_secrets_[client] = client_secret;
243 std::string GetSpdyProxyAuthValue() {
244 #if defined(SPDY_PROXY_AUTH_VALUE)
245 return SPDY_PROXY_AUTH_VALUE;
247 return std::string();
252 // Gets a value for a key. In priority order, this will be the value
254 // 1. Command-line switch
256 // 3. Environment variable
257 // 4. Baked into the build
258 // |command_line_switch| may be NULL. Official Google Chrome builds will not
259 // use the value provided by an environment variable.
260 static std::string CalculateKeyValue(const char* baked_in_value,
261 const char* environment_variable_name,
262 const char* command_line_switch,
263 const std::string& default_if_unset,
264 base::Environment* environment,
265 base::CommandLine* command_line,
266 GaiaConfig* gaia_config) {
267 std::string key_value = baked_in_value;
269 #if BUILDFLAG(IS_APPLE)
270 // macOS and iOS can also override the API key with a value from the
272 temp = ::google_apis::GetAPIKeyFromInfoPlist(environment_variable_name);
275 VLOG(1) << "Overriding API key " << environment_variable_name
276 << " with value " << key_value << " from Info.plist.";
280 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
281 // Don't allow using the environment to override API keys for official
282 // Google Chrome builds. There have been reports of mangled environments
283 // affecting users (crbug.com/710575).
284 if (environment->GetVar(environment_variable_name, &temp)) {
286 VLOG(1) << "Overriding API key " << environment_variable_name
287 << " with value " << key_value << " from environment variable.";
292 gaia_config->GetAPIKeyIfExists(environment_variable_name, &temp)) {
294 VLOG(1) << "Overriding API key " << environment_variable_name
295 << " with value " << key_value << " from gaia config.";
298 if (command_line_switch && command_line->HasSwitch(command_line_switch)) {
299 key_value = command_line->GetSwitchValueASCII(command_line_switch);
300 VLOG(1) << "Overriding API key " << environment_variable_name
301 << " with value " << key_value << " from command-line switch.";
304 if (key_value == DUMMY_API_TOKEN) {
305 // TODO(crbug.com/1294915): Rewrite this condition using
306 // BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY).
307 #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_FUCHSIA)
308 // No key should be unset in an official build except the
309 // GOOGLE_DEFAULT_* keys. The default keys don't trigger this
310 // check as their "unset" value is not DUMMY_API_TOKEN.
313 if (default_if_unset.size() > 0) {
314 VLOG(1) << "Using default value \"" << default_if_unset
315 << "\" for API key " << environment_variable_name;
316 key_value = default_if_unset;
320 // This should remain a debug-only log.
321 DVLOG(1) << "API key " << environment_variable_name << "=" << key_value;
326 std::string api_key_;
327 std::string api_key_non_stable_;
328 std::string api_key_remoting_;
329 std::string api_key_sharing_;
330 std::string api_key_soda_;
331 std::string api_key_read_aloud_;
332 std::string api_key_fresnel_;
333 std::string metrics_key_;
334 std::string client_ids_[CLIENT_NUM_ITEMS];
335 std::string client_secrets_[CLIENT_NUM_ITEMS];
338 static base::LazyInstance<APIKeyCache>::DestructorAtExit g_api_key_cache =
339 LAZY_INSTANCE_INITIALIZER;
341 bool HasAPIKeyConfigured() {
342 return GetAPIKey() != DUMMY_API_TOKEN;
345 std::string GetAPIKey() {
346 return g_api_key_cache.Get().api_key();
349 std::string GetNonStableAPIKey() {
350 return g_api_key_cache.Get().api_key_non_stable();
353 std::string GetRemotingAPIKey() {
354 return g_api_key_cache.Get().api_key_remoting();
357 std::string GetSharingAPIKey() {
358 return g_api_key_cache.Get().api_key_sharing();
361 std::string GetSodaAPIKey() {
362 return g_api_key_cache.Get().api_key_soda();
365 std::string GetReadAloudAPIKey() {
366 return g_api_key_cache.Get().api_key_read_aloud();
369 std::string GetFresnelAPIKey() {
370 return g_api_key_cache.Get().api_key_fresnel();
373 #if BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)
374 void SetAPIKey(const std::string& api_key) {
375 g_api_key_cache.Get().set_api_key(api_key);
379 std::string GetMetricsKey() {
380 return g_api_key_cache.Get().metrics_key();
383 bool HasOAuthClientConfigured() {
384 for (size_t client_id = 0; client_id < CLIENT_NUM_ITEMS; ++client_id) {
385 OAuth2Client client = static_cast<OAuth2Client>(client_id);
386 if (GetOAuth2ClientID(client) == DUMMY_API_TOKEN ||
387 GetOAuth2ClientSecret(client) == DUMMY_API_TOKEN) {
395 std::string GetOAuth2ClientID(OAuth2Client client) {
396 return g_api_key_cache.Get().GetClientID(client);
399 std::string GetOAuth2ClientSecret(OAuth2Client client) {
400 return g_api_key_cache.Get().GetClientSecret(client);
403 #if BUILDFLAG(IS_IOS)
404 void SetOAuth2ClientID(OAuth2Client client, const std::string& client_id) {
405 g_api_key_cache.Get().SetClientID(client, client_id);
408 void SetOAuth2ClientSecret(OAuth2Client client,
409 const std::string& client_secret) {
410 g_api_key_cache.Get().SetClientSecret(client, client_secret);
414 std::string GetSpdyProxyAuthValue() {
415 return g_api_key_cache.Get().GetSpdyProxyAuthValue();
418 bool IsGoogleChromeAPIKeyUsed() {
419 #if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
426 } // namespace google_apis