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.
5 #include "chrome/browser/chromeos/login/screens/network_screen.h"
7 #include "base/location.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/base/locale_util.h"
14 #include "chrome/browser/chromeos/customization/customization_document.h"
15 #include "chrome/browser/chromeos/login/help_app_launcher.h"
16 #include "chrome/browser/chromeos/login/helper.h"
17 #include "chrome/browser/chromeos/login/screen_manager.h"
18 #include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
19 #include "chrome/browser/chromeos/login/screens/network_view.h"
20 #include "chrome/browser/chromeos/login/ui/input_events_blocker.h"
21 #include "chrome/browser/chromeos/login/wizard_controller.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/grit/chromium_strings.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "chromeos/network/network_handler.h"
28 #include "chromeos/network/network_state_handler.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "ui/base/l10n/l10n_util.h"
34 // Time in seconds for connection timeout.
35 const int kConnectionTimeoutSec
= 40;
41 ///////////////////////////////////////////////////////////////////////////////
42 // NetworkScreen, public:
45 NetworkScreen
* NetworkScreen::Get(ScreenManager
* manager
) {
46 return static_cast<NetworkScreen
*>(
47 manager
->GetScreen(WizardController::kNetworkScreenName
));
50 NetworkScreen::NetworkScreen(BaseScreenDelegate
* base_screen_delegate
,
53 : NetworkModel(base_screen_delegate
),
54 is_network_subscribed_(false),
55 continue_pressed_(false),
58 network_state_helper_(new login::NetworkStateHelper
),
63 input_method::InputMethodManager::Get()->AddObserver(this);
64 InitializeTimezoneObserver();
67 void NetworkScreen::InitializeTimezoneObserver() {
68 timezone_subscription_
= CrosSettings::Get()->AddSettingsObserver(
69 kSystemTimezone
, base::Bind(&NetworkScreen::OnSystemTimezoneChanged
,
70 base::Unretained(this)));
73 NetworkScreen::~NetworkScreen() {
76 connection_timer_
.Stop();
77 UnsubscribeNetworkNotification();
79 input_method::InputMethodManager::Get()->RemoveObserver(this);
82 ////////////////////////////////////////////////////////////////////////////////
83 // NetworkScreen, NetworkModel implementation:
85 void NetworkScreen::PrepareToShow() {
87 view_
->PrepareToShow();
90 void NetworkScreen::Show() {
93 // Here we should handle default locales, for which we do not have UI
94 // resources. This would load fallback, but properly show "selected" locale
96 if (selected_language_code_
.empty()) {
97 const StartupCustomizationDocument
* startup_manifest
=
98 StartupCustomizationDocument::GetInstance();
99 SetApplicationLocale(startup_manifest
->initial_locale_default());
102 if (!timezone_subscription_
)
103 InitializeTimezoneObserver();
109 void NetworkScreen::Hide() {
110 timezone_subscription_
.reset();
115 void NetworkScreen::Initialize(::login::ScreenContext
* context
) {
116 NetworkModel::Initialize(context
);
117 OnSystemTimezoneChanged();
118 UpdateLanguageList();
121 void NetworkScreen::OnViewDestroyed(NetworkView
* view
) {
124 timezone_subscription_
.reset();
128 void NetworkScreen::OnUserAction(const std::string
& action_id
) {
129 if (action_id
== kUserActionContinueButtonClicked
) {
130 OnContinueButtonPressed();
131 } else if (action_id
== kUserActionConnectDebuggingFeaturesClicked
) {
133 delegate_
->OnEnableDebuggingScreenRequested();
135 BaseScreen::OnUserAction(action_id
);
139 void NetworkScreen::OnContextKeyUpdated(
140 const ::login::ScreenContext::KeyType
& key
) {
141 if (key
== kContextKeyLocale
)
142 SetApplicationLocale(context_
.GetString(kContextKeyLocale
));
143 else if (key
== kContextKeyInputMethod
)
144 SetInputMethod(context_
.GetString(kContextKeyInputMethod
));
145 else if (key
== kContextKeyTimezone
)
146 SetTimezone(context_
.GetString(kContextKeyTimezone
));
148 NetworkModel::OnContextKeyUpdated(key
);
151 std::string
NetworkScreen::GetLanguageListLocale() const {
152 return language_list_locale_
;
155 const base::ListValue
* NetworkScreen::GetLanguageList() const {
156 return language_list_
.get();
159 void NetworkScreen::UpdateLanguageList() {
160 ScheduleResolveLanguageList(scoped_ptr
<locale_util::LanguageSwitchResult
>());
163 ////////////////////////////////////////////////////////////////////////////////
164 // NetworkScreen, NetworkStateHandlerObserver implementation:
166 void NetworkScreen::NetworkConnectionStateChanged(const NetworkState
* network
) {
170 void NetworkScreen::DefaultNetworkChanged(const NetworkState
* network
) {
174 ////////////////////////////////////////////////////////////////////////////////
175 // NetworkScreen, InputMethodManager::Observer implementation:
177 void NetworkScreen::InputMethodChanged(
178 input_method::InputMethodManager
* manager
,
179 Profile
* /* proflie */,
180 bool /* show_message */) {
181 GetContextEditor().SetString(
182 kContextKeyInputMethod
,
183 manager
->GetActiveIMEState()->GetCurrentInputMethod().id());
186 ////////////////////////////////////////////////////////////////////////////////
187 // NetworkScreen, setters and getters for input method and timezone.
189 void NetworkScreen::SetApplicationLocale(const std::string
& locale
) {
190 const std::string app_locale
= g_browser_process
->GetApplicationLocale();
191 if (app_locale
== locale
)
194 // Block UI while resource bundle is being reloaded.
195 // (InputEventsBlocker will live until callback is finished.)
196 locale_util::SwitchLanguageCallback
callback(base::Bind(
197 &NetworkScreen::OnLanguageChangedCallback
, weak_factory_
.GetWeakPtr(),
198 base::Owned(new chromeos::InputEventsBlocker
)));
199 locale_util::SwitchLanguage(locale
, true /* enableLocaleKeyboardLayouts */,
200 true /* login_layouts_only */, callback
,
201 ProfileManager::GetActiveUserProfile());
204 std::string
NetworkScreen::GetApplicationLocale() {
205 return g_browser_process
->GetApplicationLocale();
208 void NetworkScreen::SetInputMethod(const std::string
& input_method
) {
209 input_method_
= input_method
;
210 input_method::InputMethodManager::Get()
211 ->GetActiveIMEState()
212 ->ChangeInputMethod(input_method_
, false /* show_message */);
215 std::string
NetworkScreen::GetInputMethod() const {
216 return input_method_
;
219 void NetworkScreen::SetTimezone(const std::string
& timezone_id
) {
220 std::string current_timezone_id
;
221 CrosSettings::Get()->GetString(kSystemTimezone
, ¤t_timezone_id
);
222 if (current_timezone_id
== timezone_id
)
224 timezone_
= timezone_id
;
225 CrosSettings::Get()->SetString(kSystemTimezone
, timezone_id
);
228 std::string
NetworkScreen::GetTimezone() const {
232 void NetworkScreen::CreateNetworkFromOnc(const std::string
& onc_spec
) {
233 network_state_helper_
->CreateNetworkFromOnc(onc_spec
);
236 void NetworkScreen::AddObserver(Observer
* observer
) {
238 observers_
.AddObserver(observer
);
241 void NetworkScreen::RemoveObserver(Observer
* observer
) {
243 observers_
.RemoveObserver(observer
);
246 ////////////////////////////////////////////////////////////////////////////////
247 // NetworkScreen, private:
249 void NetworkScreen::Refresh() {
250 SubscribeNetworkNotification();
254 void NetworkScreen::SetNetworkStateHelperForTest(
255 login::NetworkStateHelper
* helper
) {
256 network_state_helper_
.reset(helper
);
259 void NetworkScreen::SubscribeNetworkNotification() {
260 if (!is_network_subscribed_
) {
261 is_network_subscribed_
= true;
262 NetworkHandler::Get()->network_state_handler()->AddObserver(
267 void NetworkScreen::UnsubscribeNetworkNotification() {
268 if (is_network_subscribed_
) {
269 is_network_subscribed_
= false;
270 NetworkHandler::Get()->network_state_handler()->RemoveObserver(
275 void NetworkScreen::NotifyOnConnection() {
276 // TODO(nkostylev): Check network connectivity.
277 UnsubscribeNetworkNotification();
278 connection_timer_
.Stop();
279 Finish(BaseScreenDelegate::NETWORK_CONNECTED
);
282 void NetworkScreen::OnConnectionTimeout() {
283 StopWaitingForConnection(network_id_
);
284 if (!network_state_helper_
->IsConnected() && view_
) {
285 // Show error bubble.
286 view_
->ShowError(l10n_util::GetStringFUTF16(
287 IDS_NETWORK_SELECTION_ERROR
,
288 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME
), network_id_
));
292 void NetworkScreen::UpdateStatus() {
296 bool is_connected
= network_state_helper_
->IsConnected();
298 view_
->ClearErrors();
300 base::string16 network_name
= network_state_helper_
->GetCurrentNetworkName();
302 StopWaitingForConnection(network_name
);
303 else if (network_state_helper_
->IsConnecting())
304 WaitForConnection(network_name
);
306 StopWaitingForConnection(network_id_
);
309 void NetworkScreen::StopWaitingForConnection(const base::string16
& network_id
) {
310 bool is_connected
= network_state_helper_
->IsConnected();
311 if (is_connected
&& continue_pressed_
) {
312 NotifyOnConnection();
316 continue_pressed_
= false;
317 connection_timer_
.Stop();
319 network_id_
= network_id
;
321 view_
->ShowConnectingStatus(false, network_id_
);
323 GetContextEditor().SetBoolean(kContextKeyContinueButtonEnabled
, is_connected
);
326 void NetworkScreen::WaitForConnection(const base::string16
& network_id
) {
327 if (network_id_
!= network_id
|| !connection_timer_
.IsRunning()) {
328 connection_timer_
.Stop();
329 connection_timer_
.Start(FROM_HERE
,
330 base::TimeDelta::FromSeconds(kConnectionTimeoutSec
),
332 &NetworkScreen::OnConnectionTimeout
);
335 network_id_
= network_id
;
337 view_
->ShowConnectingStatus(continue_pressed_
, network_id_
);
339 GetContextEditor().SetBoolean(kContextKeyContinueButtonEnabled
, false);
342 void NetworkScreen::OnContinueButtonPressed() {
344 view_
->StopDemoModeDetection();
345 view_
->ClearErrors();
347 if (network_state_helper_
->IsConnected()) {
348 NotifyOnConnection();
350 continue_pressed_
= true;
351 WaitForConnection(network_id_
);
355 void NetworkScreen::OnLanguageChangedCallback(
356 const InputEventsBlocker
* /* input_events_blocker */,
357 const locale_util::LanguageSwitchResult
& result
) {
358 if (!selected_language_code_
.empty()) {
359 // We still do not have device owner, so owner settings are not applied.
360 // But Guest session can be started before owner is created, so we need to
361 // save locale settings directly here.
362 g_browser_process
->local_state()->SetString(prefs::kApplicationLocale
,
363 selected_language_code_
);
365 ScheduleResolveLanguageList(scoped_ptr
<locale_util::LanguageSwitchResult
>(
366 new locale_util::LanguageSwitchResult(result
)));
368 AccessibilityManager::Get()->OnLocaleChanged();
371 void NetworkScreen::ScheduleResolveLanguageList(
372 scoped_ptr
<locale_util::LanguageSwitchResult
> language_switch_result
) {
373 UILanguageListResolvedCallback callback
= base::Bind(
374 &NetworkScreen::OnLanguageListResolved
, weak_factory_
.GetWeakPtr());
375 ResolveUILanguageList(language_switch_result
.Pass(), callback
);
378 void NetworkScreen::OnLanguageListResolved(
379 scoped_ptr
<base::ListValue
> new_language_list
,
380 std::string new_language_list_locale
,
381 std::string new_selected_language
) {
382 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
384 language_list_
.reset(new_language_list
.release());
385 language_list_locale_
= new_language_list_locale
;
386 selected_language_code_
= new_selected_language
;
388 g_browser_process
->local_state()->SetString(prefs::kApplicationLocale
,
389 selected_language_code_
);
391 view_
->ReloadLocalizedContent();
392 FOR_EACH_OBSERVER(Observer
, observers_
, OnLanguageListReloaded());
395 void NetworkScreen::OnSystemTimezoneChanged() {
396 std::string current_timezone_id
;
397 CrosSettings::Get()->GetString(kSystemTimezone
, ¤t_timezone_id
);
398 GetContextEditor().SetString(kContextKeyTimezone
, current_timezone_id
);
401 } // namespace chromeos