network_info_bubble.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2021 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. #include "ash/system/network/network_info_bubble.h"
  5. #include "ash/constants/ash_features.h"
  6. #include "ash/shell.h"
  7. #include "ash/strings/grit/ash_strings.h"
  8. #include "ash/system/model/system_tray_model.h"
  9. #include "ash/system/network/tray_network_state_model.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
  12. #include "ui/base/l10n/l10n_util.h"
  13. #include "ui/base/ui_base_types.h"
  14. #include "ui/gfx/geometry/insets.h"
  15. #include "ui/views/bubble/bubble_border.h"
  16. #include "ui/views/controls/label.h"
  17. #include "ui/views/layout/fill_layout.h"
  18. #include "ui/views/view.h"
  19. namespace ash {
  20. namespace {
  21. using chromeos::network_config::mojom::DeviceStateProperties;
  22. using chromeos::network_config::mojom::NetworkStateProperties;
  23. using chromeos::network_config::mojom::NetworkType;
  24. // This margin value is used for:
  25. // - Margins inside the border.
  26. // - Horizontal spacing between the border and parent bubble border.
  27. // - Distance between top of the border and the bottom of the anchor view
  28. // (horizontal rule).
  29. constexpr int kBubbleMargin = 8;
  30. // Elevation used for the bubble shadow effect (tiny).
  31. constexpr int kBubbleShadowElevation = 2;
  32. // 00:00:00:00:00:00 is provided when a device MAC address cannot be retrieved.
  33. constexpr char kMissingMacAddress[] = "00:00:00:00:00:00";
  34. std::string ComputeMacAddress(NetworkType network_type) {
  35. const DeviceStateProperties* device =
  36. Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
  37. network_type);
  38. if (!device || !device->mac_address ||
  39. device->mac_address == kMissingMacAddress) {
  40. return std::string();
  41. }
  42. return *device->mac_address;
  43. }
  44. } // namespace
  45. NetworkInfoBubble::NetworkInfoBubble(base::WeakPtr<Delegate> delegate,
  46. views::View* anchor)
  47. : views::BubbleDialogDelegateView(anchor, views::BubbleBorder::TOP_RIGHT),
  48. delegate_(delegate) {
  49. DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled());
  50. SetButtons(ui::DIALOG_BUTTON_NONE);
  51. set_margins(gfx::Insets(kBubbleMargin));
  52. SetArrow(views::BubbleBorder::NONE);
  53. set_shadow(views::BubbleBorder::NO_SHADOW);
  54. SetNotifyEnterExitOnChild(true);
  55. SetLayoutManager(std::make_unique<views::FillLayout>());
  56. std::unique_ptr<views::Label> label =
  57. std::make_unique<views::Label>(ComputeInfoText());
  58. label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
  59. label->SetID(kNetworkInfoBubbleLabelViewId);
  60. label->SetMultiLine(true);
  61. label->SetSelectable(true);
  62. AddChildView(label.release());
  63. }
  64. NetworkInfoBubble::~NetworkInfoBubble() {
  65. if (delegate_)
  66. delegate_->OnInfoBubbleDestroyed();
  67. }
  68. gfx::Size NetworkInfoBubble::CalculatePreferredSize() const {
  69. // This bubble should be inset by kBubbleMargin on the left and right relative
  70. // to the parent bubble.
  71. const gfx::Size anchor_size = GetAnchorView()->size();
  72. int contents_width =
  73. anchor_size.width() - 2 * kBubbleMargin - margins().width();
  74. return gfx::Size(contents_width, GetHeightForWidth(contents_width));
  75. }
  76. void NetworkInfoBubble::OnMouseExited(const ui::MouseEvent& event) {
  77. GetWidget()->Close(); // Deletes |this|.
  78. }
  79. void NetworkInfoBubble::OnBeforeBubbleWidgetInit(
  80. views::Widget::InitParams* params,
  81. views::Widget* widget) const {
  82. params->shadow_type = views::Widget::InitParams::ShadowType::kDrop;
  83. params->shadow_elevation = kBubbleShadowElevation;
  84. params->name = "NetworkInfoBubble";
  85. }
  86. std::u16string NetworkInfoBubble::ComputeInfoText() {
  87. DCHECK(delegate_);
  88. std::u16string info_text;
  89. auto add_address_if_exists = [&info_text](std::string address, int text_id) {
  90. if (address.empty())
  91. return;
  92. if (!info_text.empty())
  93. info_text += u"\n";
  94. info_text +=
  95. l10n_util::GetStringFUTF16(text_id, base::UTF8ToUTF16(address));
  96. };
  97. const NetworkStateProperties* default_network = Shell::Get()
  98. ->system_tray_model()
  99. ->network_state_model()
  100. ->default_network();
  101. const DeviceStateProperties* device =
  102. default_network
  103. ? Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
  104. default_network->type)
  105. : nullptr;
  106. if (device) {
  107. if (device->ipv4_address) {
  108. add_address_if_exists(device->ipv4_address->ToString(),
  109. IDS_ASH_STATUS_TRAY_IP_ADDRESS);
  110. }
  111. if (device->ipv6_address) {
  112. add_address_if_exists(device->ipv6_address->ToString(),
  113. IDS_ASH_STATUS_TRAY_IPV6_ADDRESS);
  114. }
  115. }
  116. if (delegate_->ShouldIncludeDeviceAddresses()) {
  117. add_address_if_exists(ComputeMacAddress(NetworkType::kEthernet),
  118. IDS_ASH_STATUS_TRAY_ETHERNET_ADDRESS);
  119. add_address_if_exists(ComputeMacAddress(NetworkType::kWiFi),
  120. IDS_ASH_STATUS_TRAY_WIFI_ADDRESS);
  121. add_address_if_exists(ComputeMacAddress(NetworkType::kCellular),
  122. IDS_ASH_STATUS_TRAY_CELLULAR_ADDRESS);
  123. }
  124. // Avoid returning an empty bubble when no network information is available.
  125. if (info_text.empty())
  126. return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NO_NETWORKS);
  127. return info_text;
  128. }
  129. } // namespace ash