// Copyright (c) 2013 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 "base/base64.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome_launcher.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(ProcessExtensions, NoExtension) {
Switches switches;
std::vector<std::string> extensions;
base::FilePath extension_dir;
std::vector<std::string> bg_pages;
Status status = internal::ProcessExtensions(extensions, extension_dir,
false, &switches, &bg_pages);
ASSERT_TRUE(status.IsOk());
ASSERT_FALSE(switches.HasSwitch("load-extension"));
ASSERT_EQ(0u, bg_pages.size());
}
bool AddExtensionForInstall(const std::string& relative_path,
std::vector<std::string>* extensions) {
base::FilePath source_root;
PathService::Get(base::DIR_SOURCE_ROOT, &source_root);
base::FilePath crx_file_path = source_root.AppendASCII(
"chrome/test/data/chromedriver/" + relative_path);
std::string crx_contents;
if (!base::ReadFileToString(crx_file_path, &crx_contents))
return false;
std::string crx_encoded;
base::Base64Encode(crx_contents, &crx_encoded);
extensions->push_back(crx_encoded);
return true;
}
TEST(ProcessExtensions, GenerateIds) {
std::vector<std::string> extensions;
base::ScopedTempDir extension_dir;
Switches switches;
std::vector<std::string> bg_pages;
ASSERT_TRUE(AddExtensionForInstall("no_key_in_manifest.crx", &extensions));
ASSERT_TRUE(AddExtensionForInstall("same_key_as_header.crx", &extensions));
ASSERT_TRUE(AddExtensionForInstall("diff_key_from_header.crx", &extensions));
ASSERT_TRUE(extension_dir.CreateUniqueTempDir());
Status status = internal::ProcessExtensions(extensions, extension_dir.path(),
false, &switches, &bg_pages);
ASSERT_EQ(kOk, status.code()) << status.message();
ASSERT_EQ(3u, bg_pages.size());
ASSERT_EQ("chrome-extension://llphabdmknikmpmkioimgdfbohinlekl/"
"_generated_background_page.html", bg_pages[0]);
ASSERT_EQ("chrome-extension://dfdeoklpcichfcnoaomfpagfiibhomnh/"
"_generated_background_page.html", bg_pages[1]);
ASSERT_EQ("chrome-extension://ioccpomhcpklobebcbeohnmffkmcokbm/"
"_generated_background_page.html", bg_pages[2]);
}
TEST(ProcessExtensions, SingleExtensionWithBgPage) {
std::vector<std::string> extensions;
ASSERT_TRUE(AddExtensionForInstall("ext_slow_loader.crx", &extensions));
base::ScopedTempDir extension_dir;
ASSERT_TRUE(extension_dir.CreateUniqueTempDir());
Switches switches;
std::vector<std::string> bg_pages;
Status status = internal::ProcessExtensions(extensions, extension_dir.path(),
false, &switches, &bg_pages);
ASSERT_TRUE(status.IsOk());
ASSERT_TRUE(switches.HasSwitch("load-extension"));
base::FilePath temp_ext_path(switches.GetSwitchValueNative("load-extension"));
ASSERT_TRUE(base::PathExists(temp_ext_path));
std::string manifest_txt;
ASSERT_TRUE(base::ReadFileToString(
temp_ext_path.AppendASCII("manifest.json"), &manifest_txt));
scoped_ptr<base::Value> manifest(base::JSONReader::Read(manifest_txt));
ASSERT_TRUE(manifest);
base::DictionaryValue* manifest_dict = NULL;
ASSERT_TRUE(manifest->GetAsDictionary(&manifest_dict));
std::string key;
ASSERT_TRUE(manifest_dict->GetString("key", &key));
ASSERT_EQ(
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8qhZthEHjTIA3IYMzi79s2KFepVziY0du"
"JzHcqRUB/YHSGseIUqcYXGazJhDz/"
"4FbRg8ef9fQazL1UbMMGBIf4za1kJ2os2MsRrNXzHslkbtcLVj2VfofhuHJmu+"
"CnKJ77UWamJiNAaQSiclu4duwnEWrkx+g/8ChQfhZzC4jvQIDAQAB",
key);
ASSERT_EQ(1u, bg_pages.size());
ASSERT_EQ(
"chrome-extension://jijhlkpcmmeckhlgdipjhnchhoabdjae/"
"_generated_background_page.html",
bg_pages[0]);
}
TEST(ProcessExtensions, MultipleExtensionsNoBgPages) {
std::vector<std::string> extensions;
ASSERT_TRUE(AddExtensionForInstall("ext_test_1.crx", &extensions));
ASSERT_TRUE(AddExtensionForInstall("ext_test_2.crx", &extensions));
base::ScopedTempDir extension_dir;
ASSERT_TRUE(extension_dir.CreateUniqueTempDir());
Switches switches;
std::vector<std::string> bg_pages;
Status status = internal::ProcessExtensions(extensions, extension_dir.path(),
false, &switches, &bg_pages);
ASSERT_TRUE(status.IsOk());
ASSERT_TRUE(switches.HasSwitch("load-extension"));
CommandLine::StringType ext_paths = switches.GetSwitchValueNative(
"load-extension");
std::vector<CommandLine::StringType> ext_path_list;
base::SplitString(ext_paths, FILE_PATH_LITERAL(','), &ext_path_list);
ASSERT_EQ(2u, ext_path_list.size());
ASSERT_TRUE(base::PathExists(base::FilePath(ext_path_list[0])));
ASSERT_TRUE(base::PathExists(base::FilePath(ext_path_list[1])));
ASSERT_EQ(0u, bg_pages.size());
}
TEST(ProcessExtensions, CommandLineExtensions) {
std::vector<std::string> extensions;
ASSERT_TRUE(AddExtensionForInstall("ext_test_1.crx", &extensions));
base::ScopedTempDir extension_dir;
ASSERT_TRUE(extension_dir.CreateUniqueTempDir());
Switches switches;
switches.SetSwitch("load-extension", "/a");
std::vector<std::string> bg_pages;
Status status = internal::ProcessExtensions(extensions, extension_dir.path(),
false, &switches, &bg_pages);
ASSERT_EQ(kOk, status.code());
base::FilePath::StringType load = switches.GetSwitchValueNative(
"load-extension");
ASSERT_EQ(FILE_PATH_LITERAL("/a,"), load.substr(0, 3));
ASSERT_TRUE(base::PathExists(base::FilePath(load.substr(3))));
}
namespace {
void AssertEQ(const base::DictionaryValue& dict, const std::string& key,
const char* expected_value) {
std::string value;
ASSERT_TRUE(dict.GetString(key, &value));
ASSERT_STREQ(value.c_str(), expected_value);
}
} // namespace
TEST(PrepareUserDataDir, CustomPrefs) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::DictionaryValue prefs;
prefs.SetString("myPrefsKey", "ok");
prefs.SetStringWithoutPathExpansion("pref.sub", "1");
base::DictionaryValue local_state;
local_state.SetString("myLocalKey", "ok");
local_state.SetStringWithoutPathExpansion("local.state.sub", "2");
Status status = internal::PrepareUserDataDir(
temp_dir.path(), &prefs, &local_state);
ASSERT_EQ(kOk, status.code());
base::FilePath prefs_file =
temp_dir.path().AppendASCII("Default").AppendASCII("Preferences");
std::string prefs_str;
ASSERT_TRUE(base::ReadFileToString(prefs_file, &prefs_str));
scoped_ptr<base::Value> prefs_value(base::JSONReader::Read(prefs_str));
const base::DictionaryValue* prefs_dict = NULL;
ASSERT_TRUE(prefs_value->GetAsDictionary(&prefs_dict));
AssertEQ(*prefs_dict, "myPrefsKey", "ok");
AssertEQ(*prefs_dict, "pref.sub", "1");
base::FilePath local_state_file = temp_dir.path().AppendASCII("Local State");
std::string local_state_str;
ASSERT_TRUE(base::ReadFileToString(local_state_file, &local_state_str));
scoped_ptr<base::Value> local_state_value(
base::JSONReader::Read(local_state_str));
const base::DictionaryValue* local_state_dict = NULL;
ASSERT_TRUE(local_state_value->GetAsDictionary(&local_state_dict));
AssertEQ(*local_state_dict, "myLocalKey", "ok");
AssertEQ(*local_state_dict, "local.state.sub", "2");
}