blob: 8367559e562508cc280f1c395897c978ee9c2577 [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/options/network_config_view.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_state.h"
#include "chromeos/network/network_state_handler.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/common/net.mojom.h"
#include "components/arc/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 kAddNetworkMessage[] = "addNetwork";
const char kConfigureNetworkMessage[] = "configureNetwork";
const char kRequestArcVpnProviders[] = "requestArcVpnProviders";
const char kSendArcVpnProviders[] = "sendArcVpnProviders";
const char kRequestGmsCoreNotificationsDisabledDeviceNames[] =
"requestGmsCoreNotificationsDisabledDeviceNames";
const char kSendGmsCoreNotificationsDisabledDeviceNames[] =
"sendGmsCoreNotificationsDisabledDeviceNames";
std::string ServicePathFromGuid(const std::string& guid) {
const NetworkState* network =
NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
guid);
return network ? network->path() : "";
}
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() {
// TODO(stevenjb): Eliminate once network configuration UI is integrated
// into settings.
web_ui()->RegisterMessageCallback(
kAddNetworkMessage, base::BindRepeating(&InternetHandler::AddNetwork,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
kConfigureNetworkMessage,
base::BindRepeating(&InternetHandler::ConfigureNetwork,
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::AddNetwork(const base::ListValue* args) {
std::string onc_type;
if (args->GetSize() < 1 || !args->GetString(0, &onc_type)) {
NOTREACHED() << "Invalid args for: " << kAddNetworkMessage;
return;
}
if (onc_type == ::onc::network_type::kVPN) {
std::string app_id;
if (args->GetSize() >= 2)
args->GetString(1, &app_id);
if (app_id.empty()) {
// Show the "add network" dialog for the built-in OpenVPN/L2TP provider.
NetworkConfigView::ShowForType(shill::kTypeVPN);
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);
return;
}
// Request that the third-party VPN provider identified by |provider_id|
// show its "add network" dialog.
VpnServiceFactory::GetForBrowserContext(GetProfileForPrimaryUser())
->SendShowAddDialogToExtension(app_id);
} else if (onc_type == ::onc::network_type::kWiFi) {
NetworkConfigView::ShowForType(shill::kTypeWifi);
} else {
LOG(ERROR) << "Unsupported type for: " << kAddNetworkMessage;
}
}
void InternetHandler::ConfigureNetwork(const base::ListValue* args) {
std::string guid;
if (args->GetSize() < 1 || !args->GetString(0, &guid)) {
NOTREACHED() << "Invalid args for: " << kConfigureNetworkMessage;
return;
}
const std::string service_path = ServicePathFromGuid(guid);
if (service_path.empty()) {
LOG(ERROR) << "Network not found: " << guid;
return;
}
const NetworkState* network =
NetworkHandler::Get()->network_state_handler()->GetNetworkState(
service_path);
if (!network) {
LOG(ERROR) << "Network not found with service_path: " << service_path;
return;
}
if (network->type() == shill::kTypeVPN) {
if (profile_ != GetProfileForPrimaryUser())
return;
if (network->vpn_provider_type() == 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;
} else if (network->vpn_provider_type() == shill::kProviderArcVpn) {
auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD(
arc::ArcServiceManager::Get()->arc_bridge_service()->net(),
ConfigureAndroidVpn);
if (!net_instance) {
LOG(ERROR) << "User requested VPN configuration but API is unavailable";
return;
}
net_instance->ConfigureAndroidVpn();
return;
}
}
NetworkConfigView::ShowForNetworkId(network->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