ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / extensions / browser / api / vpn_provider / vpn_service.cc
blob7a51aac70dad68758c332cc4fb1fc6e35abfd96e
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_service.h"
7 #include <stdint.h>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/guid.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/values.h"
19 #include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
20 #include "chromeos/dbus/shill_third_party_vpn_observer.h"
21 #include "chromeos/network/network_configuration_handler.h"
22 #include "chromeos/network/network_profile.h"
23 #include "chromeos/network/network_profile_handler.h"
24 #include "chromeos/network/network_state.h"
25 #include "chromeos/network/network_state_handler.h"
26 #include "chromeos/network/network_type_pattern.h"
27 #include "crypto/sha2.h"
28 #include "extensions/browser/event_router.h"
29 #include "extensions/browser/extension_registry.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
32 namespace chromeos {
34 namespace {
36 namespace api_vpn = extensions::core_api::vpn_provider;
38 std::string GetKey(const std::string& extension_id, const std::string& name) {
39 const std::string key = crypto::SHA256HashString(extension_id + name);
40 return base::HexEncode(key.data(), key.size());
43 std::string GetCombinedName(const std::string& extension_name,
44 const std::string& configuration_name) {
45 // TODO(kaliamoorthi): (crbug.com/434711) Sort out the dependencies and
46 // replace the string concatenation with internationalized version.
47 return extension_name + ": " + configuration_name;
50 void DoNothingFailureCallback(const std::string& error_name,
51 const std::string& error_message) {
52 LOG(ERROR) << error_name << ": " << error_message;
55 } // namespace
57 class VpnService::VpnConfiguration : public ShillThirdPartyVpnObserver {
58 public:
59 VpnConfiguration(const std::string& extension_id,
60 const std::string& configuration_name,
61 const std::string& key,
62 base::WeakPtr<VpnService> vpn_service);
63 ~VpnConfiguration() override;
65 const std::string& extension_id() const { return extension_id_; }
66 const std::string& configuration_name() const { return configuration_name_; }
67 const std::string& key() const { return key_; }
68 const std::string& service_path() const { return service_path_; }
69 void set_service_path(const std::string& service_path) {
70 service_path_ = service_path;
72 const std::string& object_path() const { return object_path_; }
74 // ShillThirdPartyVpnObserver:
75 void OnPacketReceived(const std::vector<char>& data) override;
76 void OnPlatformMessage(uint32_t message) override;
78 private:
79 const std::string extension_id_;
80 const std::string configuration_name_;
81 const std::string key_;
82 const std::string object_path_;
84 std::string service_path_;
86 base::WeakPtr<VpnService> vpn_service_;
88 DISALLOW_COPY_AND_ASSIGN(VpnConfiguration);
91 VpnService::VpnConfiguration::VpnConfiguration(
92 const std::string& extension_id,
93 const std::string& configuration_name,
94 const std::string& key,
95 base::WeakPtr<VpnService> vpn_service)
96 : extension_id_(extension_id),
97 configuration_name_(configuration_name),
98 key_(key),
99 object_path_(shill::kObjectPathBase + key_),
100 vpn_service_(vpn_service) {
103 VpnService::VpnConfiguration::~VpnConfiguration() {
106 void VpnService::VpnConfiguration::OnPacketReceived(
107 const std::vector<char>& data) {
108 if (!vpn_service_) {
109 return;
111 scoped_ptr<base::ListValue> event_args =
112 api_vpn::OnPacketReceived::Create(data);
113 vpn_service_->SendSignalToExtension(
114 extension_id_, api_vpn::OnPacketReceived::kEventName, event_args.Pass());
117 void VpnService::VpnConfiguration::OnPlatformMessage(uint32_t message) {
118 if (!vpn_service_) {
119 return;
121 DCHECK_GE(api_vpn::PLATFORM_MESSAGE_LAST, message);
123 api_vpn::PlatformMessage platform_message =
124 static_cast<api_vpn::PlatformMessage>(message);
125 vpn_service_->SetActiveConfiguration(
126 platform_message == api_vpn::PLATFORM_MESSAGE_CONNECTED ? this : nullptr);
128 // TODO(kaliamoorthi): Update the lower layers to get the error message and
129 // pass in the error instead of std::string().
130 scoped_ptr<base::ListValue> event_args = api_vpn::OnPlatformMessage::Create(
131 configuration_name_, platform_message, std::string());
133 vpn_service_->SendSignalToExtension(
134 extension_id_, api_vpn::OnPlatformMessage::kEventName, event_args.Pass());
137 VpnService::VpnService(
138 content::BrowserContext* browser_context,
139 const std::string& userid_hash,
140 extensions::ExtensionRegistry* extension_registry,
141 extensions::EventRouter* event_router,
142 ShillThirdPartyVpnDriverClient* shill_client,
143 NetworkConfigurationHandler* network_configuration_handler,
144 NetworkProfileHandler* network_profile_handler,
145 NetworkStateHandler* network_state_handler)
146 : browser_context_(browser_context),
147 userid_hash_(userid_hash),
148 extension_registry_(extension_registry),
149 event_router_(event_router),
150 shill_client_(shill_client),
151 network_configuration_handler_(network_configuration_handler),
152 network_profile_handler_(network_profile_handler),
153 network_state_handler_(network_state_handler),
154 active_configuration_(nullptr),
155 weak_factory_(this) {
156 extension_registry_->AddObserver(this);
157 network_state_handler_->AddObserver(this, FROM_HERE);
158 network_configuration_handler_->AddObserver(this);
161 VpnService::~VpnService() {
162 network_configuration_handler_->RemoveObserver(this);
163 network_state_handler_->RemoveObserver(this, FROM_HERE);
164 extension_registry_->RemoveObserver(this);
165 STLDeleteContainerPairSecondPointers(key_to_configuration_map_.begin(),
166 key_to_configuration_map_.end());
169 void VpnService::OnConfigurationCreated(const std::string& service_path,
170 const std::string& profile_path,
171 const base::DictionaryValue& properties,
172 Source source) {
175 void VpnService::OnConfigurationRemoved(const std::string& service_path,
176 const std::string& guid,
177 Source source) {
178 if (source == SOURCE_EXTENSION_INSTALL) {
179 // No need to process if the configuration was removed using an extension
180 // API since the API would have already done the cleanup.
181 return;
184 if (service_path_to_configuration_map_.find(service_path) ==
185 service_path_to_configuration_map_.end()) {
186 // Ignore removal of a configuration unknown to VPN service, which means the
187 // configuration was created internally by the platform.
188 return;
191 VpnConfiguration* configuration =
192 service_path_to_configuration_map_[service_path];
193 scoped_ptr<base::ListValue> event_args =
194 api_vpn::OnConfigRemoved::Create(configuration->configuration_name());
195 SendSignalToExtension(configuration->extension_id(),
196 api_vpn::OnConfigRemoved::kEventName,
197 event_args.Pass());
199 DestroyConfigurationInternal(configuration);
202 void VpnService::OnPropertiesSet(const std::string& service_path,
203 const std::string& guid,
204 const base::DictionaryValue& set_properties,
205 Source source) {
208 void VpnService::OnConfigurationProfileChanged(const std::string& service_path,
209 const std::string& profile_path,
210 Source source) {
213 void VpnService::OnGetPropertiesSuccess(
214 const std::string& service_path,
215 const base::DictionaryValue& dictionary) {
216 if (service_path_to_configuration_map_.find(service_path) !=
217 service_path_to_configuration_map_.end()) {
218 return;
220 const base::DictionaryValue* provider = nullptr;
221 std::string vpn_type;
222 std::string extension_id;
223 std::string type;
224 std::string name;
225 std::string configuration_name;
226 if (!dictionary.GetDictionary(shill::kProviderProperty, &provider) ||
227 !dictionary.GetString(shill::kProviderTypeProperty, &vpn_type) ||
228 !dictionary.GetString(shill::kProviderHostProperty, &extension_id) ||
229 !dictionary.GetString(shill::kTypeProperty, &type) ||
230 !dictionary.GetString(shill::kNameProperty, &name) ||
231 !provider->GetString(shill::kConfigurationNameProperty,
232 &configuration_name) ||
233 vpn_type != shill::kProviderThirdPartyVpn || type != shill::kTypeVPN) {
234 return;
237 if (!extension_registry_->GetExtensionById(
238 extension_id, extensions::ExtensionRegistry::ENABLED)) {
239 // Does not belong to this instance of VpnService.
240 return;
243 const std::string key = GetKey(extension_id, configuration_name);
244 VpnConfiguration* configuration =
245 CreateConfigurationInternal(extension_id, configuration_name, key);
246 configuration->set_service_path(service_path);
247 service_path_to_configuration_map_[service_path] = configuration;
248 shill_client_->AddShillThirdPartyVpnObserver(configuration->object_path(),
249 configuration);
252 void VpnService::OnGetPropertiesFailure(
253 const std::string& error_name,
254 scoped_ptr<base::DictionaryValue> error_data) {
257 void VpnService::NetworkListChanged() {
258 NetworkStateHandler::NetworkStateList network_list;
259 network_state_handler_->GetVisibleNetworkListByType(NetworkTypePattern::VPN(),
260 &network_list);
261 for (auto& iter : network_list) {
262 if (service_path_to_configuration_map_.find(iter->path()) !=
263 service_path_to_configuration_map_.end()) {
264 continue;
267 network_configuration_handler_->GetShillProperties(
268 iter->path(), base::Bind(&VpnService::OnGetPropertiesSuccess,
269 weak_factory_.GetWeakPtr()),
270 base::Bind(&VpnService::OnGetPropertiesFailure,
271 weak_factory_.GetWeakPtr()));
275 void VpnService::CreateConfiguration(const std::string& extension_id,
276 const std::string& extension_name,
277 const std::string& configuration_name,
278 const SuccessCallback& success,
279 const FailureCallback& failure) {
280 if (configuration_name.empty()) {
281 failure.Run(std::string(), std::string("Empty name not supported."));
282 return;
285 const std::string key = GetKey(extension_id, configuration_name);
286 if (ContainsKey(key_to_configuration_map_, key)) {
287 failure.Run(std::string(), std::string("Name not unique."));
288 return;
291 const NetworkProfile* profile =
292 network_profile_handler_->GetProfileForUserhash(userid_hash_);
293 if (!profile) {
294 failure.Run(
295 std::string(),
296 std::string("No user profile for unshared network configuration."));
297 return;
300 VpnConfiguration* configuration =
301 CreateConfigurationInternal(extension_id, configuration_name, key);
303 base::DictionaryValue properties;
304 properties.SetStringWithoutPathExpansion(shill::kTypeProperty,
305 shill::kTypeVPN);
306 properties.SetStringWithoutPathExpansion(
307 shill::kNameProperty, // This value is shown to the user in native UI.
308 GetCombinedName(extension_name, configuration_name));
309 properties.SetStringWithoutPathExpansion(shill::kProviderHostProperty,
310 extension_id);
311 properties.SetStringWithoutPathExpansion(shill::kObjectPathSuffixProperty,
312 configuration->key());
313 properties.SetStringWithoutPathExpansion(shill::kProviderTypeProperty,
314 shill::kProviderThirdPartyVpn);
315 properties.SetStringWithoutPathExpansion(shill::kProfileProperty,
316 profile->path);
317 properties.SetStringWithoutPathExpansion(shill::kConfigurationNameProperty,
318 configuration_name);
320 // Note: This will not create an entry in |policy_util|. TODO(pneubeck):
321 // Determine the correct thing to do here, crbug.com/459278.
322 std::string guid = base::GenerateGUID();
323 properties.SetStringWithoutPathExpansion(shill::kGuidProperty, guid);
325 network_configuration_handler_->CreateShillConfiguration(
326 properties, NetworkConfigurationObserver::SOURCE_EXTENSION_INSTALL,
327 base::Bind(&VpnService::OnCreateConfigurationSuccess,
328 weak_factory_.GetWeakPtr(), success, configuration),
329 base::Bind(&VpnService::OnCreateConfigurationFailure,
330 weak_factory_.GetWeakPtr(), failure, configuration));
333 void VpnService::DestroyConfiguration(const std::string& extension_id,
334 const std::string& configuration_name,
335 const SuccessCallback& success,
336 const FailureCallback& failure) {
337 const std::string key = GetKey(extension_id, configuration_name);
338 if (!ContainsKey(key_to_configuration_map_, key)) {
339 failure.Run(std::string(), std::string("Unauthorized access."));
340 return;
343 VpnConfiguration* configuration = key_to_configuration_map_[key];
344 const std::string service_path = configuration->service_path();
345 DestroyConfigurationInternal(configuration);
347 network_configuration_handler_->RemoveConfiguration(
348 service_path, NetworkConfigurationObserver::SOURCE_EXTENSION_INSTALL,
349 base::Bind(&VpnService::OnRemoveConfigurationSuccess,
350 weak_factory_.GetWeakPtr(), success),
351 base::Bind(&VpnService::OnRemoveConfigurationFailure,
352 weak_factory_.GetWeakPtr(), failure));
355 void VpnService::SetParameters(const std::string& extension_id,
356 const base::DictionaryValue& parameters,
357 const SuccessCallback& success,
358 const FailureCallback& failure) {
359 if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
360 failure.Run(std::string(), std::string("Unauthorized access."));
361 return;
364 shill_client_->SetParameters(active_configuration_->object_path(), parameters,
365 success, failure);
368 void VpnService::SendPacket(const std::string& extension_id,
369 const std::vector<char>& data,
370 const SuccessCallback& success,
371 const FailureCallback& failure) {
372 if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
373 failure.Run(std::string(), std::string("Unauthorized access."));
374 return;
377 if (data.empty()) {
378 failure.Run(std::string(), std::string("Can't send an empty packet."));
379 return;
382 shill_client_->SendPacket(active_configuration_->object_path(), data, success,
383 failure);
386 void VpnService::NotifyConnectionStateChanged(const std::string& extension_id,
387 api_vpn::VpnConnectionState state,
388 const SuccessCallback& success,
389 const FailureCallback& failure) {
390 if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
391 failure.Run(std::string(), std::string("Unauthorized access."));
392 return;
395 shill_client_->UpdateConnectionState(active_configuration_->object_path(),
396 static_cast<uint32_t>(state), success,
397 failure);
400 void VpnService::OnExtensionUninstalled(
401 content::BrowserContext* browser_context,
402 const extensions::Extension* extension,
403 extensions::UninstallReason reason) {
404 if (browser_context != browser_context_) {
405 NOTREACHED();
406 return;
409 std::vector<VpnConfiguration*> to_be_destroyed;
410 for (const auto& iter : key_to_configuration_map_) {
411 if (iter.second->extension_id() == extension->id()) {
412 to_be_destroyed.push_back(iter.second);
416 for (auto& iter : to_be_destroyed) {
417 DestroyConfiguration(extension->id(), // Extension ID
418 iter->configuration_name(), // Configuration name
419 base::Bind(base::DoNothing),
420 base::Bind(DoNothingFailureCallback));
424 void VpnService::OnCreateConfigurationSuccess(
425 const VpnService::SuccessCallback& callback,
426 VpnConfiguration* configuration,
427 const std::string& service_path) {
428 configuration->set_service_path(service_path);
429 service_path_to_configuration_map_[service_path] = configuration;
430 shill_client_->AddShillThirdPartyVpnObserver(configuration->object_path(),
431 configuration);
432 callback.Run();
435 void VpnService::OnCreateConfigurationFailure(
436 const VpnService::FailureCallback& callback,
437 VpnConfiguration* configuration,
438 const std::string& error_name,
439 scoped_ptr<base::DictionaryValue> error_data) {
440 DestroyConfigurationInternal(configuration);
441 callback.Run(error_name, std::string());
444 void VpnService::OnRemoveConfigurationSuccess(
445 const VpnService::SuccessCallback& callback) {
446 callback.Run();
449 void VpnService::OnRemoveConfigurationFailure(
450 const VpnService::FailureCallback& callback,
451 const std::string& error_name,
452 scoped_ptr<base::DictionaryValue> error_data) {
453 callback.Run(error_name, std::string());
456 void VpnService::SendSignalToExtension(const std::string& extension_id,
457 const std::string& event_name,
458 scoped_ptr<base::ListValue> event_args) {
459 scoped_ptr<extensions::Event> event(
460 new extensions::Event(event_name, event_args.Pass(), browser_context_));
462 event_router_->DispatchEventToExtension(extension_id, event.Pass());
465 void VpnService::SetActiveConfiguration(
466 VpnService::VpnConfiguration* configuration) {
467 active_configuration_ = configuration;
470 VpnService::VpnConfiguration* VpnService::CreateConfigurationInternal(
471 const std::string& extension_id,
472 const std::string& configuration_name,
473 const std::string& key) {
474 VpnConfiguration* configuration = new VpnConfiguration(
475 extension_id, configuration_name, key, weak_factory_.GetWeakPtr());
476 // The object is owned by key_to_configuration_map_ henceforth.
477 key_to_configuration_map_[key] = configuration;
478 return configuration;
481 void VpnService::DestroyConfigurationInternal(VpnConfiguration* configuration) {
482 key_to_configuration_map_.erase(configuration->key());
483 if (active_configuration_ == configuration) {
484 active_configuration_ = nullptr;
486 if (!configuration->service_path().empty()) {
487 shill_client_->RemoveShillThirdPartyVpnObserver(
488 configuration->object_path());
489 service_path_to_configuration_map_.erase(configuration->service_path());
491 delete configuration;
494 bool VpnService::DoesActiveConfigurationExistAndIsAccessAuthorized(
495 const std::string& extension_id) {
496 return active_configuration_ &&
497 active_configuration_->extension_id() == extension_id;
500 } // namespace chromeos