Home | History | Annotate | Download | only in network
      1 // Copyright 2014 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 
      5 #include "ui/chromeos/network/network_list.h"
      6 
      7 #include "chromeos/dbus/dbus_thread_manager.h"
      8 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
      9 #include "chromeos/dbus/power_manager_client.h"
     10 #include "chromeos/network/network_state.h"
     11 #include "chromeos/network/network_state_handler.h"
     12 #include "chromeos/network/network_state_handler_observer.h"
     13 #include "grit/ui_chromeos_strings.h"
     14 #include "ui/base/resource/resource_bundle.h"
     15 #include "ui/chromeos/network/network_icon.h"
     16 #include "ui/chromeos/network/network_icon_animation.h"
     17 #include "ui/chromeos/network/network_info.h"
     18 #include "ui/chromeos/network/network_list_delegate.h"
     19 #include "ui/gfx/font.h"
     20 #include "ui/views/controls/label.h"
     21 #include "ui/views/view.h"
     22 
     23 using chromeos::NetworkHandler;
     24 using chromeos::NetworkStateHandler;
     25 using chromeos::NetworkTypePattern;
     26 
     27 namespace ui {
     28 
     29 // NetworkListView:
     30 
     31 NetworkListView::NetworkListView(NetworkListDelegate* delegate)
     32     : delegate_(delegate),
     33       content_(NULL),
     34       scanning_view_(NULL),
     35       no_wifi_networks_view_(NULL),
     36       no_cellular_networks_view_(NULL) {
     37   CHECK(delegate);
     38 }
     39 
     40 NetworkListView::~NetworkListView() {
     41   network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
     42 }
     43 
     44 void NetworkListView::UpdateNetworkList() {
     45   CHECK(content_);
     46   NetworkStateHandler::NetworkStateList network_list;
     47   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
     48   handler->GetVisibleNetworkList(&network_list);
     49   UpdateNetworks(network_list);
     50   UpdateNetworkListInternal();
     51 }
     52 
     53 bool NetworkListView::IsViewInList(views::View* view,
     54                                    std::string* service_path) const {
     55   std::map<views::View*, std::string>::const_iterator found =
     56       network_map_.find(view);
     57   if (found == network_map_.end())
     58     return false;
     59   *service_path = found->second;
     60   return true;
     61 }
     62 
     63 void NetworkListView::UpdateNetworks(
     64     const NetworkStateHandler::NetworkStateList& networks) {
     65   network_list_.clear();
     66   const NetworkTypePattern pattern = delegate_->GetNetworkTypePattern();
     67   for (NetworkStateHandler::NetworkStateList::const_iterator iter =
     68            networks.begin();
     69        iter != networks.end();
     70        ++iter) {
     71     const chromeos::NetworkState* network = *iter;
     72     if (!pattern.MatchesType(network->type()))
     73       continue;
     74     NetworkInfo* info = new NetworkInfo(network->path());
     75     network_list_.push_back(info);
     76   }
     77 }
     78 
     79 void NetworkListView::UpdateNetworkListInternal() {
     80   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
     81 
     82   // First, update state for all networks
     83   bool animating = false;
     84   for (size_t i = 0; i < network_list_.size(); ++i) {
     85     NetworkInfo* info = network_list_[i];
     86     const chromeos::NetworkState* network =
     87         handler->GetNetworkState(info->service_path);
     88     if (!network)
     89       continue;
     90     info->image =
     91         network_icon::GetImageForNetwork(network, network_icon::ICON_TYPE_LIST);
     92     info->label =
     93         network_icon::GetLabelForNetwork(network, network_icon::ICON_TYPE_LIST);
     94     info->highlight =
     95         network->IsConnectedState() || network->IsConnectingState();
     96     info->disable =
     97         network->activation_state() == shill::kActivationStateActivating;
     98     if (!animating && network->IsConnectingState())
     99       animating = true;
    100   }
    101 
    102   if (animating)
    103     network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
    104   else
    105     network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
    106 
    107   // Get the updated list entries
    108   network_map_.clear();
    109   std::set<std::string> new_service_paths;
    110   bool needs_relayout = UpdateNetworkListEntries(&new_service_paths);
    111 
    112   // Remove old children
    113   std::set<std::string> remove_service_paths;
    114   for (ServicePathMap::const_iterator it = service_path_map_.begin();
    115        it != service_path_map_.end();
    116        ++it) {
    117     if (new_service_paths.find(it->first) == new_service_paths.end()) {
    118       remove_service_paths.insert(it->first);
    119       network_map_.erase(it->second);
    120       content_->RemoveChildView(it->second);
    121       needs_relayout = true;
    122     }
    123   }
    124 
    125   for (std::set<std::string>::const_iterator remove_it =
    126            remove_service_paths.begin();
    127        remove_it != remove_service_paths.end();
    128        ++remove_it) {
    129     service_path_map_.erase(*remove_it);
    130   }
    131 
    132   if (needs_relayout) {
    133     views::View* selected_view = NULL;
    134     for (ServicePathMap::const_iterator iter = service_path_map_.begin();
    135          iter != service_path_map_.end();
    136          ++iter) {
    137       if (delegate_->IsViewHovered(iter->second)) {
    138         selected_view = iter->second;
    139         break;
    140       }
    141     }
    142     content_->SizeToPreferredSize();
    143     delegate_->RelayoutScrollList();
    144     if (selected_view)
    145       content_->ScrollRectToVisible(selected_view->bounds());
    146   }
    147 }
    148 
    149 bool NetworkListView::UpdateNetworkListEntries(
    150     std::set<std::string>* new_service_paths) {
    151   bool needs_relayout = false;
    152   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
    153 
    154   // Insert child views
    155   int index = 0;
    156 
    157   // Highlighted networks
    158   for (size_t i = 0; i < network_list_.size(); ++i) {
    159     const NetworkInfo* info = network_list_[i];
    160     if (info->highlight) {
    161       if (UpdateNetworkChild(index++, info))
    162         needs_relayout = true;
    163       new_service_paths->insert(info->service_path);
    164     }
    165   }
    166 
    167   const NetworkTypePattern pattern = delegate_->GetNetworkTypePattern();
    168   if (pattern.MatchesPattern(NetworkTypePattern::Cellular())) {
    169     // Cellular initializing
    170     int message_id = network_icon::GetCellularUninitializedMsg();
    171     if (!message_id &&
    172         handler->IsTechnologyEnabled(NetworkTypePattern::Mobile()) &&
    173         !handler->FirstNetworkByType(NetworkTypePattern::Mobile())) {
    174       message_id = IDS_ASH_STATUS_TRAY_NO_CELLULAR_NETWORKS;
    175     }
    176     if (UpdateInfoLabel(message_id, index, &no_cellular_networks_view_))
    177       needs_relayout = true;
    178     if (message_id)
    179       ++index;
    180   }
    181 
    182   if (pattern.MatchesPattern(NetworkTypePattern::WiFi())) {
    183     // "Wifi Enabled / Disabled"
    184     int message_id = 0;
    185     if (network_list_.empty()) {
    186       message_id = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())
    187                        ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
    188                        : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
    189     }
    190     if (UpdateInfoLabel(message_id, index, &no_wifi_networks_view_))
    191       needs_relayout = true;
    192     if (message_id)
    193       ++index;
    194 
    195     // "Wifi Scanning"
    196     message_id = 0;
    197     if (handler->GetScanningByType(NetworkTypePattern::WiFi()))
    198       message_id = IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE;
    199     if (UpdateInfoLabel(message_id, index, &scanning_view_))
    200       needs_relayout = true;
    201     if (message_id)
    202       ++index;
    203   }
    204 
    205   // Un-highlighted networks
    206   for (size_t i = 0; i < network_list_.size(); ++i) {
    207     const NetworkInfo* info = network_list_[i];
    208     if (!info->highlight) {
    209       if (UpdateNetworkChild(index++, info))
    210         needs_relayout = true;
    211       new_service_paths->insert(info->service_path);
    212     }
    213   }
    214 
    215   // No networks or other messages (fallback)
    216   if (index == 0) {
    217     int message_id = 0;
    218     if (pattern.Equals(NetworkTypePattern::VPN()))
    219       message_id = IDS_ASH_STATUS_TRAY_NETWORK_NO_VPN;
    220     else
    221       message_id = IDS_ASH_STATUS_TRAY_NO_NETWORKS;
    222     if (UpdateInfoLabel(message_id, index, &scanning_view_))
    223       needs_relayout = true;
    224   }
    225 
    226   return needs_relayout;
    227 }
    228 
    229 bool NetworkListView::UpdateNetworkChild(int index, const NetworkInfo* info) {
    230   bool needs_relayout = false;
    231   views::View* container = NULL;
    232   ServicePathMap::const_iterator found =
    233       service_path_map_.find(info->service_path);
    234   if (found == service_path_map_.end()) {
    235     container = delegate_->CreateViewForNetwork(*info);
    236     content_->AddChildViewAt(container, index);
    237     needs_relayout = true;
    238   } else {
    239     container = found->second;
    240     container->RemoveAllChildViews(true);
    241     delegate_->UpdateViewForNetwork(container, *info);
    242     container->Layout();
    243     container->SchedulePaint();
    244     needs_relayout = PlaceViewAtIndex(container, index);
    245   }
    246   if (info->disable)
    247     container->SetEnabled(false);
    248   network_map_[container] = info->service_path;
    249   service_path_map_[info->service_path] = container;
    250   return needs_relayout;
    251 }
    252 
    253 bool NetworkListView::PlaceViewAtIndex(views::View* view, int index) {
    254   if (content_->child_at(index) == view)
    255     return false;
    256   content_->ReorderChildView(view, index);
    257   return true;
    258 }
    259 
    260 bool NetworkListView::UpdateInfoLabel(int message_id,
    261                                       int index,
    262                                       views::Label** label) {
    263   CHECK(label);
    264   bool needs_relayout = false;
    265   if (message_id) {
    266     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    267     base::string16 text = rb.GetLocalizedString(message_id);
    268     if (!*label) {
    269       *label = delegate_->CreateInfoLabel();
    270       (*label)->SetText(text);
    271       content_->AddChildViewAt(*label, index);
    272       needs_relayout = true;
    273     } else {
    274       (*label)->SetText(text);
    275       needs_relayout = PlaceViewAtIndex(*label, index);
    276     }
    277   } else if (*label) {
    278     content_->RemoveChildView(*label);
    279     delete *label;
    280     *label = NULL;
    281     needs_relayout = true;
    282   }
    283   return needs_relayout;
    284 }
    285 
    286 void NetworkListView::NetworkIconChanged() {
    287   UpdateNetworkList();
    288 }
    289 
    290 }  // namespace ui
    291