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