Skip to content

Commit

Permalink
[CrOS Network] Add NetworkDetailedView class
Browse files Browse the repository at this point in the history
This CL continues the task of refactoring Quick settings Network
section. It adds a base class that will be implemented by both VPN and
other networks.

Bug: b/207089013
Test: Added new ash_unittest and ran CQ.
Test: Built and deployed chrome, made sure there where no failures.
Change-Id: I5469457b82e6f70c73169f7d7404991cabb52b88
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3526699
Reviewed-by: Chad Duffin <chadduffin@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Theo Johnson-kanu <tjohnsonkanu@google.com>
Cr-Commit-Position: refs/heads/main@{#983980}
  • Loading branch information
Theo Johnson-Kanu authored and Chromium LUCI CQ committed Mar 22, 2022
1 parent e8f8635 commit 1a480de
Show file tree
Hide file tree
Showing 10 changed files with 532 additions and 1 deletion.
7 changes: 7 additions & 0 deletions ash/BUILD.gn
Expand Up @@ -1251,6 +1251,10 @@ component("ash") {
"system/network/auto_connect_notifier.h",
"system/network/cellular_setup_notifier.cc",
"system/network/cellular_setup_notifier.h",
"system/network/fake_network_detailed_view_delegate.cc",
"system/network/fake_network_detailed_view_delegate.h",
"system/network/network_detailed_view.cc",
"system/network/network_detailed_view.h",
"system/network/network_feature_pod_button.cc",
"system/network/network_feature_pod_button.h",
"system/network/network_feature_pod_button_legacy.cc",
Expand Down Expand Up @@ -1520,6 +1524,8 @@ component("ash") {
"system/tray/actionable_view.h",
"system/tray/detailed_view_delegate.cc",
"system/tray/detailed_view_delegate.h",
"system/tray/fake_detailed_view_delegate.cc",
"system/tray/fake_detailed_view_delegate.h",
"system/tray/hover_highlight_view.cc",
"system/tray/hover_highlight_view.h",
"system/tray/interacted_by_tap_recorder.cc",
Expand Down Expand Up @@ -2619,6 +2625,7 @@ test("ash_unittests") {
"system/network/active_network_icon_unittest.cc",
"system/network/auto_connect_notifier_unittest.cc",
"system/network/cellular_setup_notifier_unittest.cc",
"system/network/network_detailed_view_unittest.cc",
"system/network/network_feature_pod_button_unittest.cc",
"system/network/network_feature_pod_controller_unittest.cc",
"system/network/network_icon_unittest.cc",
Expand Down
5 changes: 4 additions & 1 deletion ash/public/cpp/test/test_system_tray_client.cc
Expand Up @@ -90,7 +90,10 @@ void TestSystemTrayClient::ShowThirdPartyVpnCreate(

void TestSystemTrayClient::ShowArcVpnCreate(const std::string& app_id) {}

void TestSystemTrayClient::ShowNetworkSettings(const std::string& network_id) {}
void TestSystemTrayClient::ShowNetworkSettings(const std::string& network_id) {
show_network_settings_count_++;
last_network_settings_network_id_ = network_id;
}

void TestSystemTrayClient::ShowMultiDeviceSetup() {
show_multi_device_setup_count_++;
Expand Down
10 changes: 10 additions & 0 deletions ash/public/cpp/test/test_system_tray_client.h
Expand Up @@ -68,6 +68,10 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
return show_bluetooth_settings_count_;
}

int show_network_settings_count() const {
return show_network_settings_count_;
}

int show_bluetooth_pairing_dialog_count() const {
return show_bluetooth_pairing_dialog_count_;
}
Expand Down Expand Up @@ -102,7 +106,12 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
return last_bluetooth_settings_device_id_;
}

const std::string& last_network_settings_network_id() const {
return last_network_settings_network_id_;
}

private:
int show_network_settings_count_ = 0;
int show_bluetooth_settings_count_ = 0;
int show_bluetooth_pairing_dialog_count_ = 0;
int show_multi_device_setup_count_ = 0;
Expand All @@ -113,6 +122,7 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
int show_sim_unlock_settings_count_ = 0;
int show_firmware_update_count_ = 0;
std::string last_bluetooth_settings_device_id_;
std::string last_network_settings_network_id_;
};

} // namespace ash
Expand Down
27 changes: 27 additions & 0 deletions ash/system/network/fake_network_detailed_view_delegate.cc
@@ -0,0 +1,27 @@
// Copyright 2022 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 "ash/system/network/fake_network_detailed_view_delegate.h"

#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"

namespace ash {
namespace tray {

namespace {

using chromeos::network_config::mojom::NetworkStatePropertiesPtr;

}

FakeNetworkDetailedViewDelegate::FakeNetworkDetailedViewDelegate() {}
FakeNetworkDetailedViewDelegate::~FakeNetworkDetailedViewDelegate() = default;

void FakeNetworkDetailedViewDelegate::OnNetworkListItemSelected(
const NetworkStatePropertiesPtr& network) {
last_network_list_item_selected_ = mojo::Clone(network);
}

} // namespace tray
} // namespace ash
47 changes: 47 additions & 0 deletions ash/system/network/fake_network_detailed_view_delegate.h
@@ -0,0 +1,47 @@
// Copyright 2022 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.

#ifndef ASH_SYSTEM_NETWORK_FAKE_NETWORK_DETAILED_VIEW_DELEGATE_H_
#define ASH_SYSTEM_NETWORK_FAKE_NETWORK_DETAILED_VIEW_DELEGATE_H_

#include "ash/ash_export.h"
#include "ash/system/network/network_detailed_view.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"

namespace ash {
namespace tray {

namespace {

using chromeos::network_config::mojom::NetworkStatePropertiesPtr;

}

// Fake of NetworkDetailedView::Delegate implementation.
class ASH_EXPORT FakeNetworkDetailedViewDelegate
: public NetworkDetailedView::Delegate {
public:
FakeNetworkDetailedViewDelegate();
FakeNetworkDetailedViewDelegate(const FakeNetworkDetailedViewDelegate&) =
delete;
FakeNetworkDetailedViewDelegate& operator=(
const FakeNetworkDetailedViewDelegate&) = delete;
~FakeNetworkDetailedViewDelegate() override;

// NetworkDetailedView::Delegate:
void OnNetworkListItemSelected(
const NetworkStatePropertiesPtr& network) override;

const NetworkStatePropertiesPtr& last_network_list_item_selected() const {
return last_network_list_item_selected_;
}

private:
NetworkStatePropertiesPtr last_network_list_item_selected_;
};

} // namespace tray
} // namespace ash

#endif // ASH_SYSTEM_NETWORK_FAKE_NETWORK_DETAILED_VIEW_DELEGATE_H_
133 changes: 133 additions & 0 deletions ash/system/network/network_detailed_view.cc
@@ -0,0 +1,133 @@
// Copyright 2022 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 "ash/system/network/network_detailed_view.h"

#include "ash/public/cpp/system_tray_client.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/network/tray_network_state_model.h"
#include "ash/system/tray/detailed_view_delegate.h"
#include "ash/system/tray/tri_view.h"
#include "base/check.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/button.h"

namespace ash {
namespace tray {

NetworkDetailedView::NetworkDetailedView(
DetailedViewDelegate* detailed_view_delegate,
Delegate* delegate,
ListType list_type)
: TrayDetailedView(detailed_view_delegate),
list_type_(list_type),
login_(Shell::Get()->session_controller()->login_status()),
model_(Shell::Get()->system_tray_model()->network_state_model()),
delegate_(delegate) {
DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled());

CreateTitleRow(list_type_ == ListType::LIST_TYPE_NETWORK
? IDS_ASH_STATUS_TRAY_NETWORK
: IDS_ASH_STATUS_TRAY_VPN);
CreateTitleRowButtons();
CreateScrollableList();
// TODO(b/207089013): add metrics for UI surface displayed.
}

NetworkDetailedView::~NetworkDetailedView() = default;

void NetworkDetailedView::NotifyNetworkListChanged() {
scroll_content()->InvalidateLayout();
Layout();
}

void NetworkDetailedView::HandleViewClicked(views::View* view) {
if (login_ == LoginStatus::LOCKED)
return;
// TODO(b/207089013): Call OnNetworkListItemSelected() on delegate() and pass
// in a cast of either NetworkListNetworkItemView or NetworkListVPNItemView
// when available, also add test for this.
}

views::View* NetworkDetailedView::network_list() {
return scroll_content();
}

void NetworkDetailedView::CreateTitleRowButtons() {
DCHECK(!info_button_);
tri_view()->SetContainerVisible(TriView::Container::END, true);

std::unique_ptr<views::Button> info = base::WrapUnique(
CreateInfoButton(base::BindRepeating(&NetworkDetailedView::OnInfoClicked,
weak_ptr_factory_.GetWeakPtr()),
IDS_ASH_STATUS_TRAY_NETWORK_INFO));
info->SetID(static_cast<int>(NetworkDetailedViewChildId::kInfoButton));
info_button_ = info.get();
tri_view()->AddView(TriView::Container::END, info.release());

DCHECK(!settings_button_);

std::unique_ptr<views::Button> settings =
base::WrapUnique(CreateSettingsButton(
base::BindRepeating(&NetworkDetailedView::OnSettingsClicked,
weak_ptr_factory_.GetWeakPtr()),
IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS));
settings->SetID(
static_cast<int>(NetworkDetailedViewChildId::kSettingsButton));
settings_button_ = settings.get();
tri_view()->AddView(TriView::Container::END, settings.release());
}

bool NetworkDetailedView::ShouldIncludeDeviceAddresses() {
return list_type_ == LIST_TYPE_NETWORK;
}

void NetworkDetailedView::OnInfoBubbleDestroyed() {
info_bubble_ = nullptr;

// Widget of info bubble is activated while info bubble is shown. To move
// focus back to the widget of this view, activate it again here.
GetWidget()->Activate();
}

void NetworkDetailedView::OnInfoClicked() {
if (CloseInfoBubble())
return;

info_bubble_ =
new NetworkInfoBubble(weak_ptr_factory_.GetWeakPtr(), tri_view());
views::BubbleDialogDelegateView::CreateBubble(info_bubble_)->Show();
info_bubble_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, false);
}

bool NetworkDetailedView::CloseInfoBubble() {
if (!info_bubble_)
return false;

info_bubble_->GetWidget()->Close();
return true;
}

void NetworkDetailedView::OnSettingsClicked() {
// TODO(b/207089013): Record user action metrics here

const std::string guid = model_->default_network()
? model_->default_network()->guid
: std::string();

CloseBubble(); // Deletes |this|.

SystemTrayClient* system_tray_client =
Shell::Get()->system_tray_model()->client();
if (system_tray_client)
system_tray_client->ShowNetworkSettings(guid);
}

} // namespace tray
} // namespace ash
110 changes: 110 additions & 0 deletions ash/system/network/network_detailed_view.h
@@ -0,0 +1,110 @@
// Copyright 2022 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.

