Home | History | Annotate | Download | only in google_apis
      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:
     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 
    171   std::string api_key() const { return api_key_; }
    172 
    173   std::string GetClientID(OAuth2Client client) const {
    174     DCHECK_LT(client, CLIENT_NUM_ITEMS);
    175     return client_ids_[client];
    176   }
    177 
    178   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.
    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 
    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 
    251 std::string GetAPIKey() {
    252   return g_api_key_cache.Get().api_key();
    253 }
    254 
    255 std::string GetOAuth2ClientID(OAuth2Client client) {
    256   return g_api_key_cache.Get().GetClientID(client);
    257 }
    258 
    259 std::string GetOAuth2ClientSecret(OAuth2Client client) {
    260   return g_api_key_cache.Get().GetClientSecret(client);
    261 }
    262 
    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