1 // Copyright 2015 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.
4 
5 #include "chrome/browser/ui/ash/vpn_list_forwarder.h"
6 
7 #include "ash/public/cpp/network_config_service.h"
8 #include "base/bind.h"
9 #include "base/check_op.h"
10 #include "base/location.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "chrome/browser/chromeos/profiles/profile_helper.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
15 #include "components/user_manager/user.h"
16 #include "extensions/browser/extension_registry.h"
17 #include "extensions/common/extension.h"
18 #include "extensions/common/extension_set.h"
19 #include "extensions/common/permissions/api_permission.h"
20 #include "extensions/common/permissions/permissions_data.h"
21 
22 using chromeos::network_config::mojom::VpnProvider;
23 using chromeos::network_config::mojom::VpnProviderPtr;
24 
25 namespace mojo {
26 
27 template <>
28 struct TypeConverter<VpnProviderPtr,
29                      app_list::ArcVpnProviderManager::ArcVpnProvider*> {
Convertmojo::TypeConverter30   static VpnProviderPtr Convert(
31       const app_list::ArcVpnProviderManager::ArcVpnProvider* input) {
32     auto result = VpnProvider::New();
33     result->type = chromeos::network_config::mojom::VpnType::kArc;
34     result->provider_id = input->package_name;
35     result->provider_name = input->app_name;
36     result->app_id = input->app_id;
37     result->last_launch_time = input->last_launch_time;
38     return result;
39   }
40 };
41 
42 template <>
43 struct TypeConverter<VpnProviderPtr, const extensions::Extension*> {
Convertmojo::TypeConverter44   static VpnProviderPtr Convert(const extensions::Extension* input) {
45     auto result = VpnProvider::New();
46     result->type = chromeos::network_config::mojom::VpnType::kExtension;
47     result->provider_id = input->id();
48     result->provider_name = input->name();
49     // For Extensions, the app id is the same as the provider id.
50     result->app_id = input->id();
51     return result;
52   }
53 };
54 
55 }  // namespace mojo
56 
57 namespace {
58 
IsVPNProvider(const extensions::Extension * extension)59 bool IsVPNProvider(const extensions::Extension* extension) {
60   return extension->permissions_data()->HasAPIPermission(
61       extensions::APIPermission::kVpnProvider);
62 }
63 
GetProfileForPrimaryUser()64 Profile* GetProfileForPrimaryUser() {
65   const user_manager::User* const primary_user =
66       user_manager::UserManager::Get()->GetPrimaryUser();
67   if (!primary_user)
68     return nullptr;
69 
70   return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user);
71 }
72 
73 }  // namespace
74 
VpnListForwarder()75 VpnListForwarder::VpnListForwarder() {
76   if (user_manager::UserManager::Get()->GetPrimaryUser()) {
77     // If a user is logged in, start observing the primary user's extension
78     // registry immediately.
79     AttachToPrimaryUserProfile();
80   } else {
81     // If no user is logged in, wait until the first user logs in (thus becoming
82     // the primary user).
83     user_manager::UserManager::Get()->AddSessionStateObserver(this);
84   }
85 
86   cros_network_config_ = std::make_unique<
87       mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>>();
88   ash::GetNetworkConfigService(
89       cros_network_config_->BindNewPipeAndPassReceiver());
90 }
91 
~VpnListForwarder()92 VpnListForwarder::~VpnListForwarder() {
93   user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
94   if (extension_registry_)
95     extension_registry_->RemoveObserver(this);
96   if (arc_vpn_provider_manager_)
97     arc_vpn_provider_manager_->RemoveObserver(this);
98 }
99 
OnArcVpnProvidersRefreshed(const std::vector<std::unique_ptr<app_list::ArcVpnProviderManager::ArcVpnProvider>> & arc_vpn_providers)100 void VpnListForwarder::OnArcVpnProvidersRefreshed(
101     const std::vector<
102         std::unique_ptr<app_list::ArcVpnProviderManager::ArcVpnProvider>>&
103         arc_vpn_providers) {
104   for (const auto& arc_vpn_provider : arc_vpn_providers) {
105     vpn_providers_[arc_vpn_provider->package_name] =
106         VpnProvider::From(arc_vpn_provider.get());
107   }
108   SetVpnProviders();
109 }
110 
OnArcVpnProviderUpdated(app_list::ArcVpnProviderManager::ArcVpnProvider * arc_vpn_provider)111 void VpnListForwarder::OnArcVpnProviderUpdated(
112     app_list::ArcVpnProviderManager::ArcVpnProvider* arc_vpn_provider) {
113   vpn_providers_[arc_vpn_provider->package_name] =
114       VpnProvider::From(arc_vpn_provider);
115   SetVpnProviders();
116 }
117 
OnArcVpnProviderRemoved(const std::string & package_name)118 void VpnListForwarder::OnArcVpnProviderRemoved(
119     const std::string& package_name) {
120   vpn_providers_.erase(package_name);
121   SetVpnProviders();
122 }
123 
OnExtensionLoaded(content::BrowserContext * browser_context,const extensions::Extension * extension)124 void VpnListForwarder::OnExtensionLoaded(
125     content::BrowserContext* browser_context,
126     const extensions::Extension* extension) {
127   if (!IsVPNProvider(extension))
128     return;
129   vpn_providers_[extension->id()] = VpnProvider::From(extension);
130   SetVpnProviders();
131 }
132 
OnExtensionUnloaded(content::BrowserContext * browser_context,const extensions::Extension * extension,extensions::UnloadedExtensionReason reason)133 void VpnListForwarder::OnExtensionUnloaded(
134     content::BrowserContext* browser_context,
135     const extensions::Extension* extension,
136     extensions::UnloadedExtensionReason reason) {
137   if (!IsVPNProvider(extension))
138     return;
139   vpn_providers_.erase(extension->id());
140   SetVpnProviders();
141 }
142 
OnShutdown(extensions::ExtensionRegistry * registry)143 void VpnListForwarder::OnShutdown(extensions::ExtensionRegistry* registry) {
144   DCHECK(extension_registry_);
145   extension_registry_->RemoveObserver(this);
146   extension_registry_ = nullptr;
147 }
148 
ActiveUserChanged(user_manager::User * active_user)149 void VpnListForwarder::ActiveUserChanged(user_manager::User* active_user) {
150   DCHECK_EQ(user_manager::UserManager::Get()->GetPrimaryUser(), active_user);
151   active_user->AddProfileCreatedObserver(
152       base::BindOnce(&VpnListForwarder::AttachToPrimaryUserProfile,
153                      weak_factory_.GetWeakPtr()));
154   user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
155 }
156 
SetVpnProviders()157 void VpnListForwarder::SetVpnProviders() {
158   std::vector<VpnProviderPtr> config_providers;
159   config_providers.reserve(vpn_providers_.size());
160   for (const auto& iter : vpn_providers_)
161     config_providers.push_back(iter.second->Clone());
162   (*cros_network_config_)->SetVpnProviders(std::move(config_providers));
163 }
164 
AttachToPrimaryUserProfile()165 void VpnListForwarder::AttachToPrimaryUserProfile() {
166   AttachToPrimaryUserExtensionRegistry();
167   AttachToPrimaryUserArcVpnProviderManager();
168 }
169 
AttachToPrimaryUserExtensionRegistry()170 void VpnListForwarder::AttachToPrimaryUserExtensionRegistry() {
171   DCHECK(!extension_registry_);
172   extension_registry_ =
173       extensions::ExtensionRegistry::Get(GetProfileForPrimaryUser());
174   extension_registry_->AddObserver(this);
175 
176   for (const auto& extension : extension_registry_->enabled_extensions()) {
177     if (!IsVPNProvider(extension.get()))
178       continue;
179     vpn_providers_[extension->id()] = VpnProvider::From(extension.get());
180   }
181   SetVpnProviders();
182 }
183 
AttachToPrimaryUserArcVpnProviderManager()184 void VpnListForwarder::AttachToPrimaryUserArcVpnProviderManager() {
185   arc_vpn_provider_manager_ =
186       app_list::ArcVpnProviderManager::Get(GetProfileForPrimaryUser());
187 
188   if (arc_vpn_provider_manager_)
189     arc_vpn_provider_manager_->AddObserver(this);
190 }
191