1// Copyright (c) 2011 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/network_login_observer.h"
6
7#include "chrome/browser/chromeos/cros/cros_library.h"
8#include "chrome/browser/chromeos/cros/network_library.h"
9#include "chrome/browser/chromeos/login/background_view.h"
10#include "chrome/browser/chromeos/login/login_utils.h"
11#include "chrome/browser/chromeos/options/network_config_view.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_list.h"
14#include "chrome/browser/ui/browser_window.h"
15#include "chrome/browser/ui/views/window.h"
16#include "views/window/dialog_delegate.h"
17#include "views/window/window.h"
18
19namespace chromeos {
20
21NetworkLoginObserver::NetworkLoginObserver(NetworkLibrary* netlib) {
22  RefreshStoredNetworks(netlib->wifi_networks(),
23                        netlib->virtual_networks());
24  netlib->AddNetworkManagerObserver(this);
25}
26
27NetworkLoginObserver::~NetworkLoginObserver() {
28  CrosLibrary::Get()->GetNetworkLibrary()->RemoveNetworkManagerObserver(this);
29}
30
31void NetworkLoginObserver::CreateModalPopup(views::WindowDelegate* view) {
32  Browser* browser = BrowserList::GetLastActive();
33  if (browser && browser->type() != Browser::TYPE_NORMAL) {
34    browser = BrowserList::FindBrowserWithType(browser->profile(),
35                                               Browser::TYPE_NORMAL,
36                                               true);
37  }
38  if (browser) {
39    views::Window* window = browser::CreateViewsWindow(
40        browser->window()->GetNativeHandle(), gfx::Rect(), view);
41    window->SetIsAlwaysOnTop(true);
42    window->Show();
43  } else {
44    // Browser not found, so we should be in login/oobe screen.
45    BackgroundView* background_view = LoginUtils::Get()->GetBackgroundView();
46    if (background_view) {
47      background_view->CreateModalPopup(view);
48    }
49  }
50}
51
52void NetworkLoginObserver::RefreshStoredNetworks(
53    const WifiNetworkVector& wifi_networks,
54    const VirtualNetworkVector& virtual_networks) {
55  network_failures_.clear();
56  for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
57       it != wifi_networks.end(); it++) {
58    const WifiNetwork* wifi = *it;
59    network_failures_[wifi->service_path()] = wifi->failed();
60  }
61  for (VirtualNetworkVector::const_iterator it = virtual_networks.begin();
62       it != virtual_networks.end(); it++) {
63    const VirtualNetwork* vpn = *it;
64    network_failures_[vpn->service_path()] = vpn->failed();
65  }
66}
67
68void NetworkLoginObserver::OnNetworkManagerChanged(NetworkLibrary* cros) {
69  const WifiNetworkVector& wifi_networks = cros->wifi_networks();
70  const VirtualNetworkVector& virtual_networks = cros->virtual_networks();
71
72  NetworkConfigView* view = NULL;
73  // Check to see if we have any newly failed wifi network.
74  for (WifiNetworkVector::const_iterator it = wifi_networks.begin();
75       it != wifi_networks.end(); it++) {
76    WifiNetwork* wifi = *it;
77    if (wifi->failed()) {
78      NetworkFailureMap::iterator iter =
79          network_failures_.find(wifi->service_path());
80      // If the network did not previously exist, then don't do anything.
81      // For example, if the user travels to a location and finds a service
82      // that has previously failed, we don't want to show an error.
83      if (iter == network_failures_.end())
84        continue;
85
86      // If this network was in a failed state previously, then it's not new.
87      if (iter->second)
88        continue;
89
90      // Display login dialog again for bad_passphrase and bad_wepkey errors.
91      // Always re-display the login dialog for added networks that failed to
92      // connect for any reason (e.g. incorrect security type was chosen).
93      if (wifi->error() == ERROR_BAD_PASSPHRASE ||
94          wifi->error() == ERROR_BAD_WEPKEY ||
95          wifi->added()) {
96        // The NetworkConfigView will show the appropriate error message.
97        view = new NetworkConfigView(wifi);
98        // There should only be one wifi network that failed to connect.
99        // If for some reason, we have more than one failure,
100        // we only display the first one. So we break here.
101        break;
102      }
103    }
104  }
105  // Check to see if we have any newly failed virtual network.
106  // See wifi section for detailed comments.
107  if (!view) {
108    for (VirtualNetworkVector::const_iterator it = virtual_networks.begin();
109         it != virtual_networks.end(); it++) {
110      VirtualNetwork* vpn = *it;
111      if (vpn->failed()) {
112        NetworkFailureMap::iterator iter =
113            network_failures_.find(vpn->service_path());
114        if (iter == network_failures_.end())
115          continue;  // New network.
116        if (iter->second)
117          continue;  // Previous failure.
118        if (vpn->error() == ERROR_BAD_PASSPHRASE || vpn->added()) {
119          view = new NetworkConfigView(vpn);
120          break;
121        }
122      }
123    }
124  }
125
126  RefreshStoredNetworks(wifi_networks, virtual_networks);
127
128  // Show login box if necessary.
129  if (view)
130    CreateModalPopup(view);
131}
132
133}  // namespace chromeos
134