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