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 // TODO(joi): Can we enable this warning without having it treated as
21 // an error? We don't want to fail builds, just warn, but all warnings
22 // from the preprocessor are currently treated as errors, at least in
25 #if !defined(GOOGLE_API_KEY) && ( \
26 (!defined(GOOGLE_DEFAULT_CLIENT_ID) && \
27 !defined(GOOGLE_DEFAULT_CLIENT_SECRET)) \
29 (!defined(GOOGLE_CLIENT_ID_MAIN) && \
30 !defined(GOOGLE_CLIENT_SECRET_MAIN)))
31 #warning You have not specified API keys; some features may not work.
32 #warning See www.chromium.org/developers/how-tos/api-keys for details.
33 #endif // (API keys unset)
36 // Used to indicate an unset key/id/secret. This works better with
37 // various unit tests than leaving the token empty.
38 #define DUMMY_API_TOKEN "dummytoken"
40 #if !defined(GOOGLE_API_KEY)
41 #define GOOGLE_API_KEY DUMMY_API_TOKEN
44 #if !defined(GOOGLE_CLIENT_ID_MAIN)
45 #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
48 #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
49 #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
52 #if !defined(GOOGLE_CLIENT_ID_CLOUD_PRINT)
53 #define GOOGLE_CLIENT_ID_CLOUD_PRINT DUMMY_API_TOKEN
56 #if !defined(GOOGLE_CLIENT_SECRET_CLOUD_PRINT)
57 #define GOOGLE_CLIENT_SECRET_CLOUD_PRINT DUMMY_API_TOKEN
60 #if !defined(GOOGLE_CLIENT_ID_REMOTING)
61 #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
64 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
65 #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
68 // These are used as shortcuts for developers and users providing
69 // OAuth credentials via preprocessor defines or environment
70 // variables. If set, they will be used to replace any of the client
71 // IDs and secrets above that have not been set (and only those; they
72 // will not override already-set values).
73 #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
74 #define GOOGLE_DEFAULT_CLIENT_ID ""
76 #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
77 #define GOOGLE_DEFAULT_CLIENT_SECRET ""
82 // Specifies custom OAuth2 client id for testing purposes.
83 const char kOAuth2ClientID
[] = "oauth2-client-id";
85 // Specifies custom OAuth2 client secret for testing purposes.
86 const char kOAuth2ClientSecret
[] = "oauth2-client-secret";
88 } // namespace switches
90 namespace google_apis
{
92 // This is used as a lazy instance to determine keys once and cache them.
96 scoped_ptr
<base::Environment
> environment(base::Environment::Create());
97 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
99 api_key_
= CalculateKeyValue(GOOGLE_API_KEY
,
100 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY
),
106 std::string default_client_id
=
107 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_ID
,
108 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID
),
113 std::string default_client_secret
=
114 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_SECRET
,
115 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET
),
121 // We currently only allow overriding the baked-in values for the
122 // default OAuth2 client ID and secret using a command-line
123 // argument, since that is useful to enable testing against
124 // staging servers, and since that was what was possible and
125 // likely practiced by the QA team before this implementation was
127 client_ids_
[CLIENT_MAIN
] = CalculateKeyValue(
128 GOOGLE_CLIENT_ID_MAIN
,
129 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN
),
130 switches::kOAuth2ClientID
,
134 client_secrets_
[CLIENT_MAIN
] = CalculateKeyValue(
135 GOOGLE_CLIENT_SECRET_MAIN
,
136 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN
),
137 switches::kOAuth2ClientSecret
,
138 default_client_secret
,
142 client_ids_
[CLIENT_CLOUD_PRINT
] = CalculateKeyValue(
143 GOOGLE_CLIENT_ID_CLOUD_PRINT
,
144 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_CLOUD_PRINT
),
149 client_secrets_
[CLIENT_CLOUD_PRINT
] = CalculateKeyValue(
150 GOOGLE_CLIENT_SECRET_CLOUD_PRINT
,
151 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_CLOUD_PRINT
),
153 default_client_secret
,
157 client_ids_
[CLIENT_REMOTING
] = CalculateKeyValue(
158 GOOGLE_CLIENT_ID_REMOTING
,
159 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING
),
164 client_secrets_
[CLIENT_REMOTING
] = CalculateKeyValue(
165 GOOGLE_CLIENT_SECRET_REMOTING
,
166 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING
),
168 default_client_secret
,
173 std::string
api_key() const { return api_key_
; }
175 std::string
GetClientID(OAuth2Client client
) const {
176 DCHECK_LT(client
, CLIENT_NUM_ITEMS
);
177 return client_ids_
[client
];
180 std::string
GetClientSecret(OAuth2Client client
) const {
181 DCHECK_LT(client
, CLIENT_NUM_ITEMS
);
182 return client_secrets_
[client
];
186 // Gets a value for a key. In priority order, this will be the value
187 // provided via a command-line switch, the value provided via an
188 // environment variable, or finally a value baked into the build.
189 // |command_line_switch| may be NULL.
190 static std::string
CalculateKeyValue(const char* baked_in_value
,
191 const char* environment_variable_name
,
192 const char* command_line_switch
,
193 const std::string
& default_if_unset
,
194 base::Environment
* environment
,
195 CommandLine
* command_line
) {
196 std::string key_value
= baked_in_value
;
198 if (environment
->GetVar(environment_variable_name
, &temp
)) {
200 LOG(INFO
) << "Overriding API key " << environment_variable_name
201 << " with value " << key_value
<< " from environment variable.";
204 if (command_line_switch
&& command_line
->HasSwitch(command_line_switch
)) {
205 key_value
= command_line
->GetSwitchValueASCII(command_line_switch
);
206 LOG(INFO
) << "Overriding API key " << environment_variable_name
207 << " with value " << key_value
<< " from command-line switch.";
210 if (key_value
== DUMMY_API_TOKEN
) {
211 #if defined(GOOGLE_CHROME_BUILD)
212 // No key should be unset in an official build except the
213 // GOOGLE_DEFAULT_* keys. The default keys don't trigger this
214 // check as their "unset" value is not DUMMY_API_TOKEN.
217 if (default_if_unset
.size() > 0) {
218 LOG(INFO
) << "Using default value \"" << default_if_unset
219 << "\" for API key " << environment_variable_name
;
220 key_value
= default_if_unset
;
224 // This should remain a debug-only log.
225 DVLOG(1) << "API key " << environment_variable_name
<< "=" << key_value
;
230 std::string api_key_
;
231 std::string client_ids_
[CLIENT_NUM_ITEMS
];
232 std::string client_secrets_
[CLIENT_NUM_ITEMS
];
235 static base::LazyInstance
<APIKeyCache
> g_api_key_cache
=
236 LAZY_INSTANCE_INITIALIZER
;
238 std::string
GetAPIKey() {
239 return g_api_key_cache
.Get().api_key();
242 std::string
GetOAuth2ClientID(OAuth2Client client
) {
243 return g_api_key_cache
.Get().GetClientID(client
);
246 std::string
GetOAuth2ClientSecret(OAuth2Client client
) {
247 return g_api_key_cache
.Get().GetClientSecret(client
);
250 } // namespace google_apis