Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / browser / api / vpn_provider / vpn_provider_api.cc
blobf38a1e275153721f48958f5ee3811d1ff66c5458
1 // Copyright 2014 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 "extensions/browser/api/vpn_provider/vpn_provider_api.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_util.h"
13 #include "base/values.h"
14 #include "extensions/browser/api/vpn_provider/vpn_service.h"
15 #include "extensions/browser/api/vpn_provider/vpn_service_factory.h"
16 #include "extensions/common/api/vpn_provider.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace extensions {
21 namespace {
23 namespace api_vpn = extensions::core_api::vpn_provider;
25 const char kCIDRSeperator[] = "/";
27 bool CheckIPCIDRSanity(const std::string& value, bool cidr, bool ipv6) {
28 int dots = ipv6 ? 0 : 3;
29 int sep = cidr ? 1 : 0;
30 int colon = ipv6 ? 7 : 0;
31 bool hex_allowed = ipv6;
32 int counter = 0;
34 for (const auto& elem : value) {
35 if (IsAsciiDigit(elem)) {
36 counter++;
37 continue;
39 if (elem == '.') {
40 if (!dots)
41 return false;
42 dots--;
43 } else if (elem == kCIDRSeperator[0]) {
44 if (!sep || dots || colon == 7 || !counter)
45 return false;
46 // Separator observed, no more dots and colons, only digits are allowed
47 // after observing separator. So setting hex_allowed to false.
48 sep--;
49 counter = 0;
50 colon = 0;
51 hex_allowed = false;
52 } else if (elem == ':') {
53 if (!colon)
54 return false;
55 colon--;
56 } else if (!hex_allowed || !IsHexDigit(elem)) {
57 return false;
58 } else {
59 counter++;
62 return !sep && !dots && (colon < 7) && counter;
65 bool CheckIPCIDRSanityList(const std::vector<std::string>& list,
66 bool cidr,
67 bool ipv6) {
68 for (const auto& address : list) {
69 if (!CheckIPCIDRSanity(address, cidr, ipv6)) {
70 return false;
73 return true;
76 void ConvertParameters(const api_vpn::Parameters& parameters,
77 base::DictionaryValue* parameter_value,
78 std::string* error) {
79 if (!CheckIPCIDRSanity(parameters.address, true /* CIDR */,
80 false /*IPV4 */)) {
81 *error = "Address CIDR sanity check failed.";
82 return;
85 if (!CheckIPCIDRSanityList(parameters.exclusion_list, true /* CIDR */,
86 false /*IPV4 */)) {
87 *error = "Exclusion list CIDR sanity check failed.";
88 return;
91 if (!CheckIPCIDRSanityList(parameters.inclusion_list, true /* CIDR */,
92 false /*IPV4 */)) {
93 *error = "Inclusion list CIDR sanity check failed.";
94 return;
97 if (!CheckIPCIDRSanityList(parameters.dns_servers, false /* Not CIDR */,
98 false /*IPV4 */)) {
99 *error = "DNS server IP sanity check failed.";
100 return;
103 std::vector<std::string> cidr_parts;
104 CHECK(Tokenize(parameters.address, kCIDRSeperator, &cidr_parts) == 2);
106 parameter_value->SetStringWithoutPathExpansion(
107 shill::kAddressParameterThirdPartyVpn, cidr_parts[0]);
109 parameter_value->SetStringWithoutPathExpansion(
110 shill::kSubnetPrefixParameterThirdPartyVpn, cidr_parts[1]);
112 parameter_value->SetStringWithoutPathExpansion(
113 shill::kExclusionListParameterThirdPartyVpn,
114 JoinString(parameters.exclusion_list, shill::kIPDelimiter));
116 parameter_value->SetStringWithoutPathExpansion(
117 shill::kInclusionListParameterThirdPartyVpn,
118 JoinString(parameters.inclusion_list, shill::kIPDelimiter));
120 if (parameters.mtu) {
121 parameter_value->SetStringWithoutPathExpansion(
122 shill::kMtuParameterThirdPartyVpn, *parameters.mtu);
125 if (parameters.broadcast_address) {
126 parameter_value->SetStringWithoutPathExpansion(
127 shill::kBroadcastAddressParameterThirdPartyVpn,
128 *parameters.broadcast_address);
131 if (parameters.domain_search) {
132 parameter_value->SetStringWithoutPathExpansion(
133 shill::kDomainSearchParameterThirdPartyVpn,
134 JoinString(*parameters.domain_search, shill::kNonIPDelimiter));
137 parameter_value->SetStringWithoutPathExpansion(
138 shill::kDnsServersParameterThirdPartyVpn,
139 JoinString(parameters.dns_servers, shill::kIPDelimiter));
141 return;
144 } // namespace
146 VpnThreadExtensionFunction::~VpnThreadExtensionFunction() {
149 void VpnThreadExtensionFunction::SignalCallCompletionSuccess() {
150 Respond(NoArguments());
153 void VpnThreadExtensionFunction::SignalCallCompletionSuccessWithId(
154 const std::string& configuration_id) {
155 Respond(OneArgument(new base::StringValue(configuration_id)));
158 void VpnThreadExtensionFunction::SignalCallCompletionSuccessWithWarning(
159 const std::string& warning) {
160 if (!warning.empty()) {
161 WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, warning);
163 Respond(NoArguments());
166 void VpnThreadExtensionFunction::SignalCallCompletionFailure(
167 const std::string& error_name,
168 const std::string& error_message) {
169 if (!error_name.empty() && !error_message.empty()) {
170 Respond(Error(error_name + ": " + error_message));
171 } else if (!error_name.empty()) {
172 Respond(Error(error_name));
173 } else {
174 Respond(Error(error_message));
178 VpnProviderCreateConfigFunction::~VpnProviderCreateConfigFunction() {
181 ExtensionFunction::ResponseAction VpnProviderCreateConfigFunction::Run() {
182 scoped_ptr<api_vpn::CreateConfig::Params> params(
183 api_vpn::CreateConfig::Params::Create(*args_));
184 if (!params) {
185 return RespondNow(Error("Invalid arguments."));
188 chromeos::VpnService* service =
189 chromeos::VpnServiceFactory::GetForBrowserContext(browser_context());
190 if (!service) {
191 return RespondNow(Error("Invalid profile."));
194 // Use the configuration name as ID. In the future, a different ID scheme may
195 // be used, requiring a mapping between the two.
196 service->CreateConfiguration(
197 extension_id(), extension()->name(), params->name,
198 base::Bind(
199 &VpnProviderCreateConfigFunction::SignalCallCompletionSuccessWithId,
200 this, params->name),
201 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
202 SignalCallCompletionFailure,
203 this));
205 return RespondLater();
208 VpnProviderDestroyConfigFunction::~VpnProviderDestroyConfigFunction() {
211 ExtensionFunction::ResponseAction VpnProviderDestroyConfigFunction::Run() {
212 scoped_ptr<api_vpn::DestroyConfig::Params> params(
213 api_vpn::DestroyConfig::Params::Create(*args_));
214 if (!params) {
215 return RespondNow(Error("Invalid arguments."));
218 chromeos::VpnService* service =
219 chromeos::VpnServiceFactory::GetForBrowserContext(browser_context());
220 if (!service) {
221 return RespondNow(Error("Invalid profile."));
224 service->DestroyConfiguration(
225 extension_id(), params->id,
226 base::Bind(&VpnProviderDestroyConfigFunction::SignalCallCompletionSuccess,
227 this),
228 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
229 SignalCallCompletionFailure,
230 this));
232 return RespondLater();
235 VpnProviderSetParametersFunction::~VpnProviderSetParametersFunction() {
238 ExtensionFunction::ResponseAction VpnProviderSetParametersFunction::Run() {
239 scoped_ptr<api_vpn::SetParameters::Params> params(
240 api_vpn::SetParameters::Params::Create(*args_));
241 if (!params) {
242 return RespondNow(Error("Invalid arguments."));
245 chromeos::VpnService* service =
246 chromeos::VpnServiceFactory::GetForBrowserContext(browser_context());
247 if (!service) {
248 return RespondNow(Error("Invalid profile."));
251 base::DictionaryValue parameter_value;
252 std::string error;
253 ConvertParameters(params->parameters, &parameter_value, &error);
254 if (!error.empty()) {
255 return RespondNow(Error(error));
258 service->SetParameters(
259 extension_id(), parameter_value,
260 base::Bind(&VpnProviderSetParametersFunction::
261 SignalCallCompletionSuccessWithWarning,
262 this),
263 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
264 SignalCallCompletionFailure,
265 this));
267 return RespondLater();
270 VpnProviderSendPacketFunction::~VpnProviderSendPacketFunction() {
273 ExtensionFunction::ResponseAction VpnProviderSendPacketFunction::Run() {
274 scoped_ptr<api_vpn::SendPacket::Params> params(
275 api_vpn::SendPacket::Params::Create(*args_));
276 if (!params) {
277 return RespondNow(Error("Invalid arguments."));
280 chromeos::VpnService* service =
281 chromeos::VpnServiceFactory::GetForBrowserContext(browser_context());
282 if (!service) {
283 return RespondNow(Error("Invalid profile."));
286 service->SendPacket(
287 extension_id(), params->data,
288 base::Bind(&VpnProviderSendPacketFunction::SignalCallCompletionSuccess,
289 this),
290 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
291 SignalCallCompletionFailure,
292 this));
294 return RespondLater();
297 VpnProviderNotifyConnectionStateChangedFunction::
298 ~VpnProviderNotifyConnectionStateChangedFunction() {
301 ExtensionFunction::ResponseAction
302 VpnProviderNotifyConnectionStateChangedFunction::Run() {
303 scoped_ptr<api_vpn::NotifyConnectionStateChanged::Params> params(
304 api_vpn::NotifyConnectionStateChanged::Params::Create(*args_));
305 if (!params) {
306 return RespondNow(Error("Invalid arguments."));
309 chromeos::VpnService* service =
310 chromeos::VpnServiceFactory::GetForBrowserContext(browser_context());
311 if (!service) {
312 return RespondNow(Error("Invalid profile."));
315 service->NotifyConnectionStateChanged(
316 extension_id(), params->state,
317 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
318 SignalCallCompletionSuccess,
319 this),
320 base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
321 SignalCallCompletionFailure,
322 this));
324 return RespondLater();
327 } // namespace extensions