| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/network_menu_button.h" | 5 #include "chrome/browser/chromeos/network_menu_button.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
| 11 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 12 #include "base/time.h" | 10 #include "base/time.h" |
| 13 #include "chrome/browser/browser.h" | 11 #include "chrome/browser/browser.h" |
| 14 #include "chrome/browser/browser_window.h" | 12 #include "chrome/browser/browser_window.h" |
| 15 #include "grit/generated_resources.h" | 13 #include "grit/generated_resources.h" |
| 16 #include "grit/theme_resources.h" | 14 #include "grit/theme_resources.h" |
| 17 #include "views/widget/widget.h" | 15 #include "views/widget/widget.h" |
| 18 #include "views/window/window.h" | 16 #include "views/window/window.h" |
| 19 | 17 |
| 20 //////////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////////// |
| 21 // NetworkMenuButton | 19 // NetworkMenuButton |
| 22 | 20 |
| 23 // static | 21 // static |
| 24 const int NetworkMenuButton::kNumWifiImages = 8; | 22 const int NetworkMenuButton::kNumWifiImages = 8; |
| 25 SkBitmap* NetworkMenuButton::wifi_images_[kNumWifiImages]; | |
| 26 SkBitmap* NetworkMenuButton::wired_image_ = NULL; | |
| 27 SkBitmap* NetworkMenuButton::disconnected_image_ = NULL; | |
| 28 const int NetworkMenuButton::kAnimationDelayMillis = 100; | 23 const int NetworkMenuButton::kAnimationDelayMillis = 100; |
| 29 | 24 |
| 30 NetworkMenuButton::NetworkMenuButton(Browser* browser, bool cros_library_loaded) | 25 NetworkMenuButton::NetworkMenuButton(Browser* browser) |
| 31 : MenuButton(NULL, std::wstring(), this, false), | 26 : MenuButton(NULL, std::wstring(), this, false), |
| 32 cros_library_loaded_(cros_library_loaded), | |
| 33 refreshing_menu_(false), | 27 refreshing_menu_(false), |
| 34 ethernet_connected_(false), | |
| 35 network_menu_(this), | 28 network_menu_(this), |
| 36 browser_(browser), | 29 browser_(browser), |
| 37 icon_animation_index_(0), | 30 icon_animation_index_(0), |
| 38 icon_animation_increasing_(true) { | 31 icon_animation_increasing_(true) { |
| 39 static bool initialized = false; | 32 SetShowHighlighted(false); |
| 40 if (!initialized) { | 33 UpdateIcon(); |
| 41 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 34 CrosNetworkLibrary::Get()->AddObserver(this); |
| 42 int image_index = IDR_STATUSBAR_WIFI_1; | 35 } |
| 43 for (int i = 0; i < kNumWifiImages; i++) | 36 |
| 44 wifi_images_[i] = rb.GetBitmapNamed(image_index + i); | 37 NetworkMenuButton::~NetworkMenuButton() { |
| 45 wired_image_ = rb.GetBitmapNamed(IDR_STATUSBAR_WIRED); | 38 CrosNetworkLibrary::Get()->RemoveObserver(this); |
| 46 disconnected_image_ = rb.GetBitmapNamed(IDR_STATUSBAR_DISCONNECTED); | |
| 47 initialized = true; | |
| 48 } | |
| 49 RefreshNetworks(); | |
| 50 } | 39 } |
| 51 | 40 |
| 52 //////////////////////////////////////////////////////////////////////////////// | 41 //////////////////////////////////////////////////////////////////////////////// |
| 53 // NetworkMenuButton, views::Menu2Model implementation: | 42 // NetworkMenuButton, views::Menu2Model implementation: |
| 54 | 43 |
| 55 int NetworkMenuButton::GetItemCount() const { | 44 int NetworkMenuButton::GetItemCount() const { |
| 56 // The menu contains the available wifi networks. If there are none, then it | 45 // The menu contains the available wifi networks. If there are none, then it |
| 57 // only has one item with a message that no networks are available. | 46 // only has one item with a message that no networks are available. |
| 58 return wifi_networks_in_menu_.empty() ? 1 : | 47 return wifi_networks_.empty() ? 1 : static_cast<int>(wifi_networks_.size()); |
| 59 static_cast<int>(wifi_networks_in_menu_.size()); | |
| 60 } | 48 } |
| 61 | 49 |
| 62 views::Menu2Model::ItemType NetworkMenuButton::GetTypeAt(int index) const { | 50 views::Menu2Model::ItemType NetworkMenuButton::GetTypeAt(int index) const { |
| 63 return wifi_networks_in_menu_.empty() ? views::Menu2Model::TYPE_COMMAND : | 51 return wifi_networks_.empty() ? views::Menu2Model::TYPE_COMMAND : |
| 64 views::Menu2Model::TYPE_CHECK; | 52 views::Menu2Model::TYPE_CHECK; |
| 65 } | 53 } |
| 66 | 54 |
| 67 string16 NetworkMenuButton::GetLabelAt(int index) const { | 55 string16 NetworkMenuButton::GetLabelAt(int index) const { |
| 68 return wifi_networks_in_menu_.empty() ? | 56 return wifi_networks_.empty() ? |
| 69 l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE) : | 57 l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE) : |
| 70 ASCIIToUTF16(wifi_networks_in_menu_[index].ssid); | 58 ASCIIToUTF16(wifi_networks_[index].ssid); |
| 71 } | 59 } |
| 72 | 60 |
| 73 bool NetworkMenuButton::IsItemCheckedAt(int index) const { | 61 bool NetworkMenuButton::IsItemCheckedAt(int index) const { |
| 74 // Network that we are connected to (or currently connecting to) is checked. | 62 // WifiNetwork that we are connected to (or connecting to) is checked. |
| 75 return wifi_networks_in_menu_.empty() ? false : | 63 return wifi_networks_.empty() ? false : |
| 76 wifi_networks_in_menu_[index].ssid == current_ssid_ || | 64 wifi_networks_[index].ssid == CrosNetworkLibrary::Get()->wifi_ssid(); |
| 77 wifi_networks_in_menu_[index].ssid == connecting_ssid_; | |
| 78 } | 65 } |
| 79 | 66 |
| 80 bool NetworkMenuButton::IsEnabledAt(int index) const { | 67 bool NetworkMenuButton::IsEnabledAt(int index) const { |
| 81 return !wifi_networks_in_menu_.empty(); | 68 return !wifi_networks_.empty(); |
| 82 } | 69 } |
| 83 | 70 |
| 84 void NetworkMenuButton::ActivatedAt(int index) { | 71 void NetworkMenuButton::ActivatedAt(int index) { |
| 85 // When we are refreshing the menu, ignore menu item activation. | 72 // When we are refreshing the menu, ignore menu item activation. |
| 86 if (refreshing_menu_) | 73 if (refreshing_menu_) |
| 87 return; | 74 return; |
| 88 | 75 |
| 89 // We need to look up the ssid in ssids_in_menu_. | 76 CrosNetworkLibrary* cros = CrosNetworkLibrary::Get(); |
| 90 std::string ssid = wifi_networks_in_menu_[index].ssid; | |
| 91 | 77 |
| 92 // If clicked on a network that we are already connected to or we are | 78 // If clicked on a network that we are already connected to or we are |
| 93 // currently trying to connect to, then do nothing. | 79 // currently trying to connect to, then do nothing. |
| 94 if (ssid == current_ssid_ || ssid == connecting_ssid_) | 80 if (wifi_networks_[index].ssid == cros->wifi_ssid()) |
| 95 return; | 81 return; |
| 96 | 82 |
| 83 activated_wifi_network_ = wifi_networks_[index]; |
| 84 |
| 97 // If wifi network is not encrypted, then directly connect. | 85 // If wifi network is not encrypted, then directly connect. |
| 98 // Otherwise, we open password dialog window. | 86 // Otherwise, we open password dialog window. |
| 99 if (!wifi_networks_in_menu_[index].encrypted) { | 87 if (!wifi_networks_[index].encrypted) { |
| 100 ConnectToWifiNetwork(ssid, string16()); | 88 cros->ConnectToWifiNetwork(wifi_networks_[index], string16()); |
| 101 } else { | 89 } else { |
| 102 gfx::NativeWindow parent = browser_->window()->GetNativeHandle(); | 90 gfx::NativeWindow parent = browser_->window()->GetNativeHandle(); |
| 103 PasswordDialogView* dialog = new PasswordDialogView(this, ssid); | 91 PasswordDialogView* dialog = new PasswordDialogView(this, |
| 92 wifi_networks_[index].ssid); |
| 104 views::Window* window = views::Window::CreateChromeWindow( | 93 views::Window* window = views::Window::CreateChromeWindow( |
| 105 parent, gfx::Rect(), dialog); | 94 parent, gfx::Rect(), dialog); |
| 106 // Draw the password dialog right below this button and right aligned. | 95 // Draw the password dialog right below this button and right aligned. |
| 107 gfx::Size size = dialog->GetPreferredSize(); | 96 gfx::Size size = dialog->GetPreferredSize(); |
| 108 gfx::Rect rect = bounds(); | 97 gfx::Rect rect = bounds(); |
| 109 gfx::Point point = gfx::Point(rect.width() - size.width(), rect.height()); | 98 gfx::Point point = gfx::Point(rect.width() - size.width(), rect.height()); |
| 110 ConvertPointToScreen(this, &point); | 99 ConvertPointToScreen(this, &point); |
| 111 window->SetBounds(gfx::Rect(point, size), parent); | 100 window->SetBounds(gfx::Rect(point, size), parent); |
| 112 window->Show(); | 101 window->Show(); |
| 113 } | 102 } |
| 114 } | 103 } |
| 115 | 104 |
| 116 //////////////////////////////////////////////////////////////////////////////// | 105 //////////////////////////////////////////////////////////////////////////////// |
| 117 // NetworkMenuButton, PasswordDialogDelegate implementation: | 106 // NetworkMenuButton, PasswordDialogDelegate implementation: |
| 118 | 107 |
| 119 bool NetworkMenuButton::OnPasswordDialogAccept(const std::string& ssid, | 108 bool NetworkMenuButton::OnPasswordDialogAccept(const std::string& ssid, |
| 120 const string16& password) { | 109 const string16& password) { |
| 121 return ConnectToWifiNetwork(ssid, password); | 110 CrosNetworkLibrary::Get()->ConnectToWifiNetwork(activated_wifi_network_, |
| 111 password); |
| 112 return true; |
| 122 } | 113 } |
| 123 | 114 |
| 124 //////////////////////////////////////////////////////////////////////////////// | 115 //////////////////////////////////////////////////////////////////////////////// |
| 125 // NetworkMenuButton, views::ViewMenuDelegate implementation: | 116 // NetworkMenuButton, views::ViewMenuDelegate implementation: |
| 126 | 117 |
| 127 void NetworkMenuButton::RunMenu(views::View* source, const gfx::Point& pt, | 118 void NetworkMenuButton::RunMenu(views::View* source, const gfx::Point& pt, |
| 128 gfx::NativeView hwnd) { | 119 gfx::NativeView hwnd) { |
| 129 RefreshNetworks(); | 120 wifi_networks_ = CrosNetworkLibrary::Get()->GetWifiNetworks(); |
| 130 // Make a copy of the wifi networks that we are showing because it may change. | |
| 131 wifi_networks_in_menu_ = wifi_networks_; | |
| 132 refreshing_menu_ = true; | 121 refreshing_menu_ = true; |
| 133 network_menu_.Rebuild(); | 122 network_menu_.Rebuild(); |
| 134 network_menu_.UpdateStates(); | 123 network_menu_.UpdateStates(); |
| 135 refreshing_menu_ = false; | 124 refreshing_menu_ = false; |
| 136 network_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); | 125 network_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); |
| 137 } | 126 } |
| 138 | 127 |
| 139 bool NetworkMenuButton::GetWifiNetwork(const WifiNetworkVector& networks, | 128 //////////////////////////////////////////////////////////////////////////////// |
| 140 const std::string& ssid, | 129 // NetworkMenuButton, CrosNetworkLibrary::Observer implementation: |
| 141 WifiNetwork* network) { | |
| 142 WifiNetworkVector::const_iterator it; | |
| 143 for (it = networks.begin(); it != networks.end(); ++it) { | |
| 144 if (it->ssid == ssid) { | |
| 145 *network = *it; | |
| 146 return true; | |
| 147 } | |
| 148 } | |
| 149 return false; | |
| 150 } | |
| 151 | 130 |
| 152 void NetworkMenuButton::AddWifiNetwork(const std::string& ssid, | 131 void NetworkMenuButton::NetworkChanged(CrosNetworkLibrary* obj) { |
| 153 bool encrypted, | 132 if (CrosNetworkLibrary::Get()->wifi_connecting()) { |
| 154 chromeos::EncryptionType encryption, | 133 StartConnectingAnimation(); |
| 155 int strength) { | |
| 156 wifi_networks_.push_back( | |
| 157 WifiNetwork(ssid, encrypted, encryption, strength)); | |
| 158 } | |
| 159 | |
| 160 void NetworkMenuButton::RefreshNetworks() { | |
| 161 std::string current; | |
| 162 std::string connecting; | |
| 163 wifi_networks_.clear(); | |
| 164 ethernet_connected_ = false; | |
| 165 | |
| 166 if (cros_library_loaded_) { | |
| 167 chromeos::ServiceStatus* service_status = chromeos::GetAvailableNetworks(); | |
| 168 for (int i = 0; i < service_status->size; i++) { | |
| 169 chromeos::ServiceInfo service = service_status->services[i]; | |
| 170 std::string ssid = service.ssid; | |
| 171 DLOG(WARNING) << "Found network type=" << service.type << | |
| 172 " ssid=" << service.ssid << | |
| 173 " state=" << service.state << | |
| 174 " needs_passphrase=" << service.needs_passphrase << | |
| 175 " encryption=" << service.encryption << | |
| 176 " signal_strength=" << service.signal_strength; | |
| 177 if (service.type == chromeos::TYPE_WIFI) { | |
| 178 AddWifiNetwork(ssid, service.needs_passphrase, service.encryption, | |
| 179 service.signal_strength); | |
| 180 // Check connection state. | |
| 181 switch (service.state) { | |
| 182 case chromeos::STATE_ASSOCIATION: // connecting to access point | |
| 183 case chromeos::STATE_CONFIGURATION: // optaining ip address | |
| 184 connecting = ssid; | |
| 185 break; | |
| 186 case chromeos::STATE_READY: // connected and has ip | |
| 187 current = ssid; | |
| 188 break; | |
| 189 case chromeos::STATE_FAILURE: // failed to connect | |
| 190 // TODO(chocobo): Handle failure. Show it to user. | |
| 191 DLOG(WARNING) << "Wifi network failed to connect: " << ssid; | |
| 192 break; | |
| 193 case chromeos::STATE_IDLE: // no connection | |
| 194 case chromeos::STATE_DISCONNECT: // disconnected | |
| 195 case chromeos::STATE_CARRIER: // not used | |
| 196 case chromeos::STATE_UNKNOWN: // unknown | |
| 197 default: | |
| 198 break; | |
| 199 } | |
| 200 } else if (service.type == chromeos::TYPE_ETHERNET) { | |
| 201 if (service.state == chromeos::STATE_READY) | |
| 202 ethernet_connected_ = true; | |
| 203 } | |
| 204 } | |
| 205 chromeos::FreeServiceStatus(service_status); | |
| 206 } else { | 134 } else { |
| 207 // Use test data if ChromeOS shared library is not loaded. | |
| 208 AddWifiNetwork("Wifi (12)", false, chromeos::NONE, 12); | |
| 209 AddWifiNetwork("Wifi RSN (70)", true, chromeos::RSN, 70); | |
| 210 AddWifiNetwork("Wifi (28)", false, chromeos::NONE, 28); | |
| 211 AddWifiNetwork("Wifi WEP (99)", true, chromeos::WEP, 99); | |
| 212 current = connecting_ssid_.empty() ? current_ssid_ : connecting_ssid_; | |
| 213 ethernet_connected_ = true; | |
| 214 } | |
| 215 | |
| 216 // Sort the list of wifi networks by ssid. | |
| 217 std::sort(wifi_networks_.begin(), wifi_networks_.end()); | |
| 218 | |
| 219 connecting_ssid_ = connecting; | |
| 220 current_ssid_ = current; | |
| 221 | |
| 222 if (connecting_ssid_.empty()) { | |
| 223 StopConnectingAnimation(); | 135 StopConnectingAnimation(); |
| 224 UpdateIcon(); | 136 UpdateIcon(); |
| 225 } else { | |
| 226 StartConnectingAnimation(); | |
| 227 } | 137 } |
| 228 } | 138 } |
| 229 | 139 |
| 230 static const char* GetEncryptionString(chromeos::EncryptionType encryption) { | |
| 231 switch (encryption) { | |
| 232 case chromeos::NONE: | |
| 233 return "none"; | |
| 234 case chromeos::RSN: | |
| 235 return "rsn"; | |
| 236 case chromeos::WEP: | |
| 237 return "wep"; | |
| 238 case chromeos::WPA: | |
| 239 return "wpa"; | |
| 240 } | |
| 241 return "none"; | |
| 242 } | |
| 243 | |
| 244 bool NetworkMenuButton::ConnectToWifiNetwork(const std::string& ssid, | |
| 245 const string16& password) { | |
| 246 bool ok = true; | |
| 247 if (cros_library_loaded_) { | |
| 248 chromeos::EncryptionType encryption = chromeos::NONE; | |
| 249 WifiNetwork network; | |
| 250 if (GetWifiNetwork(wifi_networks_in_menu_, ssid, &network)) | |
| 251 encryption = network.encryption; | |
| 252 ok = chromeos::ConnectToWifiNetwork(ssid.c_str(), | |
| 253 password.empty() ? NULL : UTF16ToUTF8(password).c_str(), | |
| 254 GetEncryptionString(encryption)); | |
| 255 } | |
| 256 if (ok) { | |
| 257 connecting_ssid_ = ssid; | |
| 258 StartConnectingAnimation(); | |
| 259 } | |
| 260 return true; | |
| 261 } | |
| 262 | |
| 263 void NetworkMenuButton::StartConnectingAnimation() { | 140 void NetworkMenuButton::StartConnectingAnimation() { |
| 264 if (!timer_.IsRunning()) { | 141 if (!timer_.IsRunning()) { |
| 265 icon_animation_index_ = 0; | 142 icon_animation_index_ = 0; |
| 266 icon_animation_increasing_ = true; | 143 icon_animation_increasing_ = true; |
| 267 timer_.Start(base::TimeDelta::FromMilliseconds(kAnimationDelayMillis), this, | 144 timer_.Start(base::TimeDelta::FromMilliseconds(kAnimationDelayMillis), this, |
| 268 &NetworkMenuButton::UpdateIcon); | 145 &NetworkMenuButton::UpdateIcon); |
| 269 } | 146 } |
| 270 } | 147 } |
| 271 | 148 |
| 272 void NetworkMenuButton::StopConnectingAnimation() { | 149 void NetworkMenuButton::StopConnectingAnimation() { |
| 273 if (timer_.IsRunning()) { | 150 if (timer_.IsRunning()) { |
| 274 timer_.Stop(); | 151 timer_.Stop(); |
| 275 } | 152 } |
| 276 } | 153 } |
| 277 | 154 |
| 278 void NetworkMenuButton::UpdateIcon() { | 155 void NetworkMenuButton::UpdateIcon() { |
| 279 if (!connecting_ssid_.empty()) { | 156 CrosNetworkLibrary* cros = CrosNetworkLibrary::Get(); |
| 157 int id = IDR_STATUSBAR_DISCONNECTED; |
| 158 if (cros->wifi_connecting()) { |
| 280 // Get the next frame. Reverse direction if necessary. | 159 // Get the next frame. Reverse direction if necessary. |
| 281 if (icon_animation_increasing_) { | 160 if (icon_animation_increasing_) { |
| 282 icon_animation_index_++; | 161 icon_animation_index_++; |
| 283 if (icon_animation_index_ >= kNumWifiImages) { | 162 if (icon_animation_index_ >= kNumWifiImages) { |
| 284 icon_animation_index_ = kNumWifiImages - 1; | 163 icon_animation_index_ = kNumWifiImages - 1; |
| 285 icon_animation_increasing_ = false; | 164 icon_animation_increasing_ = false; |
| 286 } | 165 } |
| 287 } else { | 166 } else { |
| 288 icon_animation_index_--; | 167 icon_animation_index_--; |
| 289 if (icon_animation_index_ < 0) { | 168 if (icon_animation_index_ < 0) { |
| 290 icon_animation_index_ = 0; | 169 icon_animation_index_ = 0; |
| 291 icon_animation_increasing_ = true; | 170 icon_animation_increasing_ = true; |
| 292 } | 171 } |
| 293 } | 172 } |
| 294 SetIcon(*wifi_images_[icon_animation_index_]); | 173 id = IDR_STATUSBAR_WIFI_1 + icon_animation_index_; |
| 295 | |
| 296 // Refresh wifi networks every full animation. | |
| 297 // And see if we need to stop the animation. | |
| 298 if (icon_animation_index_ == 0) | |
| 299 RefreshNetworks(); | |
| 300 } else { | 174 } else { |
| 301 if (current_ssid_.empty()) { | 175 if (cros->wifi_ssid().empty()) { |
| 302 if (ethernet_connected_) | 176 if (cros->ethernet_connected()) |
| 303 SetIcon(*wired_image_); | 177 id = IDR_STATUSBAR_WIRED; |
| 304 else | 178 else |
| 305 SetIcon(*disconnected_image_); | 179 id = IDR_STATUSBAR_DISCONNECTED; |
| 306 } else { | 180 } else { |
| 307 WifiNetwork network; | 181 // Gets the wifi image of 1-8 bars depending on signal strength. Signal |
| 308 if (GetWifiNetwork(wifi_networks_, current_ssid_, &network)) { | 182 // strength is from 0 to 100, so we need to convert that to 0 to 7. |
| 309 // Gets the wifi image of 1-8 bars depending on signal strength. Signal | 183 int index = floor(cros->wifi_strength() / (100.0 / kNumWifiImages)); |
| 310 // strength is from 0 to 100, so we need to convert that to 0 to 7. | 184 // This can happen if the signal strength is 100. |
| 311 int index = floor(network.strength / (100.0 / kNumWifiImages)); | 185 if (index == kNumWifiImages) |
| 312 // This can happen if the signal strength is 100. | 186 index--; |
| 313 if (index == kNumWifiImages) | 187 id = IDR_STATUSBAR_WIFI_1 + index; |
| 314 index--; | |
| 315 SetIcon(*wifi_images_[index]); | |
| 316 } else { | |
| 317 // We no longer find the current network in the list of networks. | |
| 318 // So just set the icon to the disconnected image. | |
| 319 SetIcon(*disconnected_image_); | |
| 320 } | |
| 321 } | 188 } |
| 322 } | 189 } |
| 190 SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(id)); |
| 323 SchedulePaint(); | 191 SchedulePaint(); |
| 324 } | 192 } |
| OLD | NEW |