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.
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.
9 #include "base/command_line.h"
10 #include "base/environment.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/stringize_macros.h"
16 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_OFFICIAL_GOOGLE_API_KEYS)
17 #include "google_apis/internal/google_chrome_api_keys.h"
20 // Used to indicate an unset key/id/secret. This works better with
21 // various unit tests than leaving the token empty.
22 #define DUMMY_API_TOKEN "dummytoken"
24 #if !defined(GOOGLE_API_KEY)
25 #define GOOGLE_API_KEY DUMMY_API_TOKEN
28 #if !defined(GOOGLE_CLIENT_ID_MAIN)
29 #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
32 #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
33 #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
36 #if !defined(GOOGLE_CLIENT_ID_CLOUD_PRINT)
37 #define GOOGLE_CLIENT_ID_CLOUD_PRINT DUMMY_API_TOKEN
40 #if !defined(GOOGLE_CLIENT_SECRET_CLOUD_PRINT)
41 #define GOOGLE_CLIENT_SECRET_CLOUD_PRINT DUMMY_API_TOKEN
44 #if !defined(GOOGLE_CLIENT_ID_REMOTING)
45 #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
48 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
49 #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
52 #if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
53 #define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
56 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
57 #define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
60 // These are used as shortcuts for developers and users providing
61 // OAuth credentials via preprocessor defines or environment
62 // variables. If set, they will be used to replace any of the client
63 // IDs and secrets above that have not been set (and only those; they
64 // will not override already-set values).
65 #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
66 #define GOOGLE_DEFAULT_CLIENT_ID ""
68 #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
69 #define GOOGLE_DEFAULT_CLIENT_SECRET ""
74 // Specifies custom OAuth2 client id for testing purposes.
75 const char kOAuth2ClientID
[] = "oauth2-client-id";
77 // Specifies custom OAuth2 client secret for testing purposes.
78 const char kOAuth2ClientSecret
[] = "oauth2-client-secret";
80 } // namespace switches
82 namespace google_apis
{
84 // This is used as a lazy instance to determine keys once and cache them.
88 scoped_ptr
<base::Environment
> environment(base::Environment::Create());
89 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
91 api_key_
= CalculateKeyValue(GOOGLE_API_KEY
,
92 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY
),
98 std::string default_client_id
=
99 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_ID
,
100 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID
),
105 std::string default_client_secret
=
106 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_SECRET
,
107 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET
),
113 // We currently only allow overriding the baked-in values for the
114 // default OAuth2 client ID and secret using a command-line
115 // argument, since that is useful to enable testing against
116 // staging servers, and since that was what was possible and
117 // likely practiced by the QA team before this implementation was
119 client_ids_
[CLIENT_MAIN
] = CalculateKeyValue(
120 GOOGLE_CLIENT_ID_MAIN
,
121 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN
),
122 switches::kOAuth2ClientID
,
126 client_secrets_
[CLIENT_MAIN
] = CalculateKeyValue(
127 GOOGLE_CLIENT_SECRET_MAIN
,
128 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN
),
129 switches::kOAuth2ClientSecret
,
130 default_client_secret
,
134 client_ids_
[CLIENT_CLOUD_PRINT
] = CalculateKeyValue(
135 GOOGLE_CLIENT_ID_CLOUD_PRINT
,
136 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_CLOUD_PRINT
),
141 client_secrets_
[CLIENT_CLOUD_PRINT
] = CalculateKeyValue(
142 GOOGLE_CLIENT_SECRET_CLOUD_PRINT
,
143 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_CLOUD_PRINT
),
145 default_client_secret
,
149 client_ids_
[CLIENT_REMOTING
] = CalculateKeyValue(
150 GOOGLE_CLIENT_ID_REMOTING
,
151 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING
),
156 client_secrets_
[CLIENT_REMOTING
] = CalculateKeyValue(
157 GOOGLE_CLIENT_SECRET_REMOTING
,
158 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING
),
160 default_client_secret
,
164 client_ids_
[CLIENT_REMOTING_HOST
] = CalculateKeyValue(
165 GOOGLE_CLIENT_ID_REMOTING_HOST
,
166 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST
),
171 client_secrets_
[CLIENT_REMOTING_HOST
] = CalculateKeyValue(
172 GOOGLE_CLIENT_SECRET_REMOTING_HOST
,
173 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST
),
175 default_client_secret
,
180 std::string
api_key() const { return api_key_
; }
182 std::string
GetClientID(OAuth2Client client
) const {
183 DCHECK_LT(client
, CLIENT_NUM_ITEMS
);
184 return client_ids_
[client
];
187 std::string
GetClientSecret(OAuth2Client client
) const {
188 DCHECK_LT(client
, CLIENT_NUM_ITEMS
);
189 return client_secrets_
[client
];
193 // Gets a value for a key. In priority order, this will be the value
194 // provided via a command-line switch, the value provided via an
195 // environment variable, or finally a value baked into the build.
196 // |command_line_switch| may be NULL.
197 static std::string
CalculateKeyValue(const char* baked_in_value
,
198 const char* environment_variable_name
,
199 const char* command_line_switch
,
200 const std::string
& default_if_unset
,
201 base::Environment
* environment
,
202 CommandLine
* command_line
) {
203 std::string key_value
= baked_in_value
;
205 if (environment
->GetVar(environment_variable_name
, &temp
)) {
207 VLOG(1) << "Overriding API key " << environment_variable_name
208 << " with value " << key_value
<< " from environment variable.";
211 if (command_line_switch
&& command_line
->HasSwitch(command_line_switch
)) {
212 key_value
= command_line
->GetSwitchValueASCII(command_line_switch
);
213 VLOG(1) << "Overriding API key " << environment_variable_name
214 << " with value " << key_value
<< " from command-line switch.";
217 if (key_value
== DUMMY_API_TOKEN
) {
218 #if defined(GOOGLE_CHROME_BUILD)
219 // No key should be unset in an official build except the
220 // GOOGLE_DEFAULT_* keys. The default keys don't trigger this
221 // check as their "unset" value is not DUMMY_API_TOKEN.
224 if (default_if_unset
.size() > 0) {
225 VLOG(1) << "Using default value \"" << default_if_unset
226 << "\" for API key " << environment_variable_name
;
227 key_value
= default_if_unset
;
231 // This should remain a debug-only log.
232 DVLOG(1) << "API key " << environment_variable_name
<< "=" << key_value
;
237 std::string api_key_
;
238 std::string client_ids_
[CLIENT_NUM_ITEMS
];
239 std::string client_secrets_
[CLIENT_NUM_ITEMS
];
242 static base::LazyInstance
<APIKeyCache
> g_api_key_cache
=
243 LAZY_INSTANCE_INITIALIZER
;
245 bool HasKeysConfigured() {
246 if (GetAPIKey() == DUMMY_API_TOKEN
)
249 for (size_t client_id
= 0; client_id
< CLIENT_NUM_ITEMS
; ++client_id
) {
250 OAuth2Client client
= static_cast<OAuth2Client
>(client_id
);
251 if (GetOAuth2ClientID(client
) == DUMMY_API_TOKEN
||
252 GetOAuth2ClientSecret(client
) == DUMMY_API_TOKEN
) {
260 std::string
GetAPIKey() {
261 return g_api_key_cache
.Get().api_key();
264 std::string
GetOAuth2ClientID(OAuth2Client client
) {
265 return g_api_key_cache
.Get().GetClientID(client
);
268 std::string
GetOAuth2ClientSecret(OAuth2Client client
) {
269 return g_api_key_cache
.Get().GetClientSecret(client
);
272 } // namespace google_apis