network_config_view.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1// Copyright (c) 2012 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 "chrome/browser/chromeos/options/network_config_view.h" 6 7#include <algorithm> 8 9#include "ash/shell.h" 10#include "base/strings/string_util.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" 13#include "chrome/browser/chromeos/options/network_property_ui_data.h" 14#include "chrome/browser/chromeos/options/vpn_config_view.h" 15#include "chrome/browser/chromeos/options/wifi_config_view.h" 16#include "chrome/browser/chromeos/options/wimax_config_view.h" 17#include "chrome/browser/profiles/profile_manager.h" 18#include "chrome/browser/ui/browser.h" 19#include "chrome/browser/ui/browser_finder.h" 20#include "chrome/browser/ui/browser_window.h" 21#include "chrome/browser/ui/host_desktop.h" 22#include "chrome/grit/chromium_strings.h" 23#include "chrome/grit/generated_resources.h" 24#include "chrome/grit/locale_settings.h" 25#include "chrome/grit/theme_resources.h" 26#include "chromeos/login/login_state.h" 27#include "chromeos/network/network_state.h" 28#include "chromeos/network/network_state_handler.h" 29#include "components/user_manager/user.h" 30#include "ui/accessibility/ax_view_state.h" 31#include "ui/aura/window_event_dispatcher.h" 32#include "ui/base/l10n/l10n_util.h" 33#include "ui/base/resource/resource_bundle.h" 34#include "ui/gfx/image/image.h" 35#include "ui/gfx/rect.h" 36#include "ui/views/controls/button/label_button.h" 37#include "ui/views/controls/image_view.h" 38#include "ui/views/layout/layout_constants.h" 39#include "ui/views/widget/widget.h" 40 41using views::Widget; 42 43namespace { 44 45gfx::NativeWindow GetParentForUnhostedDialog() { 46 if (chromeos::LoginDisplayHostImpl::default_host()) { 47 return chromeos::LoginDisplayHostImpl::default_host()->GetNativeWindow(); 48 } else { 49 Browser* browser = chrome::FindTabbedBrowser( 50 ProfileManager::GetPrimaryUserProfile(), 51 true, 52 chrome::HOST_DESKTOP_TYPE_ASH); 53 if (browser) 54 return browser->window()->GetNativeWindow(); 55 } 56 return NULL; 57} 58 59// Avoid global static initializer. 60chromeos::NetworkConfigView** GetActiveDialogPointer() { 61 static chromeos::NetworkConfigView* active_dialog = NULL; 62 return &active_dialog; 63} 64 65chromeos::NetworkConfigView* GetActiveDialog() { 66 return *(GetActiveDialogPointer()); 67} 68 69void SetActiveDialog(chromeos::NetworkConfigView* dialog) { 70 *(GetActiveDialogPointer()) = dialog; 71} 72 73} // namespace 74 75namespace chromeos { 76 77// static 78const int ChildNetworkConfigView::kInputFieldMinWidth = 270; 79 80NetworkConfigView::NetworkConfigView() 81 : child_config_view_(NULL), 82 delegate_(NULL), 83 advanced_button_(NULL) { 84 DCHECK(GetActiveDialog() == NULL); 85 SetActiveDialog(this); 86} 87 88bool NetworkConfigView::InitWithNetworkState(const NetworkState* network) { 89 DCHECK(network); 90 std::string service_path = network->path(); 91 if (network->type() == shill::kTypeWifi || 92 network->type() == shill::kTypeEthernet) { 93 child_config_view_ = new WifiConfigView(this, service_path, false); 94 } else if (network->type() == shill::kTypeWimax) { 95 child_config_view_ = new WimaxConfigView(this, service_path); 96 } else if (network->type() == shill::kTypeVPN) { 97 child_config_view_ = new VPNConfigView(this, service_path); 98 } 99 return child_config_view_ != NULL; 100} 101 102bool NetworkConfigView::InitWithType(const std::string& type) { 103 if (type == shill::kTypeWifi) { 104 child_config_view_ = new WifiConfigView(this, 105 "" /* service_path */, 106 false /* show_8021x */); 107 advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16( 108 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON)); 109 advanced_button_->SetStyle(views::Button::STYLE_BUTTON); 110 } else if (type == shill::kTypeVPN) { 111 child_config_view_ = new VPNConfigView(this, 112 "" /* service_path */); 113 } 114 return child_config_view_ != NULL; 115} 116 117NetworkConfigView::~NetworkConfigView() { 118 DCHECK(GetActiveDialog() == this); 119 SetActiveDialog(NULL); 120} 121 122// static 123void NetworkConfigView::Show(const std::string& service_path, 124 gfx::NativeWindow parent) { 125 if (GetActiveDialog() != NULL) 126 return; 127 NetworkConfigView* view = new NetworkConfigView(); 128 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 129 GetNetworkState(service_path); 130 if (!network) { 131 LOG(ERROR) << "NetworkConfigView::Show called with invalid service_path"; 132 return; 133 } 134 if (!view->InitWithNetworkState(network)) { 135 LOG(ERROR) << "NetworkConfigView::Show called with invalid network type: " 136 << network->type(); 137 delete view; 138 return; 139 } 140 view->ShowDialog(parent); 141} 142 143// static 144void NetworkConfigView::ShowForType(const std::string& type, 145 gfx::NativeWindow parent) { 146 if (GetActiveDialog() != NULL) 147 return; 148 NetworkConfigView* view = new NetworkConfigView(); 149 if (!view->InitWithType(type)) { 150 LOG(ERROR) << "NetworkConfigView::ShowForType called with invalid type: " 151 << type; 152 delete view; 153 return; 154 } 155 view->ShowDialog(parent); 156} 157 158gfx::NativeWindow NetworkConfigView::GetNativeWindow() const { 159 return GetWidget()->GetNativeWindow(); 160} 161 162base::string16 NetworkConfigView::GetDialogButtonLabel( 163 ui::DialogButton button) const { 164 if (button == ui::DIALOG_BUTTON_OK) { 165 if (child_config_view_->IsConfigureDialog()) 166 return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONFIGURE); 167 return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT); 168 } 169 return views::DialogDelegateView::GetDialogButtonLabel(button); 170} 171 172bool NetworkConfigView::IsDialogButtonEnabled(ui::DialogButton button) const { 173 // Disable connect button if cannot login. 174 if (button == ui::DIALOG_BUTTON_OK) 175 return child_config_view_->CanLogin(); 176 return true; 177} 178 179bool NetworkConfigView::Cancel() { 180 if (delegate_) 181 delegate_->OnDialogCancelled(); 182 child_config_view_->Cancel(); 183 return true; 184} 185 186bool NetworkConfigView::Accept() { 187 // Do not attempt login if it is guaranteed to fail, keep the dialog open. 188 if (!child_config_view_->CanLogin()) 189 return false; 190 bool result = child_config_view_->Login(); 191 if (result && delegate_) 192 delegate_->OnDialogAccepted(); 193 return result; 194} 195 196views::View* NetworkConfigView::CreateExtraView() { 197 return advanced_button_; 198} 199 200views::View* NetworkConfigView::GetInitiallyFocusedView() { 201 return child_config_view_->GetInitiallyFocusedView(); 202} 203 204base::string16 NetworkConfigView::GetWindowTitle() const { 205 DCHECK(!child_config_view_->GetTitle().empty()); 206 return child_config_view_->GetTitle(); 207} 208 209ui::ModalType NetworkConfigView::GetModalType() const { 210 return ui::MODAL_TYPE_SYSTEM; 211} 212 213void NetworkConfigView::GetAccessibleState(ui::AXViewState* state) { 214 state->name = 215 l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS); 216 state->role = ui::AX_ROLE_DIALOG; 217} 218 219void NetworkConfigView::ButtonPressed(views::Button* sender, 220 const ui::Event& event) { 221 if (advanced_button_ && sender == advanced_button_) { 222 advanced_button_->SetVisible(false); 223 ShowAdvancedView(); 224 } 225} 226 227void NetworkConfigView::ShowAdvancedView() { 228 // Clear out the old widgets and build new ones. 229 RemoveChildView(child_config_view_); 230 delete child_config_view_; 231 // For now, there is only an advanced view for Wi-Fi 802.1X. 232 child_config_view_ = new WifiConfigView(this, 233 "" /* service_path */, 234 true /* show_8021x */); 235 AddChildView(child_config_view_); 236 // Resize the window to be able to hold the new widgets. 237 gfx::Size size = views::Widget::GetLocalizedContentsSize( 238 IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_WIDTH_CHARS, 239 IDS_JOIN_WIFI_NETWORK_DIALOG_ADVANCED_MINIMUM_HEIGHT_LINES); 240 // Get the new bounds with desired size at the same center point. 241 gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen(); 242 int horiz_padding = bounds.width() - size.width(); 243 int vert_padding = bounds.height() - size.height(); 244 bounds.Inset(horiz_padding / 2, vert_padding / 2, 245 horiz_padding / 2, vert_padding / 2); 246 GetWidget()->SetBoundsConstrained(bounds); 247 Layout(); 248 child_config_view_->InitFocus(); 249} 250 251void NetworkConfigView::Layout() { 252 child_config_view_->SetBounds(0, 0, width(), height()); 253} 254 255gfx::Size NetworkConfigView::GetPreferredSize() const { 256 gfx::Size result(views::Widget::GetLocalizedContentsSize( 257 IDS_JOIN_WIFI_NETWORK_DIALOG_WIDTH_CHARS, 258 IDS_JOIN_WIFI_NETWORK_DIALOG_MINIMUM_HEIGHT_LINES)); 259 gfx::Size size = child_config_view_->GetPreferredSize(); 260 result.set_height(size.height()); 261 if (size.width() > result.width()) 262 result.set_width(size.width()); 263 return result; 264} 265 266void NetworkConfigView::ViewHierarchyChanged( 267 const ViewHierarchyChangedDetails& details) { 268 // Can't init before we're inserted into a Container, because we require 269 // a HWND to parent native child controls to. 270 if (details.is_add && details.child == this) { 271 AddChildView(child_config_view_); 272 } 273} 274 275void NetworkConfigView::ShowDialog(gfx::NativeWindow parent) { 276 if (parent == NULL) 277 parent = GetParentForUnhostedDialog(); 278 // Failed connections may result in a pop-up with no natural parent window, 279 // so provide a fallback context on the primary display. This is necessary 280 // becase one of parent or context must be non NULL. 281 gfx::NativeWindow context = 282 parent ? NULL : ash::Shell::GetPrimaryRootWindow(); 283 Widget* window = DialogDelegate::CreateDialogWidget(this, context, parent); 284 window->SetAlwaysOnTop(true); 285 window->Show(); 286} 287 288// ChildNetworkConfigView 289 290ChildNetworkConfigView::ChildNetworkConfigView( 291 NetworkConfigView* parent, 292 const std::string& service_path) 293 : parent_(parent), 294 service_path_(service_path) { 295} 296 297ChildNetworkConfigView::~ChildNetworkConfigView() { 298} 299 300bool ChildNetworkConfigView::IsConfigureDialog() { 301 return false; 302} 303 304// static 305void ChildNetworkConfigView::GetShareStateForLoginState(bool* default_value, 306 bool* modifiable) { 307 *default_value = !LoginState::Get()->UserHasNetworkProfile(); 308 // Allow only authenticated user to change the share state. 309 *modifiable = LoginState::Get()->IsUserAuthenticated(); 310} 311 312// ControlledSettingIndicatorView 313 314ControlledSettingIndicatorView::ControlledSettingIndicatorView() 315 : managed_(false), 316 image_view_(NULL) { 317 Init(); 318} 319 320ControlledSettingIndicatorView::ControlledSettingIndicatorView( 321 const NetworkPropertyUIData& ui_data) 322 : managed_(false), 323 image_view_(NULL) { 324 Init(); 325 Update(ui_data); 326} 327 328ControlledSettingIndicatorView::~ControlledSettingIndicatorView() {} 329 330void ControlledSettingIndicatorView::Update( 331 const NetworkPropertyUIData& ui_data) { 332 if (managed_ == ui_data.IsManaged()) 333 return; 334 335 managed_ = ui_data.IsManaged(); 336 PreferredSizeChanged(); 337} 338 339gfx::Size ControlledSettingIndicatorView::GetPreferredSize() const { 340 return (managed_ && visible()) ? image_view_->GetPreferredSize() 341 : gfx::Size(); 342} 343 344void ControlledSettingIndicatorView::Layout() { 345 image_view_->SetBounds(0, 0, width(), height()); 346} 347 348void ControlledSettingIndicatorView::Init() { 349 image_ = ResourceBundle::GetSharedInstance().GetImageNamed( 350 IDR_CONTROLLED_SETTING_MANDATORY).ToImageSkia(); 351 image_view_ = new views::ImageView(); 352 // Disable |image_view_| so mouse events propagate to the parent. 353 image_view_->SetEnabled(false); 354 image_view_->SetImage(image_); 355 image_view_->SetTooltipText( 356 l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY)); 357 AddChildView(image_view_); 358} 359 360} // namespace chromeos 361