Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / policy / test / local_policy_test_server.cc
blobbc1e200f41b8f677db0d416d7dd5a1168ee80a12
1 // Copyright (c) 2013 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.
5 #include "chrome/browser/policy/test/local_policy_test_server.h"
7 #include <ctype.h>
9 #include <algorithm>
10 #include <vector>
12 #include "base/base_paths.h"
13 #include "base/file_util.h"
14 #include "base/json/json_writer.h"
15 #include "base/path_service.h"
16 #include "base/stl_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
19 #include "crypto/rsa_private_key.h"
20 #include "net/test/python_utils.h"
21 #include "net/test/spawned_test_server/base_test_server.h"
23 namespace policy {
25 namespace {
27 // Filename in the temporary directory storing the policy data.
28 const base::FilePath::CharType kPolicyFileName[] = FILE_PATH_LITERAL("policy");
30 // Private signing key file within the temporary directory.
31 const base::FilePath::CharType kSigningKeyFileName[] =
32 FILE_PATH_LITERAL("signing_key");
34 // The file containing client definitions to be passed to the server.
35 const base::FilePath::CharType kClientStateFileName[] =
36 FILE_PATH_LITERAL("clients");
38 // Dictionary keys for the client state file. Needs to be kept in sync with
39 // policy_testserver.py.
40 const char kClientStateKeyAllowedPolicyTypes[] = "allowed_policy_types";
41 const char kClientStateKeyDeviceId[] = "device_id";
42 const char kClientStateKeyDeviceToken[] = "device_token";
43 const char kClientStateKeyMachineName[] = "machine_name";
44 const char kClientStateKeyMachineId[] = "machine_id";
46 // Checks whether a given character should be replaced when constructing a file
47 // name. To keep things simple, this is a bit over-aggressive. Needs to be kept
48 // in sync with policy_testserver.py.
49 bool IsUnsafeCharacter(char c) {
50 return !(isalnum(c) || c == '.' || c == '@' || c == '-');
53 } // namespace
55 LocalPolicyTestServer::LocalPolicyTestServer()
56 : net::LocalTestServer(net::BaseTestServer::TYPE_HTTP,
57 net::BaseTestServer::kLocalhost,
58 base::FilePath()) {
59 CHECK(server_data_dir_.CreateUniqueTempDir());
60 config_file_ = server_data_dir_.path().Append(kPolicyFileName);
63 LocalPolicyTestServer::LocalPolicyTestServer(const base::FilePath& config_file)
64 : net::LocalTestServer(net::BaseTestServer::TYPE_HTTP,
65 net::BaseTestServer::kLocalhost,
66 base::FilePath()),
67 config_file_(config_file) {}
69 LocalPolicyTestServer::LocalPolicyTestServer(const std::string& test_name)
70 : net::LocalTestServer(net::BaseTestServer::TYPE_HTTP,
71 net::BaseTestServer::kLocalhost,
72 base::FilePath()) {
73 // Read configuration from a file in chrome/test/data/policy.
74 base::FilePath source_root;
75 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &source_root));
76 config_file_ = source_root
77 .AppendASCII("chrome")
78 .AppendASCII("test")
79 .AppendASCII("data")
80 .AppendASCII("policy")
81 .AppendASCII(base::StringPrintf("policy_%s.json", test_name.c_str()));
84 LocalPolicyTestServer::~LocalPolicyTestServer() {}
86 bool LocalPolicyTestServer::SetSigningKey(const crypto::RSAPrivateKey* key) {
87 CHECK(server_data_dir_.IsValid());
89 std::vector<uint8> signing_key_bits;
90 if (!key->ExportPrivateKey(&signing_key_bits))
91 return false;
93 policy_key_ = server_data_dir_.path().Append(kSigningKeyFileName);
94 int bytes_written = file_util::WriteFile(
95 policy_key_,
96 reinterpret_cast<const char*>(vector_as_array(&signing_key_bits)),
97 signing_key_bits.size());
98 return bytes_written == static_cast<int>(signing_key_bits.size());
101 void LocalPolicyTestServer::RegisterClient(const std::string& dm_token,
102 const std::string& device_id) {
103 CHECK(server_data_dir_.IsValid());
105 scoped_ptr<base::DictionaryValue> client_dict(new base::DictionaryValue());
106 client_dict->SetString(kClientStateKeyDeviceId, device_id);
107 client_dict->SetString(kClientStateKeyDeviceToken, dm_token);
108 client_dict->SetString(kClientStateKeyMachineName, std::string());
109 client_dict->SetString(kClientStateKeyMachineId, std::string());
111 // Allow all policy types for now.
112 scoped_ptr<base::ListValue> types(new base::ListValue());
113 types->AppendString(dm_protocol::kChromeDevicePolicyType);
114 types->AppendString(dm_protocol::kChromeUserPolicyType);
115 types->AppendString(dm_protocol::kChromePublicAccountPolicyType);
116 types->AppendString(dm_protocol::kChromeExtensionPolicyType);
118 client_dict->Set(kClientStateKeyAllowedPolicyTypes, types.release());
119 clients_.Set(dm_token, client_dict.release());
122 bool LocalPolicyTestServer::UpdatePolicy(const std::string& type,
123 const std::string& entity_id,
124 const std::string& policy) {
125 CHECK(server_data_dir_.IsValid());
127 std::string selector = GetSelector(type, entity_id);
128 base::FilePath policy_file = server_data_dir_.path().AppendASCII(
129 base::StringPrintf("policy_%s.bin", selector.c_str()));
131 return file_util::WriteFile(policy_file, policy.c_str(), policy.size()) ==
132 static_cast<int>(policy.size());
135 bool LocalPolicyTestServer::UpdatePolicyData(const std::string& type,
136 const std::string& entity_id,
137 const std::string& data) {
138 CHECK(server_data_dir_.IsValid());
140 std::string selector = GetSelector(type, entity_id);
141 base::FilePath data_file = server_data_dir_.path().AppendASCII(
142 base::StringPrintf("policy_%s.data", selector.c_str()));
144 return file_util::WriteFile(data_file, data.c_str(), data.size()) ==
145 static_cast<int>(data.size());
148 GURL LocalPolicyTestServer::GetServiceURL() const {
149 return GetURL("device_management");
152 bool LocalPolicyTestServer::SetPythonPath() const {
153 if (!net::LocalTestServer::SetPythonPath())
154 return false;
156 // Add the net/tools/testserver directory to the path.
157 base::FilePath net_testserver_path;
158 if (!LocalTestServer::GetTestServerPath(&net_testserver_path)) {
159 LOG(ERROR) << "Failed to get net testserver path.";
160 return false;
162 AppendToPythonPath(net_testserver_path.DirName());
164 // We need protobuf python bindings.
165 base::FilePath third_party_dir;
166 if (!PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) {
167 LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
168 return false;
170 AppendToPythonPath(third_party_dir
171 .AppendASCII("third_party")
172 .AppendASCII("protobuf")
173 .AppendASCII("python"));
175 // Add the generated python protocol buffer bindings.
176 base::FilePath pyproto_dir;
177 if (!GetPyProtoPath(&pyproto_dir)) {
178 LOG(ERROR) << "Cannot find pyproto dir for generated code.";
179 return false;
182 AppendToPythonPath(pyproto_dir
183 .AppendASCII("chrome")
184 .AppendASCII("browser")
185 .AppendASCII("policy")
186 .AppendASCII("proto")
187 .AppendASCII("cloud"));
188 AppendToPythonPath(pyproto_dir
189 .AppendASCII("policy")
190 .AppendASCII("proto"));
191 #if defined(OS_CHROMEOS)
192 AppendToPythonPath(pyproto_dir
193 .AppendASCII("chrome")
194 .AppendASCII("browser")
195 .AppendASCII("policy")
196 .AppendASCII("proto")
197 .AppendASCII("chromeos"));
198 #endif
200 return true;
203 bool LocalPolicyTestServer::GetTestServerPath(
204 base::FilePath* testserver_path) const {
205 base::FilePath source_root;
206 if (!PathService::Get(base::DIR_SOURCE_ROOT, &source_root)) {
207 LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
208 return false;
210 *testserver_path = source_root
211 .AppendASCII("chrome")
212 .AppendASCII("browser")
213 .AppendASCII("policy")
214 .AppendASCII("test")
215 .AppendASCII("policy_testserver.py");
216 return true;
219 bool LocalPolicyTestServer::GenerateAdditionalArguments(
220 base::DictionaryValue* arguments) const {
221 if (!net::LocalTestServer::GenerateAdditionalArguments(arguments))
222 return false;
224 arguments->SetString("config-file", config_file_.AsUTF8Unsafe());
225 if (!policy_key_.empty())
226 arguments->SetString("policy-key", policy_key_.AsUTF8Unsafe());
227 if (server_data_dir_.IsValid()) {
228 arguments->SetString("data-dir", server_data_dir_.path().AsUTF8Unsafe());
230 if (!clients_.empty()) {
231 std::string json;
232 base::JSONWriter::Write(&clients_, &json);
233 base::FilePath client_state_file =
234 server_data_dir_.path().Append(kClientStateFileName);
235 if (file_util::WriteFile(client_state_file, json.c_str(), json.size()) !=
236 static_cast<int>(json.size())) {
237 return false;
239 arguments->SetString("client-state", client_state_file.AsUTF8Unsafe());
243 return true;
246 std::string LocalPolicyTestServer::GetSelector(const std::string& type,
247 const std::string& entity_id) {
248 std::string selector = type;
249 if (!entity_id.empty())
250 selector = base::StringPrintf("%s/%s", type.c_str(), entity_id.c_str());
251 std::replace_if(selector.begin(), selector.end(), IsUnsafeCharacter, '_');
252 return selector;
255 } // namespace policy