#ifndef ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_
#define ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_

#include "ash/ash_export.h"
#include "ash/login_status.h"
#include "ash/system/network/network_info_bubble.h"
#include "ash/system/tray/tray_detailed_view.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"

namespace views {

class View;

} // namespace views

namespace ash {

class TrayNetworkStateModel;
class DetailedViewDelegate;
class Button;

namespace tray {

// This class defines both the interface used to interact with the detailed
// Network page within the quick settings, including the view responsible for
// containing the network list. This class includes the declaration for the
// delegate interface it uses to propagate user interactions.
class ASH_EXPORT NetworkDetailedView : public TrayDetailedView,
public NetworkInfoBubble::Delegate {
public:
// This class defines the interface that NetworkDetailedView will use to
// propagate user interactions.
class Delegate {
public:
Delegate() = default;
virtual ~Delegate() = default;

virtual void OnNetworkListItemSelected(
const chromeos::network_config::mojom::NetworkStatePropertiesPtr&
network) = 0;
};

NetworkDetailedView(const NetworkDetailedView&) = delete;
NetworkDetailedView& operator=(const NetworkDetailedView&) = delete;
~NetworkDetailedView() override;

// Notifies that the network list has changed and the layout is invalid.
void NotifyNetworkListChanged();

// Returns the network list.
views::View* network_list();

protected:
enum ListType { LIST_TYPE_NETWORK, LIST_TYPE_VPN };

NetworkDetailedView(DetailedViewDelegate* detailed_view_delegate,
Delegate* delegate,
ListType list_type);

Delegate* delegate() { return delegate_; }

private:
friend class NetworkDetailedViewTest;

// Used for testing. Starts at 1 because view IDs should not be 0.
enum class NetworkDetailedViewChildId {
kInfoButton = 1,
kSettingsButton = 2,
};

void CreateTitleRowButtons();
void OnInfoClicked();
bool CloseInfoBubble();
void OnSettingsClicked();

// TrayDetailedView:
void HandleViewClicked(views::View* view) override;

// NetworkInfoBubble::Delegate:
bool ShouldIncludeDeviceAddresses() override;
void OnInfoBubbleDestroyed() override;

// Type of list (all non-VPN netwoks, or only VPN networks).
const ListType list_type_;

// Used to cache the login status on creation.
const LoginStatus login_;

TrayNetworkStateModel* model_;

views::Button* info_button_ = nullptr;
views::Button* settings_button_ = nullptr;

// A small bubble for displaying network info.
NetworkInfoBubble* info_bubble_ = nullptr;

Delegate* delegate_;

base::WeakPtrFactory<NetworkDetailedView> weak_ptr_factory_{this};
};

} // namespace tray
} // namespace ash

#endif // ASH_SYSTEM_NETWORK_NETWORK_DETAILED_VIEW_H_

0 comments on commit 1a480de

Please sign in to comment.