chromium/chrome/browser/ui/webui/ash/internet_detail_dialog.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/browser/ui/webui/ash/internet_detail_dialog.h"

#include "ash/constants/ash_features.h"
#include "ash/public/cpp/connectivity_services.h"
#include "ash/public/cpp/network_config_service.h"
#include "base/json/json_writer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ash/cellular_setup/cellular_setup_localized_strings_provider.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/internet_detail_dialog_resources.h"
#include "chrome/grit/internet_detail_dialog_resources_map.h"
#include "chromeos/ash/components/network/network_connect.h"
#include "chromeos/ash/components/network/network_handler.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_util.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "chromeos/strings/grit/chromeos_strings.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
#include "ui/chromeos/strings/network/network_element_localized_strings_provider.h"
#include "ui/webui/color_change_listener/color_change_handler.h"

namespace ash {

namespace {

// Matches the width of the Settings content.
constexpr int kInternetDetailDialogWidth = 640;

int s_internet_detail_dialog_count = 0;

void AddInternetStrings(content::WebUIDataSource* html_source) {
  // Add default strings first.
  ui::network_element::AddLocalizedStrings(html_source);
  ui::network_element::AddOncLocalizedStrings(html_source);
  ui::network_element::AddDetailsLocalizedStrings(html_source);
  // Add additional strings and overrides needed by the dialog.
  struct {
    const char* name;
    int id;
  } localized_strings[] = {
      {"cancel", IDS_CANCEL},
      {"close", IDS_CLOSE},
      {"networkButtonConnect", IDS_SETTINGS_INTERNET_BUTTON_CONNECT},
      {"networkButtonDisconnect", IDS_SETTINGS_INTERNET_BUTTON_DISCONNECT},
      {"networkButtonForget", IDS_SETTINGS_INTERNET_BUTTON_FORGET},
      {"networkButtonSignin", IDS_SETTINGS_INTERNET_BUTTON_SIGNIN},
      {"networkIPAddress", IDS_SETTINGS_INTERNET_NETWORK_IP_ADDRESS},
      {"networkSectionNetwork", IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK},
      {"networkSectionProxy", IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY},
      {"networkIPConfigAuto", IDS_SETTINGS_INTERNET_NETWORK_IP_CONFIG_AUTO},
      {"save", IDS_SAVE},
      // Override for ui::network_element::AddDetailsLocalizedStrings
      {"networkProxyConnectionType",
       IDS_SETTINGS_INTERNET_NETWORK_PROXY_CONNECTION_TYPE_DIALOG},
  };
  for (const auto& entry : localized_strings)
    html_source->AddLocalizedString(entry.name, entry.id);
}

std::string GetNetworkName8(const NetworkState& network) {
  return network.Matches(NetworkTypePattern::Ethernet())
             ? l10n_util::GetStringUTF8(IDS_NETWORK_TYPE_ETHERNET)
             : network.name();
}

class PortalNetworkMessageHandler : public content::WebUIMessageHandler {
 public:
  PortalNetworkMessageHandler() = default;
  ~PortalNetworkMessageHandler() override = default;

  void RegisterMessages() override {
    web_ui()->RegisterMessageCallback(
        "showPortalSignin",
        base::BindRepeating(&PortalNetworkMessageHandler::ShowPortalSignin,
                            base::Unretained(this)));
  }

 private:
  void ShowPortalSignin(const base::Value::List& args) {
    if (args.size() < 1 || !args[0].is_string()) {
      NOTREACHED_IN_MIGRATION() << "Invalid args for: ShowPortalSignin";
      return;
    }
    const std::string& guid = args[0].GetString();
    NetworkConnect::Get()->ShowPortalSignin(guid,
                                            NetworkConnect::Source::kSettings);
  }
};

}  // namespace

// static
bool InternetDetailDialog::IsShown() {
  return s_internet_detail_dialog_count > 0;
}

// static
void InternetDetailDialog::ShowDialog(const std::string& network_id,
                                      gfx::NativeWindow parent) {
  auto* network_state_handler = NetworkHandler::Get()->network_state_handler();
  const NetworkState* network;
  if (!network_id.empty())
    network = network_state_handler->GetNetworkStateFromGuid(network_id);
  else
    network = network_state_handler->DefaultNetwork();
  if (!network) {
    LOG(ERROR) << "Network not found: " << network_id;
    return;
  }
  auto* instance = SystemWebDialogDelegate::FindInstance(network->guid());
  if (instance) {
    instance->Focus();
    return;
  }

  InternetDetailDialog* dialog = new InternetDetailDialog(*network);
  dialog->ShowSystemDialog(parent);
}

InternetDetailDialog::InternetDetailDialog(const NetworkState& network)
    : SystemWebDialogDelegate(GURL(chrome::kChromeUIInternetDetailDialogURL),
                              /* title= */ std::u16string()),
      network_id_(network.guid()),
      network_type_(network_util::TranslateShillTypeToONC(network.type())),
      network_name_(GetNetworkName8(network)) {
  ++s_internet_detail_dialog_count;
}

InternetDetailDialog::~InternetDetailDialog() {
  --s_internet_detail_dialog_count;
}

std::string InternetDetailDialog::Id() {
  return network_id_;
}

void InternetDetailDialog::GetDialogSize(gfx::Size* size) const {
  size->SetSize(kInternetDetailDialogWidth,
                SystemWebDialogDelegate::kDialogHeight);
}

std::string InternetDetailDialog::GetDialogArgs() const {
  base::Value::Dict args;
  args.Set("type", network_type_);
  args.Set("guid", network_id_);
  args.Set("name", network_name_);
  std::string json;
  base::JSONWriter::Write(args, &json);
  return json;
}

// InternetDetailDialogUI

InternetDetailDialogUI::InternetDetailDialogUI(content::WebUI* web_ui)
    : ui::MojoWebDialogUI(web_ui) {
  web_ui->AddMessageHandler(std::make_unique<PortalNetworkMessageHandler>());

  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
      Profile::FromWebUI(web_ui), chrome::kChromeUIInternetDetailDialogHost);
  source->AddBoolean("showTechnologyBadge",
                     !features::IsSeparateNetworkIconsEnabled());
  source->AddBoolean("apnRevamp", features::IsApnRevampEnabled());
  cellular_setup::AddNonStringLoadTimeData(source);
  AddInternetStrings(source);
  source->AddLocalizedString("title", IDS_SETTINGS_INTERNET_DETAIL);

  webui::SetupWebUIDataSource(
      source,
      base::make_span(kInternetDetailDialogResources,
                      kInternetDetailDialogResourcesSize),
      IDR_INTERNET_DETAIL_DIALOG_INTERNET_DETAIL_DIALOG_CONTAINER_HTML);
  source->DisableTrustedTypesCSP();
}

InternetDetailDialogUI::~InternetDetailDialogUI() {}

void InternetDetailDialogUI::BindInterface(
    mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
        receiver) {
  GetNetworkConfigService(std::move(receiver));
}

void InternetDetailDialogUI::BindInterface(
    mojo::PendingReceiver<color_change_listener::mojom::PageHandler> receiver) {
  color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>(
      web_ui()->GetWebContents(), std::move(receiver));
}

void InternetDetailDialogUI::BindInterface(
    mojo::PendingReceiver<chromeos::connectivity::mojom::PasspointService>
        receiver) {
  ash::GetPasspointService(std::move(receiver));
}

WEB_UI_CONTROLLER_TYPE_IMPL(InternetDetailDialogUI)

}  // namespace ash