• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "google_apis/google_api_keys.h"
6 
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"
15 #include "google_apis/gaia/gaia_switches.h"
16 
17 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_OFFICIAL_GOOGLE_API_KEYS)
18 #include "google_apis/internal/google_chrome_api_keys.h"
19 #endif
20 
21 // Used to indicate an unset key/id/secret.  This works better with
22 // various unit tests than leaving the token empty.
23 #define DUMMY_API_TOKEN "dummytoken"
24 
25 #if !defined(GOOGLE_API_KEY)
26 #define GOOGLE_API_KEY DUMMY_API_TOKEN
27 #endif
28 
29 #if !defined(GOOGLE_CLIENT_ID_MAIN)
30 #define GOOGLE_CLIENT_ID_MAIN DUMMY_API_TOKEN
31 #endif
32 
33 #if !defined(GOOGLE_CLIENT_SECRET_MAIN)
34 #define GOOGLE_CLIENT_SECRET_MAIN DUMMY_API_TOKEN
35 #endif
36 
37 #if !defined(GOOGLE_CLIENT_ID_CLOUD_PRINT)
38 #define GOOGLE_CLIENT_ID_CLOUD_PRINT DUMMY_API_TOKEN
39 #endif
40 
41 #if !defined(GOOGLE_CLIENT_SECRET_CLOUD_PRINT)
42 #define GOOGLE_CLIENT_SECRET_CLOUD_PRINT DUMMY_API_TOKEN
43 #endif
44 
45 #if !defined(GOOGLE_CLIENT_ID_REMOTING)
46 #define GOOGLE_CLIENT_ID_REMOTING DUMMY_API_TOKEN
47 #endif
48 
49 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING)
50 #define GOOGLE_CLIENT_SECRET_REMOTING DUMMY_API_TOKEN
51 #endif
52 
53 #if !defined(GOOGLE_CLIENT_ID_REMOTING_HOST)
54 #define GOOGLE_CLIENT_ID_REMOTING_HOST DUMMY_API_TOKEN
55 #endif
56 
57 #if !defined(GOOGLE_CLIENT_SECRET_REMOTING_HOST)
58 #define GOOGLE_CLIENT_SECRET_REMOTING_HOST DUMMY_API_TOKEN
59 #endif
60 
61 // These are used as shortcuts for developers and users providing
62 // OAuth credentials via preprocessor defines or environment
63 // variables.  If set, they will be used to replace any of the client
64 // IDs and secrets above that have not been set (and only those; they
65 // will not override already-set values).
66 #if !defined(GOOGLE_DEFAULT_CLIENT_ID)
67 #define GOOGLE_DEFAULT_CLIENT_ID ""
68 #endif
69 #if !defined(GOOGLE_DEFAULT_CLIENT_SECRET)
70 #define GOOGLE_DEFAULT_CLIENT_SECRET ""
71 #endif
72 
73 namespace google_apis {
74 
75 // This is used as a lazy instance to determine keys once and cache them.
76 class APIKeyCache {
77  public:
APIKeyCache()78   APIKeyCache() {
79     scoped_ptr<base::Environment> environment(base::Environment::Create());
80     CommandLine* command_line = CommandLine::ForCurrentProcess();
81 
82     api_key_ = CalculateKeyValue(GOOGLE_API_KEY,
83                                  STRINGIZE_NO_EXPANSION(GOOGLE_API_KEY),
84                                  NULL,
85                                  std::string(),
86                                  environment.get(),
87                                  command_line);
88 
89     std::string default_client_id =
90         CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_ID,
91                           STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_ID),
92                           NULL,
93                           std::string(),
94                           environment.get(),
95                           command_line);
96     std::string default_client_secret =
97         CalculateKeyValue(GOOGLE_DEFAULT_CLIENT_SECRET,
98                           STRINGIZE_NO_EXPANSION(GOOGLE_DEFAULT_CLIENT_SECRET),
99                           NULL,
100                           std::string(),
101                           environment.get(),
102                           command_line);
103 
104     // We currently only allow overriding the baked-in values for the
105     // default OAuth2 client ID and secret using a command-line
106     // argument, since that is useful to enable testing against
107     // staging servers, and since that was what was possible and
108     // likely practiced by the QA team before this implementation was
109     // written.
110     client_ids_[CLIENT_MAIN] = CalculateKeyValue(
111         GOOGLE_CLIENT_ID_MAIN,
112         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_MAIN),
113         switches::kOAuth2ClientID,
114         default_client_id,
115         environment.get(),
116         command_line);
117     client_secrets_[CLIENT_MAIN] = CalculateKeyValue(
118         GOOGLE_CLIENT_SECRET_MAIN,
119         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_MAIN),
120         switches::kOAuth2ClientSecret,
121         default_client_secret,
122         environment.get(),
123         command_line);
124 
125     client_ids_[CLIENT_CLOUD_PRINT] = CalculateKeyValue(
126         GOOGLE_CLIENT_ID_CLOUD_PRINT,
127         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_CLOUD_PRINT),
128         NULL,
129         default_client_id,
130         environment.get(),
131         command_line);
132     client_secrets_[CLIENT_CLOUD_PRINT] = CalculateKeyValue(
133         GOOGLE_CLIENT_SECRET_CLOUD_PRINT,
134         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_CLOUD_PRINT),
135         NULL,
136         default_client_secret,
137         environment.get(),
138         command_line);
139 
140     client_ids_[CLIENT_REMOTING] = CalculateKeyValue(
141         GOOGLE_CLIENT_ID_REMOTING,
142         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING),
143         NULL,
144         default_client_id,
145         environment.get(),
146         command_line);
147     client_secrets_[CLIENT_REMOTING] = CalculateKeyValue(
148         GOOGLE_CLIENT_SECRET_REMOTING,
149         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING),
150         NULL,
151         default_client_secret,
152         environment.get(),
153         command_line);
154 
155     client_ids_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
156         GOOGLE_CLIENT_ID_REMOTING_HOST,
157         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_ID_REMOTING_HOST),
158         NULL,
159         default_client_id,
160         environment.get(),
161         command_line);
162     client_secrets_[CLIENT_REMOTING_HOST] = CalculateKeyValue(
163         GOOGLE_CLIENT_SECRET_REMOTING_HOST,
164         STRINGIZE_NO_EXPANSION(GOOGLE_CLIENT_SECRET_REMOTING_HOST),
165         NULL,
166         default_client_secret,
167         environment.get(),
168         command_line);
169   }
170 
api_key() const171   std::string api_key() const { return api_key_; }
172 
GetClientID(OAuth2Client client) const173   std::string GetClientID(OAuth2Client client) const {
174     DCHECK_LT(client, CLIENT_NUM_ITEMS);
175     return client_ids_[client];
176   }
177 
GetClientSecret(OAuth2Client client) const178   std::string GetClientSecret(OAuth2Client client) const {
179     DCHECK_LT(client, CLIENT_NUM_ITEMS);
180     return client_secrets_[client];
181   }
182 
183  private:
184   // Gets a value for a key.  In priority order, this will be the value
185   // provided via a command-line switch, the value provided via an
186   // environment variable, or finally a value baked into the build.
187   // |command_line_switch| may be NULL.
CalculateKeyValue(const char * baked_in_value,const char * environment_variable_name,const char * command_line_switch,const std::string & default_if_unset,base::Environment * environment,CommandLine * command_line)188   static std::string CalculateKeyValue(const char* baked_in_value,
189                                        const char* environment_variable_name,
190                                        const char* command_line_switch,
191                                        const std::string& default_if_unset,
192                                        base::Environment* environment,
193                                        CommandLine* command_line) {
194     std::string key_value = baked_in_value;
195     std::string temp;
196     if (environment->GetVar(environment_variable_name, &temp)) {
197       key_value = temp;
198       VLOG(1) << "Overriding API key " << environment_variable_name
199               << " with value " << key_value << " from environment variable.";
200     }
201 
202     if (command_line_switch && command_line->HasSwitch(command_line_switch)) {
203       key_value = command_line->GetSwitchValueASCII(command_line_switch);
204       VLOG(1) << "Overriding API key " << environment_variable_name
205               << " with value " << key_value << " from command-line switch.";
206     }
207 
208     if (key_value == DUMMY_API_TOKEN) {
209 #if defined(GOOGLE_CHROME_BUILD)
210       // No key should be unset in an official build except the
211       // GOOGLE_DEFAULT_* keys.  The default keys don't trigger this
212       // check as their "unset" value is not DUMMY_API_TOKEN.
213       CHECK(false);
214 #endif
215       if (default_if_unset.size() > 0) {
216         VLOG(1) << "Using default value \"" << default_if_unset
217                 << "\" for API key " << environment_variable_name;
218         key_value = default_if_unset;
219       }
220     }
221 
222     // This should remain a debug-only log.
223     DVLOG(1) << "API key " << environment_variable_name << "=" << key_value;
224 
225     return key_value;
226   }
227 
228   std::string api_key_;
229   std::string client_ids_[CLIENT_NUM_ITEMS];
230   std::string client_secrets_[CLIENT_NUM_ITEMS];
231 };
232 
233 static base::LazyInstance<APIKeyCache> g_api_key_cache =
234     LAZY_INSTANCE_INITIALIZER;
235 
HasKeysConfigured()236 bool HasKeysConfigured() {
237   if (GetAPIKey() == DUMMY_API_TOKEN)
238     return false;
239 
240   for (size_t client_id = 0; client_id < CLIENT_NUM_ITEMS; ++client_id) {
241     OAuth2Client client = static_cast<OAuth2Client>(client_id);
242     if (GetOAuth2ClientID(client) == DUMMY_API_TOKEN ||
243         GetOAuth2ClientSecret(client) == DUMMY_API_TOKEN) {
244       return false;
245     }
246   }
247 
248   return true;
249 }
250 
GetAPIKey()251 std::string GetAPIKey() {
252   return g_api_key_cache.Get().api_key();
253 }
254 
GetOAuth2ClientID(OAuth2Client client)255 std::string GetOAuth2ClientID(OAuth2Client client) {
256   return g_api_key_cache.Get().GetClientID(client);
257 }
258 
GetOAuth2ClientSecret(OAuth2Client client)259 std::string GetOAuth2ClientSecret(OAuth2Client client) {
260   return g_api_key_cache.Get().GetClientSecret(client);
261 }
262 
IsGoogleChromeAPIKeyUsed()263 bool IsGoogleChromeAPIKeyUsed() {
264 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_OFFICIAL_GOOGLE_API_KEYS)
265   return true;
266 #else
267   return false;
268 #endif
269 }
270 
271 }  // namespace google_apis
272