blob: 6d0b2214df288128dfa7bccb5d8cd59002458727 [file] [log] [blame]
// Copyright 2016 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 "chrome/browser/ui/webui/settings/chromeos/internet_handler.h"
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/tether/tether_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/common/net.mojom.h"
#include "components/arc/metrics/arc_metrics_constants.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/session/connection_holder.h"
#include "components/onc/onc_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "extensions/browser/api/vpn_provider/vpn_service.h"
#include "extensions/browser/api/vpn_provider/vpn_service_factory.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/events/event_constants.h"
namespace chromeos {
namespace {
const char kAddThirdPartyVpnMessage[] = "addThirdPartyVpn";
const char kConfigureThirdPartyVpnMessage[] = "configureThirdPartyVpn";
const char kRequestArcVpnProviders[] = "requestArcVpnProviders";
const char kSendArcVpnProviders[] = "sendArcVpnProviders";
const char kRequestGmsCoreNotificationsDisabledDeviceNames[] =
"requestGmsCoreNotificationsDisabledDeviceNames";
const char kSendGmsCoreNotificationsDisabledDeviceNames[] =
"sendGmsCoreNotificationsDisabledDeviceNames";
Profile* GetProfileForPrimaryUser() {
return ProfileHelper::Get()->GetProfileByUser(
user_manager::UserManager::Get()->GetPrimaryUser());
}
std::unique_ptr<base::DictionaryValue> ArcVpnProviderToValue(
const app_list::ArcVpnProviderManager::ArcVpnProvider* arc_vpn_provider) {
std::unique_ptr<base::DictionaryValue> serialized_entry =
std::make_unique<base::DictionaryValue>();
serialized_entry->SetString("PackageName", arc_vpn_provider->package_name);
serialized_entry->SetString("ProviderName", arc_vpn_provider->app_name);
serialized_entry->SetString("AppID", arc_vpn_provider->app_id);
serialized_entry->SetDouble("LastLaunchTime",
arc_vpn_provider->last_launch_time.ToDoubleT());
return serialized_entry;
}
} // namespace
namespace settings {
InternetHandler::InternetHandler(Profile* profile) : profile_(profile) {
DCHECK(profile_);
arc_vpn_provider_manager_ = app_list::ArcVpnProviderManager::Get(profile_);
if (arc_vpn_provider_manager_)
arc_vpn_provider_manager_->AddObserver(this);
TetherService* tether_service = TetherService::Get(profile);
gms_core_notifications_state_tracker_ =
tether_service ? tether_service->GetGmsCoreNotificationsStateTracker()
: nullptr;
if (gms_core_notifications_state_tracker_)
gms_core_notifications_state_tracker_->AddObserver(this);
}
InternetHandler::~InternetHandler() {
if (arc_vpn_provider_manager_)
arc_vpn_provider_manager_->RemoveObserver(this);
if (gms_core_notifications_state_tracker_)
gms_core_notifications_state_tracker_->RemoveObserver(this);
}
void InternetHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
kAddThirdPartyVpnMessage,
base::BindRepeating(&InternetHandler::AddThirdPartyVpn,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
kConfigureThirdPartyVpnMessage,
base::BindRepeating(&InternetHandler::ConfigureThirdPartyVpn,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
kRequestArcVpnProviders,
base::BindRepeating(&InternetHandler::RequestArcVpnProviders,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
kRequestGmsCoreNotificationsDisabledDeviceNames,
base::BindRepeating(
&InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames,
base::Unretained(this)));
}
void InternetHandler::OnJavascriptAllowed() {}
void InternetHandler::OnJavascriptDisallowed() {}
void InternetHandler::OnArcVpnProviderRemoved(const std::string& package_name) {
if (arc_vpn_providers_.find(package_name) == arc_vpn_providers_.end())
return;
arc_vpn_providers_.erase(package_name);
SendArcVpnProviders();
}
void InternetHandler::OnArcVpnProvidersRefreshed(
const std::vector<
std::unique_ptr<app_list::ArcVpnProviderManager::ArcVpnProvider>>&
arc_vpn_providers) {
SetArcVpnProviders(arc_vpn_providers);
}
void InternetHandler::OnArcVpnProviderUpdated(
app_list::ArcVpnProviderManager::ArcVpnProvider* arc_vpn_provider) {
arc_vpn_providers_[arc_vpn_provider->package_name] =
ArcVpnProviderToValue(arc_vpn_provider);
SendArcVpnProviders();
}
void InternetHandler::OnGmsCoreNotificationStateChanged() {
SetGmsCoreNotificationsDisabledDeviceNames();
}
void InternetHandler::AddThirdPartyVpn(const base::ListValue* args) {
std::string app_id;
if (args->GetSize() < 1 || !args->GetString(0, &app_id)) {
NOTREACHED() << "Invalid args for: " << kAddThirdPartyVpnMessage;
return;
}
if (app_id.empty()) {
NET_LOG(ERROR) << "Empty app id for " << kAddThirdPartyVpnMessage;
return;
}
if (profile_ != GetProfileForPrimaryUser() || profile_->IsChild()) {
NET_LOG(ERROR)
<< "Only the primary user and non-child accounts can add VPNs";
return;
}
// Request to launch Arc VPN provider.
const auto* arc_app_list_prefs = ArcAppListPrefs::Get(profile_);
if (arc_app_list_prefs && arc_app_list_prefs->GetApp(app_id)) {
arc::LaunchApp(profile_, app_id, ui::EF_NONE,
arc::UserInteractionType::APP_STARTED_FROM_SETTINGS);
return;
}
// Request that the third-party VPN provider identified by |provider_id|
// show its "add network" dialog.
VpnServiceFactory::GetForBrowserContext(GetProfileForPrimaryUser())
->SendShowAddDialogToExtension(app_id);
}
void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) {
std::string guid;
if (args->GetSize() < 1 || !args->GetString(0, &guid)) {
NOTREACHED() << "Invalid args for: " << kConfigureThirdPartyVpnMessage;
return;
}
if (profile_ != GetProfileForPrimaryUser()) {
NET_LOG(ERROR) << "Only the primary user can configure VPNs";
return;
}
const NetworkState* network =
NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
guid);
if (!network) {
NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Network not found: " << guid;
return;
}
if (network->type() != shill::kTypeVPN) {
NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Network is not a VPN: " << guid;
return;
}
if (network->GetVpnProviderType() == shill::kProviderThirdPartyVpn) {
// Request that the third-party VPN provider used by the |network| show a
// configuration dialog for it.
VpnServiceFactory::GetForBrowserContext(profile_)
->SendShowConfigureDialogToExtension(network->vpn_provider()->id,
network->name());
return;
}
if (network->GetVpnProviderType() == shill::kProviderArcVpn) {
auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD(
arc::ArcServiceManager::Get()->arc_bridge_service()->net(),
ConfigureAndroidVpn);
if (!net_instance) {
NET_LOG(ERROR) << "ConfigureThirdPartyVpn: API is unavailable";
return;
}
net_instance->ConfigureAndroidVpn();
return;
}
NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Unsupported VPN type: "
<< network->GetVpnProviderType() << " For: " << guid;
}
void InternetHandler::RequestArcVpnProviders(const base::ListValue* args) {
if (!arc_vpn_provider_manager_)
return;
AllowJavascript();
SetArcVpnProviders(arc_vpn_provider_manager_->GetArcVpnProviders());
}
void InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames(
const base::ListValue* args) {
AllowJavascript();
SetGmsCoreNotificationsDisabledDeviceNames();
}
void InternetHandler::SetArcVpnProviders(
const std::vector<
std::unique_ptr<app_list::ArcVpnProviderManager::ArcVpnProvider>>&
arc_vpn_providers) {
arc_vpn_providers_.clear();
for (const auto& arc_vpn_provider : arc_vpn_providers) {
arc_vpn_providers_[arc_vpn_provider->package_name] =
ArcVpnProviderToValue(arc_vpn_provider.get());
}
SendArcVpnProviders();
}
void InternetHandler::SendArcVpnProviders() {
if (!IsJavascriptAllowed())
return;
base::ListValue arc_vpn_providers_value;
for (const auto& iter : arc_vpn_providers_) {
arc_vpn_providers_value.GetList().push_back(iter.second->Clone());
}
FireWebUIListener(kSendArcVpnProviders, arc_vpn_providers_value);
}
void InternetHandler::SetGmsCoreNotificationsDisabledDeviceNames() {
if (!gms_core_notifications_state_tracker_) {
// No device names should be present in the list if
// |gms_core_notifications_state_tracker_| is null.
DCHECK(device_names_without_notifications_.empty());
return;
}
device_names_without_notifications_.clear();
const std::vector<std::string> device_names =
gms_core_notifications_state_tracker_
->GetGmsCoreNotificationsDisabledDeviceNames();
for (const auto& device_name : device_names) {
device_names_without_notifications_.emplace_back(
std::make_unique<base::Value>(device_name));
}
SendGmsCoreNotificationsDisabledDeviceNames();
}
void InternetHandler::SendGmsCoreNotificationsDisabledDeviceNames() {
if (!IsJavascriptAllowed())
return;
base::ListValue device_names_value;
for (const auto& device_name : device_names_without_notifications_)
device_names_value.GetList().push_back(device_name->Clone());
FireWebUIListener(kSendGmsCoreNotificationsDisabledDeviceNames,
device_names_value);
}
gfx::NativeWindow InternetHandler::GetNativeWindow() const {
return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
}
void InternetHandler::SetGmsCoreNotificationsStateTrackerForTesting(
chromeos::tether::GmsCoreNotificationsStateTracker*
gms_core_notifications_state_tracker) {
if (gms_core_notifications_state_tracker_)
gms_core_notifications_state_tracker_->RemoveObserver(this);
gms_core_notifications_state_tracker_ = gms_core_notifications_state_tracker;
gms_core_notifications_state_tracker_->AddObserver(this);
}
} // namespace settings
} // namespace chromeos