910e62b5创建于 1月15日历史提交
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "google_apis/google_api_keys.h"

#include <string>

#include "base/check_is_test.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/no_destructor.h"
#include "base/version_info/channel.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "google_apis/api_key_cache.h"
#include "google_apis/buildflags.h"
#include "google_apis/default_api_keys.h"

#if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
#include "google_apis/internal/google_chrome_api_keys.h"
#include "google_apis/internal/metrics_signing_key.h"
#endif

namespace google_apis {

namespace {

// Import `GetDefaultApiKeysFromDefinedValues()` definition based on the current
// preprocessor directives.
#include "google_apis/default_api_keys-inc.cc"

std::atomic<ApiKeyCache*> g_api_key_cache_instance = nullptr;

ApiKeyCache& CreateLeakyApiKeyCacheInstance() {
  static base::NoDestructor<ApiKeyCache> instance(
      GetDefaultApiKeysFromDefinedValues());
  // `g_api_key_cache_instance` is always assigned to the same value but it
  // might happen simultaneously from multiple threads, so use atomics.
  ApiKeyCache* expected = nullptr;
  g_api_key_cache_instance.compare_exchange_strong(expected, instance.get());
  return *instance.get();
}

ApiKeyCache& GetApiKeyCacheInstance() {
  if (!g_api_key_cache_instance) {
    return CreateLeakyApiKeyCacheInstance();
  }
  return *g_api_key_cache_instance;
}

#if BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)
// Explicitly creates the global API key cache.
//
// Expects that `g_api_key_cache_instance` is null, as this function must be
// called before any prior usage of the global API key cache.
ApiKeyCache& InitializeApiKeyCacheInstance() {
  // Tests need to override the global instance of the API key cache, so it
  // is not feasible to check that `g_api_key_cache_instance` is null in
  // tests.
  if (g_api_key_cache_instance) {
    CHECK_IS_TEST();
  }
  return GetApiKeyCacheInstance();
}
#endif  // BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)

}  // namespace

const char kAPIKeysDevelopersHowToURL[] =
    "https://www.chromium.org/developers/how-tos/api-keys";

bool HasAPIKeyConfigured() {
  return GetApiKeyCacheInstance().HasAPIKeyConfigured();
}

const std::string& GetAPIKey(version_info::Channel channel) {
  return channel == version_info::Channel::STABLE
             ? GetAPIKey()
             : GetApiKeyCacheInstance().api_key_non_stable();
}

const std::string& GetAPIKey() {
  return GetApiKeyCacheInstance().api_key();
}

const std::string& GetRemotingAPIKey() {
  return GetApiKeyCacheInstance().api_key_remoting();
}

const std::string& GetSodaAPIKey() {
  return GetApiKeyCacheInstance().api_key_soda();
}

#if !BUILDFLAG(IS_ANDROID)
const std::string& GetHatsAPIKey() {
  return GetApiKeyCacheInstance().api_key_hats();
}
#endif

#if BUILDFLAG(IS_CHROMEOS)
const std::string& GetSharingAPIKey() {
  return GetApiKeyCacheInstance().api_key_sharing();
}

const std::string& GetReadAloudAPIKey() {
  return GetApiKeyCacheInstance().api_key_read_aloud();
}

const std::string& GetFresnelAPIKey() {
  return GetApiKeyCacheInstance().api_key_fresnel();
}

const std::string& GetBocaAPIKey() {
  return GetApiKeyCacheInstance().api_key_boca();
}

const std::string& GetCrosSystemGeoAPIKey() {
  return GetApiKeyCacheInstance().api_key_cros_system_geo();
}
const std::string& GetCrosChromeGeoAPIKey() {
  return GetApiKeyCacheInstance().api_key_cros_chrome_geo();
}
#endif

const std::string& GetMetricsKey() {
  return GetApiKeyCacheInstance().metrics_key();
}

bool HasOAuthClientConfigured() {
  return GetApiKeyCacheInstance().HasOAuthClientConfigured();
}

const std::string& GetOAuth2ClientID(OAuth2Client client) {
  return GetApiKeyCacheInstance().GetClientID(client);
}

const std::string& GetOAuth2ClientSecret(OAuth2Client client) {
  return GetApiKeyCacheInstance().GetClientSecret(client);
}

bool IsGoogleChromeAPIKeyUsed() {
#if defined(USE_OFFICIAL_GOOGLE_API_KEYS)
  return true;
#else
  return false;
#endif
}

#if BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)
void InitializeAndOverrideAPIKey(const std::string& api_key) {
  ApiKeyCache& cache = InitializeApiKeyCacheInstance();
  cache.set_api_key(api_key);
}

void InitializeAndOverrideAPIKeyAndOAuthClient(
    const std::string& api_key,
    const std::string& client_id,
    const std::string& client_secret) {
  ApiKeyCache& cache = InitializeApiKeyCacheInstance();
  cache.set_api_key(api_key);
  for (size_t i = 0; i < google_apis::CLIENT_NUM_ITEMS; ++i) {
    google_apis::OAuth2Client client =
        static_cast<google_apis::OAuth2Client>(i);
    cache.SetClientID(client, client_id);
    cache.SetClientSecret(client, client_secret);
  }
}
#endif  // BUILDFLAG(SUPPORT_EXTERNAL_GOOGLE_API_KEY)

base::ScopedClosureRunner SetScopedApiKeyCacheForTesting(
    ApiKeyCache* api_key_cache) {
  CHECK(api_key_cache) << "Overriding with nullptr is not allowed.";
  ApiKeyCache* previous_value =
      g_api_key_cache_instance.exchange(api_key_cache);
  return base::ScopedClosureRunner(base::BindOnce(
      [](ApiKeyCache* previous_value) {
        g_api_key_cache_instance = previous_value;
      },
      previous_value));
}

}  // namespace google_apis