blob: 2cf92fd0bf9ea623ff4f3e4e66c2a2c2dcafa032 [file] [log] [blame]
[email protected]e5e894ff2012-09-06 02:18:471// 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
[email protected]6386cf52012-09-07 04:26:375#include "google_apis/google_api_keys.h"
[email protected]e5e894ff2012-09-06 02:18:476
[email protected]e03604b2013-01-10 23:38:227// If you add more includes to this list, you also need to add them to
8// google_api_keys_unittest.cc.
[email protected]e5e894ff2012-09-06 02:18:479#include "base/command_line.h"
10#include "base/environment.h"
11#include "base/lazy_instance.h"
[email protected]b08bf822012-09-11 21:50:3812#include "base/logging.h"
[email protected]e5e894ff2012-09-06 02:18:4713#include "base/memory/scoped_ptr.h"
[email protected]8edbebd2013-01-31 19:45:0214#include "base/strings/stringize_macros.h"
[email protected]e5e894ff2012-09-06 02:18:4715
[email protected]d647e282012-09-13 13:10:1016#if defined(GOOGLE_CHROME_BUILD) || defined(USE_OFFICIAL_GOOGLE_API_KEYS)
[email protected]b08bf822012-09-11 21:50:3817#include "google_apis/internal/google_chrome_api_keys.h"
[email protected]e5e894ff2012-09-06 02:18:4718#endif
19
[email protected]d647e282012-09-13 13:10:1020// 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"
23
[email protected]e5e894ff2012-09-06 02:18:4724#if !defined(GOOGLE_API_KEY)
[email protected]1abac7a2013-01-31 14:01:2525#define GOOGLE_API_KEY DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4726#endif
27
28#if !defined(GOOGLE_CLIENT_ID_MAIN)
[email protected]fc2212d2012-09-17 17:33:2029#define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4730#endif
31
32#if !defined(GOOGLE_CLIENT_SECRET_MAIN)
[email protected]fc2212d2012-09-17 17:33:2033#define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4734#endif
35
36#if !defined(GOOGLE_CLIENT_ID_CLOUD_PRINT)
[email protected]fc2212d2012-09-17 17:33:2037#define GOOGLE_CLIENT_ID_CLOUD_PRINT DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4738#endif
39
40#if !defined(GOOGLE_CLIENT_SECRET_CLOUD_PRINT)
[email protected]fc2212d2012-09-17 17:33:2041#define GOOGLE_CLIENT_SECRET_CLOUD_PRINT DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4742#endif
43
44#if !defined(GOOGLE_CLIENT_ID_REMOTING)
[email protected]fc2212d2012-09-17 17:33:2045#define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4746#endif
47
48#if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
[email protected]fc2212d2012-09-17 17:33:2049#define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
[email protected]e5e894ff2012-09-06 02:18:4750#endif
51
[email protected]d66d81742013-08-16 05:18:3852#if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
53#define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
54#endif
55
56#if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
57#define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
58#endif
59
[email protected]e5e894ff2012-09-06 02:18:4760// 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)
[email protected]1abac7a2013-01-31 14:01:2566#define GOOGLE_DEFAULT_CLIENT_ID ""
[email protected]e5e894ff2012-09-06 02:18:4767#endif
68#if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
[email protected]1abac7a2013-01-31 14:01:2569#define GOOGLE_DEFAULT_CLIENT_SECRET ""
[email protected]e5e894ff2012-09-06 02:18:4770#endif
71
72namespace switches {
73
74// Specifies custom OAuth2 client id for testing purposes.
75const char kOAuth2ClientID[] = "oauth2-client-id";
76
77// Specifies custom OAuth2 client secret for testing purposes.
78const char kOAuth2ClientSecret[] = "oauth2-client-secret";
79
80} // namespace switches
81
82namespace google_apis {
83
[email protected]e5e894ff2012-09-06 02:18:4784// This is used as a lazy instance to determine keys once and cache them.
85class APIKeyCache {
86 public:
87 APIKeyCache() {
88 scoped_ptr<base::Environment> environment(base::Environment::Create());
89 CommandLine* command_line = CommandLine::ForCurrentProcess();
90
91 api_key_ = CalculateKeyValue(GOOGLE_API_KEY,
92 STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY),
[email protected]007b3f82013-04-09 08:46:4593 NULL,
94 std::string(),
[email protected]e5e894ff2012-09-06 02:18:4795 environment.get(),
96 command_line);
97
[email protected]007b3f82013-04-09 08:46:4598 std::string default_client_id =
99 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_ID,
100 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID),
101 NULL,
102 std::string(),
103 environment.get(),
104 command_line);
105 std::string default_client_secret =
106 CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_SECRET,
107 STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET),
108 NULL,
109 std::string(),
110 environment.get(),
111 command_line);
[email protected]e5e894ff2012-09-06 02:18:47112
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
118 // written.
119 client_ids_[CLIENT_MAIN] = CalculateKeyValue(
120 GOOGLE_CLIENT_ID_MAIN,
121 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN),
122 switches::kOAuth2ClientID,
123 default_client_id,
124 environment.get(),
125 command_line);
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,
131 environment.get(),
132 command_line);
133
134 client_ids_[CLIENT_CLOUD_PRINT] = CalculateKeyValue(
135 GOOGLE_CLIENT_ID_CLOUD_PRINT,
136 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_CLOUD_PRINT),
137 NULL,
138 default_client_id,
139 environment.get(),
140 command_line);
141 client_secrets_[CLIENT_CLOUD_PRINT] = CalculateKeyValue(
142 GOOGLE_CLIENT_SECRET_CLOUD_PRINT,
143 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_CLOUD_PRINT),
144 NULL,
145 default_client_secret,
146 environment.get(),
147 command_line);
148
149 client_ids_[CLIENT_REMOTING] = CalculateKeyValue(
150 GOOGLE_CLIENT_ID_REMOTING,
151 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING),
152 NULL,
153 default_client_id,
154 environment.get(),
155 command_line);
156 client_secrets_[CLIENT_REMOTING] = CalculateKeyValue(
157 GOOGLE_CLIENT_SECRET_REMOTING,
158 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING),
159 NULL,
160 default_client_secret,
161 environment.get(),
162 command_line);
[email protected]d66d81742013-08-16 05:18:38163
164 client_ids_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
165 GOOGLE_CLIENT_ID_REMOTING_HOST,
166 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST),
167 NULL,
168 default_client_id,
169 environment.get(),
170 command_line);
171 client_secrets_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
172 GOOGLE_CLIENT_SECRET_REMOTING_HOST,
173 STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST),
174 NULL,
175 default_client_secret,
176 environment.get(),
177 command_line);
[email protected]e5e894ff2012-09-06 02:18:47178 }
179
180 std::string api_key() const { return api_key_; }
181
182 std::string GetClientID(OAuth2Client client) const {
183 DCHECK_LT(client, CLIENT_NUM_ITEMS);
184 return client_ids_[client];
185 }
186
187 std::string GetClientSecret(OAuth2Client client) const {
188 DCHECK_LT(client, CLIENT_NUM_ITEMS);
189 return client_secrets_[client];
190 }
191
192 private:
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;
204 std::string temp;
[email protected]b08bf822012-09-11 21:50:38205 if (environment->GetVar(environment_variable_name, &temp)) {
[email protected]e5e894ff2012-09-06 02:18:47206 key_value = temp;
[email protected]94305332013-11-25 22:32:05207 VLOG(1) << "Overriding API key " << environment_variable_name
208 << " with value " << key_value << " from environment variable.";
[email protected]b08bf822012-09-11 21:50:38209 }
210
211 if (command_line_switch && command_line->HasSwitch(command_line_switch)) {
[email protected]e5e894ff2012-09-06 02:18:47212 key_value = command_line->GetSwitchValueASCII(command_line_switch);
[email protected]94305332013-11-25 22:32:05213 VLOG(1) << "Overriding API key " << environment_variable_name
214 << " with value " << key_value << " from command-line switch.";
[email protected]b08bf822012-09-11 21:50:38215 }
[email protected]e5e894ff2012-09-06 02:18:47216
[email protected]2b113652012-09-17 17:01:39217 if (key_value == DUMMY_API_TOKEN) {
[email protected]e5e894ff2012-09-06 02:18:47218#if defined(GOOGLE_CHROME_BUILD)
[email protected]2b113652012-09-17 17:01:39219 // 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.
222 CHECK(false);
[email protected]e5e894ff2012-09-06 02:18:47223#endif
[email protected]2b113652012-09-17 17:01:39224 if (default_if_unset.size() > 0) {
[email protected]94305332013-11-25 22:32:05225 VLOG(1) << "Using default value \"" << default_if_unset
226 << "\" for API key " << environment_variable_name;
[email protected]2b113652012-09-17 17:01:39227 key_value = default_if_unset;
228 }
[email protected]e5e894ff2012-09-06 02:18:47229 }
230
[email protected]b08bf822012-09-11 21:50:38231 // This should remain a debug-only log.
232 DVLOG(1) << "API key " << environment_variable_name << "=" << key_value;
[email protected]e5e894ff2012-09-06 02:18:47233
[email protected]b08bf822012-09-11 21:50:38234 return key_value;
[email protected]e5e894ff2012-09-06 02:18:47235 }
236
237 std::string api_key_;
238 std::string client_ids_[CLIENT_NUM_ITEMS];
239 std::string client_secrets_[CLIENT_NUM_ITEMS];
240};
241
242static base::LazyInstance<APIKeyCache> g_api_key_cache =
243 LAZY_INSTANCE_INITIALIZER;
244
[email protected]e7dd7892013-05-16 19:10:40245bool HasKeysConfigured() {
246 if (GetAPIKey() == DUMMY_API_TOKEN)
247 return false;
248
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) {
253 return false;
254 }
255 }
256
257 return true;
258}
259
[email protected]e5e894ff2012-09-06 02:18:47260std::string GetAPIKey() {
261 return g_api_key_cache.Get().api_key();
262}
263
264std::string GetOAuth2ClientID(OAuth2Client client) {
265 return g_api_key_cache.Get().GetClientID(client);
266}
267
268std::string GetOAuth2ClientSecret(OAuth2Client client) {
269 return g_api_key_cache.Get().GetClientSecret(client);
270}
271
[email protected]e4b54e32014-01-17 13:55:20272bool IsGoogleChromeAPIKeyUsed() {
273#if defined(GOOGLE_CHROME_BUILD) || defined(USE_OFFICIAL_GOOGLE_API_KEYS)
274 return true;
275#else
276 return false;
277#endif
278}
279
[email protected]e5e894ff2012-09-06 02:18:47280} // namespace google_apis