Pass serialized GaiaConfig to renderer process
This prevents class GaiaUrls from diverging between browser and renderer processes, namely honoring command-line argument --gaia-config being honored in the renderer process. Change-Id: I523f300d1bf376a4985be839178a199d8992626d Fixed: 1223400 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2983030 Commit-Queue: Mikel Astiz <mastiz@chromium.org> Reviewed-by: Ken Buchanan <kenrb@chromium.org> Reviewed-by: Alex Ilin <alexilin@chromium.org> Cr-Commit-Position: refs/heads/master@{#899472}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
7b293561d3
commit
fca31c5937
content/browser/renderer_host
google_apis
@ -32,6 +32,7 @@ specific_include_rules = {
|
||||
"+components/viz/service",
|
||||
],
|
||||
"render_process_host_impl\.cc": [
|
||||
"+google_apis/gaia/gaia_config.h",
|
||||
"+google_apis/gaia/gaia_switches.h",
|
||||
# TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
|
||||
# embedded in mus won't be able to talk to the native ozone.
|
||||
|
@ -168,6 +168,7 @@
|
||||
#include "content/public/common/sandboxed_process_launcher_delegate.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "content/public/common/zygote/zygote_buildflags.h"
|
||||
#include "google_apis/gaia/gaia_config.h"
|
||||
#include "google_apis/gaia/gaia_switches.h"
|
||||
#include "gpu/GLES2/gl2extchromium.h"
|
||||
#include "gpu/command_buffer/client/gpu_switches.h"
|
||||
@ -3561,6 +3562,17 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
|
||||
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
|
||||
base::size(kSwitchNames));
|
||||
|
||||
// |switches::kGaiaConfig| can be set via browser command-line arguments,
|
||||
// usually by developers working on signin code. The switch, however, cannot
|
||||
// be passed as is, because the renderer cannot read the file anyway. In those
|
||||
// cases (and only in those cases) GaiaConfig::GetInstance() returns non-null,
|
||||
// and it can be used to serialize its content (usually <2 KB) into a
|
||||
// command-line switch.
|
||||
if (GaiaConfig::GetInstance()) {
|
||||
GaiaConfig::GetInstance()->SerializeContentsToCommandLineSwitch(
|
||||
renderer_cmd);
|
||||
}
|
||||
|
||||
BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(renderer_cmd);
|
||||
BrowserChildProcessHostImpl::CopyTraceStartupFlags(renderer_cmd);
|
||||
|
||||
|
@ -218,6 +218,7 @@ test("google_apis_unittests") {
|
||||
sources = [
|
||||
"gaia/gaia_auth_fetcher_unittest.cc",
|
||||
"gaia/gaia_auth_util_unittest.cc",
|
||||
"gaia/gaia_config_unittest.cc",
|
||||
"gaia/gaia_oauth_client_unittest.cc",
|
||||
"gaia/gaia_urls_unittest.cc",
|
||||
"gaia/google_service_auth_error_unittest.cc",
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/no_destructor.h"
|
||||
@ -19,31 +20,54 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<GaiaConfig> ReadConfigFromDisk() {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (!command_line->HasSwitch(switches::kGaiaConfig))
|
||||
return nullptr;
|
||||
|
||||
const base::FilePath config_path =
|
||||
command_line->GetSwitchValuePath(switches::kGaiaConfig);
|
||||
std::string config_contents;
|
||||
if (!base::ReadFileToString(config_path, &config_contents)) {
|
||||
LOG(ERROR) << "Couldn't read gaia config file " << config_path;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<GaiaConfig> ReadConfigFromString(
|
||||
const std::string& config_contents) {
|
||||
absl::optional<base::Value> dict = base::JSONReader::Read(config_contents);
|
||||
if (!dict || !dict->is_dict()) {
|
||||
LOG(ERROR) << "Couldn't parse gaia config file " << config_path;
|
||||
LOG(FATAL) << "Couldn't parse Gaia config file";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<GaiaConfig>(std::move(dict.value()));
|
||||
}
|
||||
|
||||
std::unique_ptr<GaiaConfig> ReadConfigFromDisk(
|
||||
const base::FilePath& config_path) {
|
||||
std::string config_contents;
|
||||
if (!base::ReadFileToString(config_path, &config_contents)) {
|
||||
LOG(FATAL) << "Couldn't read Gaia config file " << config_path;
|
||||
return nullptr;
|
||||
}
|
||||
return ReadConfigFromString(config_contents);
|
||||
}
|
||||
|
||||
std::unique_ptr<GaiaConfig> ReadConfigFromCommandLineSwitches(
|
||||
const base::CommandLine* command_line) {
|
||||
if (command_line->HasSwitch(switches::kGaiaConfigPath) &&
|
||||
command_line->HasSwitch(switches::kGaiaConfigContents)) {
|
||||
LOG(FATAL) << "Either a Gaia config file path or a config file contents "
|
||||
"can be provided; "
|
||||
<< "not both";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (command_line->HasSwitch(switches::kGaiaConfigContents)) {
|
||||
return ReadConfigFromString(
|
||||
command_line->GetSwitchValueASCII(switches::kGaiaConfigContents));
|
||||
}
|
||||
|
||||
if (command_line->HasSwitch(switches::kGaiaConfigPath)) {
|
||||
return ReadConfigFromDisk(
|
||||
command_line->GetSwitchValuePath(switches::kGaiaConfigPath));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<GaiaConfig>* GetGlobalConfig() {
|
||||
static base::NoDestructor<std::unique_ptr<GaiaConfig>> config(
|
||||
ReadConfigFromDisk());
|
||||
ReadConfigFromCommandLineSwitches(
|
||||
base::CommandLine::ForCurrentProcess()));
|
||||
return config.get();
|
||||
}
|
||||
|
||||
@ -100,7 +124,22 @@ bool GaiaConfig::GetAPIKeyIfExists(base::StringPiece key,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GaiaConfig::SerializeContentsToCommandLineSwitch(
|
||||
base::CommandLine* command_line) const {
|
||||
std::string config_contents;
|
||||
base::JSONWriter::Write(parsed_config_, &config_contents);
|
||||
command_line->AppendSwitchASCII(switches::kGaiaConfigContents,
|
||||
config_contents);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<GaiaConfig> GaiaConfig::CreateFromCommandLineForTesting(
|
||||
const base::CommandLine* command_line) {
|
||||
return ReadConfigFromCommandLineSwitches(command_line);
|
||||
}
|
||||
|
||||
// static
|
||||
void GaiaConfig::ResetInstanceForTesting() {
|
||||
*GetGlobalConfig() = ReadConfigFromDisk();
|
||||
*GetGlobalConfig() =
|
||||
ReadConfigFromCommandLineSwitches(base::CommandLine::ForCurrentProcess());
|
||||
}
|
||||
|
@ -15,9 +15,14 @@
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
} // namespace base
|
||||
|
||||
// Class representing a configuration for Gaia URLs and Google API keys.
|
||||
// Parses a JSON config file specified by |switches::kGaiaConfig| and provides
|
||||
// convenient getters for reading this config.
|
||||
// Parses a JSON config file specified by |switches::kGaiaConfigPath| or
|
||||
// |switches::kGaiaConfigContents| and provides convenient getters for reading
|
||||
// this config.
|
||||
//
|
||||
// The config is represented by a JSON object with the following structure:
|
||||
// {
|
||||
@ -26,7 +31,7 @@ class GURL;
|
||||
// "url": "https://accounts.example.com"
|
||||
// },
|
||||
// ...
|
||||
// }
|
||||
// },
|
||||
// "api_keys": {
|
||||
// "GOOGLE_CLIENT_ID_MAIN": "example_key",
|
||||
// ...
|
||||
@ -36,12 +41,14 @@ class GaiaConfig {
|
||||
public:
|
||||
// Returns a global instance of GaiaConfig.
|
||||
// This may return nullptr if the config file was not specified by a command
|
||||
// line parameter or couldn't be parsed correctly.
|
||||
// line parameter.
|
||||
static GaiaConfig* GetInstance();
|
||||
|
||||
// Constructs a new GaiaConfig from a parsed JSON dictionary.
|
||||
// Prefer GetInstance() over this constructor.
|
||||
explicit GaiaConfig(base::Value parsed_config);
|
||||
GaiaConfig(const GaiaConfig&) = delete;
|
||||
GaiaConfig& operator=(const GaiaConfig&) = delete;
|
||||
~GaiaConfig();
|
||||
|
||||
// Searches for a URL by |key|.
|
||||
@ -56,6 +63,17 @@ class GaiaConfig {
|
||||
// Otherwise, returns false. |out_api_key| will be unmodified.
|
||||
bool GetAPIKeyIfExists(base::StringPiece key, std::string* out_api_key);
|
||||
|
||||
// Serializes the state of |this| into |command_line|, in a way that
|
||||
// GaiaConfig::GetInstance() would honor. Internally, it uses switch
|
||||
// |kGaiaConfigContents| for this purpose, which is appended to
|
||||
// |*command_line|.
|
||||
void SerializeContentsToCommandLineSwitch(
|
||||
base::CommandLine* command_line) const;
|
||||
|
||||
// Instantiates this object given |base::CommandLine|, used in tests.
|
||||
static std::unique_ptr<GaiaConfig> CreateFromCommandLineForTesting(
|
||||
const base::CommandLine* command_line);
|
||||
|
||||
private:
|
||||
friend class GaiaUrlsTest;
|
||||
FRIEND_TEST_ALL_PREFIXES(GoogleAPIKeysTest, OverrideAllKeysUsingConfig);
|
||||
|
96
google_apis/gaia/gaia_config_unittest.cc
Normal file
96
google_apis/gaia/gaia_config_unittest.cc
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "google_apis/gaia/gaia_config.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "google_apis/gaia/gaia_switches.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::Eq;
|
||||
using testing::IsNull;
|
||||
|
||||
const char kTestConfigContents[] = R"(
|
||||
{
|
||||
"urls": {
|
||||
"test_url": {
|
||||
"url": "https://accounts.example.com/"
|
||||
}
|
||||
},
|
||||
"api_keys": {
|
||||
"test_api_key": "test_api_key_value"
|
||||
}
|
||||
})";
|
||||
|
||||
TEST(GaiaConfigTest, ShouldGetURLIfExists) {
|
||||
absl::optional<base::Value> dict =
|
||||
base::JSONReader::Read(kTestConfigContents);
|
||||
ASSERT_TRUE(dict.has_value());
|
||||
|
||||
GaiaConfig config(std::move(*dict));
|
||||
GURL url;
|
||||
EXPECT_TRUE(config.GetURLIfExists("test_url", &url));
|
||||
EXPECT_THAT(url, Eq("https://accounts.example.com/"));
|
||||
}
|
||||
|
||||
TEST(GaiaConfigTest, ShouldReturnNullIfURLDoesNotExists) {
|
||||
absl::optional<base::Value> dict =
|
||||
base::JSONReader::Read(kTestConfigContents);
|
||||
ASSERT_TRUE(dict.has_value());
|
||||
|
||||
GaiaConfig config(std::move(*dict));
|
||||
GURL url;
|
||||
EXPECT_FALSE(config.GetURLIfExists("missing_url", &url));
|
||||
}
|
||||
|
||||
TEST(GaiaConfigTest, ShouldGetAPIKeyIfExists) {
|
||||
absl::optional<base::Value> dict =
|
||||
base::JSONReader::Read(kTestConfigContents);
|
||||
ASSERT_TRUE(dict.has_value());
|
||||
|
||||
GaiaConfig config(std::move(*dict));
|
||||
std::string api_key;
|
||||
EXPECT_TRUE(config.GetAPIKeyIfExists("test_api_key", &api_key));
|
||||
EXPECT_THAT(api_key, Eq("test_api_key_value"));
|
||||
}
|
||||
|
||||
TEST(GaiaConfigTest, ShouldReturnNullIfAPIKeyDoesNotExists) {
|
||||
absl::optional<base::Value> dict =
|
||||
base::JSONReader::Read(kTestConfigContents);
|
||||
ASSERT_TRUE(dict.has_value());
|
||||
|
||||
GaiaConfig config(std::move(*dict));
|
||||
std::string api_key;
|
||||
EXPECT_FALSE(config.GetAPIKeyIfExists("missing_api_key", &api_key));
|
||||
}
|
||||
|
||||
TEST(GaiaConfigTest, ShouldSerializeContentsToCommandLineSwitch) {
|
||||
absl::optional<base::Value> dict =
|
||||
base::JSONReader::Read(kTestConfigContents);
|
||||
ASSERT_TRUE(dict.has_value());
|
||||
|
||||
GaiaConfig config(std::move(*dict));
|
||||
GURL url;
|
||||
ASSERT_TRUE(config.GetURLIfExists("test_url", &url));
|
||||
ASSERT_THAT(url, Eq("https://accounts.example.com/"));
|
||||
|
||||
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
|
||||
config.SerializeContentsToCommandLineSwitch(&command_line);
|
||||
EXPECT_TRUE(command_line.HasSwitch(switches::kGaiaConfigContents));
|
||||
|
||||
std::unique_ptr<GaiaConfig> deserialized_config =
|
||||
GaiaConfig::CreateFromCommandLineForTesting(&command_line);
|
||||
GURL deserialized_url;
|
||||
EXPECT_TRUE(
|
||||
deserialized_config->GetURLIfExists("test_url", &deserialized_url));
|
||||
EXPECT_THAT(deserialized_url, Eq("https://accounts.example.com/"));
|
||||
}
|
||||
|
||||
} // namespace
|
@ -6,7 +6,8 @@
|
||||
|
||||
namespace switches {
|
||||
|
||||
const char kGaiaConfig[] = "gaia-config";
|
||||
const char kGaiaConfigPath[] = "gaia-config";
|
||||
const char kGaiaConfigContents[] = "gaia-config-contents";
|
||||
const char kGoogleUrl[] = "google-url";
|
||||
const char kGaiaUrl[] = "gaia-url";
|
||||
const char kGoogleApisUrl[] = "google-apis-url";
|
||||
|
@ -9,7 +9,12 @@ namespace switches {
|
||||
|
||||
// Specifies the path to a config file containing GAIA urls.
|
||||
// See "google_apis/test/data/gaia/all_urls.json" for a format example.
|
||||
extern const char kGaiaConfig[];
|
||||
extern const char kGaiaConfigPath[];
|
||||
|
||||
// Specifies a string containing the JSON config for GAIA urls. This is
|
||||
// equivalent to pointing to a file with the same content via kGaiaConfigPath.
|
||||
// See "google_apis/test/data/gaia/all_urls.json" for a format example.
|
||||
extern const char kGaiaConfigContents[];
|
||||
|
||||
// Specifies the domain of the SAPISID cookie. The default value is
|
||||
// "http://.google.com".
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "google_apis/gaia/gaia_config.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@ -452,6 +453,21 @@ TEST_F(GaiaUrlsTest, InitializeFromConfig_AllBaseUrls) {
|
||||
"https://accounts.example.com/");
|
||||
}
|
||||
|
||||
TEST_F(GaiaUrlsTest, InitializeFromConfigContents) {
|
||||
base::test::ScopedCommandLine command_line;
|
||||
command_line.GetProcessCommandLine()->AppendSwitchASCII(
|
||||
"gaia-config-contents", R"(
|
||||
{
|
||||
"urls": {
|
||||
"gaia_url": {
|
||||
"url": "https://accounts.example.com"
|
||||
}
|
||||
}
|
||||
})");
|
||||
|
||||
EXPECT_EQ(gaia_urls()->gaia_url().spec(), "https://accounts.example.com/");
|
||||
}
|
||||
|
||||
TEST_F(GaiaUrlsTest, InitializeFromConfig_BadUrl) {
|
||||
base::test::ScopedCommandLine command_line;
|
||||
command_line.GetProcessCommandLine()->AppendSwitchPath(
|
||||
@ -484,8 +500,7 @@ TEST_F(GaiaUrlsTest, InitializeFromConfig_FileNotFound) {
|
||||
command_line.GetProcessCommandLine()->AppendSwitchPath(
|
||||
"gaia-config", GetTestFilePath("no_such_file.json"));
|
||||
|
||||
// Fallback to the default URL.
|
||||
EXPECT_EQ(gaia_urls()->google_url().spec(), "http://google.com/");
|
||||
EXPECT_DEATH_IF_SUPPORTED(gaia_urls(), "Couldn't read Gaia config file");
|
||||
}
|
||||
|
||||
TEST_F(GaiaUrlsTest, InitializeFromConfig_NotAJson) {
|
||||
@ -493,6 +508,5 @@ TEST_F(GaiaUrlsTest, InitializeFromConfig_NotAJson) {
|
||||
command_line.GetProcessCommandLine()->AppendSwitchPath(
|
||||
"gaia-config", GetTestFilePath("not_a_json.txt"));
|
||||
|
||||
// Fallback to the default URL.
|
||||
EXPECT_EQ(gaia_urls()->google_url().spec(), "http://google.com/");
|
||||
EXPECT_DEATH_IF_SUPPORTED(gaia_urls(), "Couldn't parse Gaia config file");
|
||||
}
|
||||
|
Reference in New Issue
Block a user