summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 03:25:56 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 03:25:56 +0000
commit0f42f11ccbb7de2dbea2404481985a9473e694bd (patch)
treec7f1fdce20a699e0e2d2dfe275f19fe311cdca53
parent2a75eccb132d1027985f5e1909de3fa19a008227 (diff)
downloadchromium_src-0f42f11ccbb7de2dbea2404481985a9473e694bd.zip
chromium_src-0f42f11ccbb7de2dbea2404481985a9473e694bd.tar.gz
chromium_src-0f42f11ccbb7de2dbea2404481985a9473e694bd.tar.bz2
kiosk: Network connectivity test during launch.
- Add NetworkStateInformer and ErrorScreenActor to AppLaunchSplashScreenHandler; - AppLaunchSplashScreenHandler sends network state to its delegate (AppLaunchController) during network check; - AppLaunchController decides when to show network configure UI and call AppLaunchSplashScreenActor to show it (via ErrorScreenActor); - Show network config UI for enterprise kiosk; - Add a 'Reboot' button for kiosk network error; - Add a PromptForNetworkWhenOffline boolean field to DeviceLocalAccountsProto to control whether to show network config UI for enterprise managed kiosk; BUG=314710 TEST=KioskTest.LaunchAppNetworkDown/Portal Review URL: https://codereview.chromium.org/79113002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238873 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/policy/policy_templates.json22
-rw-r--r--chrome/browser/chromeos/app_mode/app_launch_utils.cc37
-rw-r--r--chrome/browser/chromeos/app_mode/startup_app_launcher.cc57
-rw-r--r--chrome/browser/chromeos/app_mode/startup_app_launcher.h32
-rw-r--r--chrome/browser/chromeos/login/app_launch_controller.cc107
-rw-r--r--chrome/browser/chromeos/login/app_launch_controller.h25
-rw-r--r--chrome/browser/chromeos/login/kiosk_browsertest.cc150
-rw-r--r--chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h12
-rw-r--r--chrome/browser/chromeos/login/test/oobe_screen_waiter.cc10
-rw-r--r--chrome/browser/chromeos/login/test/oobe_screen_waiter.h6
-rw-r--r--chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc8
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider.cc19
-rw-r--r--chrome/browser/policy/proto/chromeos/chrome_device_policy.proto12
-rw-r--r--chrome/browser/resources/chromeos/login/screen_error_message.css4
-rw-r--r--chrome/browser/resources/chromeos/login/screen_error_message.js14
-rw-r--r--chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc89
-rw-r--r--chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h21
-rw-r--r--chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc8
-rw-r--r--chrome/browser/ui/webui/chromeos/login/error_screen_handler.h1
-rw-r--r--chrome/browser/ui/webui/chromeos/login/oobe_ui.cc3
-rw-r--r--chrome/test/data/policy/policy_test_cases.json3
-rw-r--r--chromeos/settings/cros_settings_names.cc2
-rw-r--r--chromeos/settings/cros_settings_names.h2
-rw-r--r--tools/metrics/histograms/histograms.xml1
24 files changed, 448 insertions, 197 deletions
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index f0f5d94..074416d 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -118,7 +118,7 @@
# persistent IDs for all fields (but not for groups!) are needed. These are
# specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs,
# because doing so would break the deployed wire format!
-# For your editing convenience: highest ID currently used: 249
+# For your editing convenience: highest ID currently used: 250
#
# Placeholders:
# The following placeholder strings are automatically substituted:
@@ -3886,7 +3886,6 @@
},
'supported_on': ['chrome_os:25-'],
'device_only': True,
- 'future': True,
'features': {
'dynamic_refresh': True,
},
@@ -3946,7 +3945,6 @@
'features': {
'dynamic_refresh': True,
},
- 'future': True,
'example_value': True,
'id': 202,
'caption': '''Enable bailout keyboard shortcut for auto-login''',
@@ -3957,6 +3955,24 @@
If this policy is set to False, zero-delay auto-login (if configured) cannot be bypassed.'''
},
{
+ 'name': 'DeviceLocalAccountPromptForNetworkWhenOffline',
+ 'type': 'main',
+ 'schema': { 'type': 'boolean' },
+ 'supported_on': ['chrome_os:33-'],
+ 'device_only': True,
+ 'features': {
+ 'dynamic_refresh': True,
+ },
+ 'example_value': True,
+ 'id': 250,
+ 'caption': '''Enable network configuration prompt when offline''',
+ 'desc': '''Enable network configuration prompt when offline.
+
+ If this policy is unset or set to True and a device-local account is configured for zero-delay auto-login and the device does not have access to the Internet, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will show a network configuration prompt.
+
+ If this policy is set to False, an error message will be displayed instead of the network configuration prompt.'''
+ },
+ {
'name': 'BackgroundModeEnabled',
'type': 'main',
'schema': { 'type': 'boolean' },
diff --git a/chrome/browser/chromeos/app_mode/app_launch_utils.cc b/chrome/browser/chromeos/app_mode/app_launch_utils.cc
index 21efeb9..aee250c 100644
--- a/chrome/browser/chromeos/app_mode/app_launch_utils.cc
+++ b/chrome/browser/chromeos/app_mode/app_launch_utils.cc
@@ -14,15 +14,13 @@ namespace chromeos {
// A simple manager for the app launch that starts the launch
// and deletes itself when the launch finishes. On launch failure,
// it exits the browser process.
-class AppLaunchManager : public StartupAppLauncher::Observer {
+class AppLaunchManager : public StartupAppLauncher::Delegate {
public:
AppLaunchManager(Profile* profile, const std::string& app_id)
- : waiting_for_network_(false) {
- startup_app_launcher_.reset(new StartupAppLauncher(profile, app_id));
+ : startup_app_launcher_(new StartupAppLauncher(profile, app_id, this)) {
}
void Start() {
- startup_app_launcher_->AddObserver(this);
startup_app_launcher_->Initialize();
}
@@ -31,34 +29,19 @@ class AppLaunchManager : public StartupAppLauncher::Observer {
void Cleanup() { delete this; }
- void OnNetworkWaitTimedout() {
- DCHECK(waiting_for_network_);
- LOG(ERROR) << "Timed out while waiting for network during app launch.";
- OnLaunchFailed(KioskAppLaunchError::UNABLE_TO_INSTALL);
+ // StartupAppLauncher::Delegate overrides:
+ virtual void InitializeNetwork() OVERRIDE {
+ // This is on crash-restart path and assumes network is online.
+ // TODO(xiyuan): Remove the crash-restart path for kiosk or add proper
+ // network configure handling.
+ startup_app_launcher_->ContinueWithNetworkReady();
}
-
- // StartupAppLauncher::Observer overrides:
virtual void OnLoadingOAuthFile() OVERRIDE {}
virtual void OnInitializingTokenService() OVERRIDE {}
-
- virtual void OnInitializingNetwork() OVERRIDE {
- waiting_for_network_ = true;
- const int kMaxNetworkWaitSeconds = 5 * 60;
- network_wait_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromSeconds(kMaxNetworkWaitSeconds),
- this, &AppLaunchManager::OnNetworkWaitTimedout);
- }
-
- virtual void OnInstallingApp() OVERRIDE {
- waiting_for_network_ = false;
- network_wait_timer_.Stop();
- }
-
+ virtual void OnInstallingApp() OVERRIDE {}
virtual void OnReadyToLaunch() OVERRIDE {
startup_app_launcher_->LaunchApp();
}
-
virtual void OnLaunchSucceeded() OVERRIDE { Cleanup(); }
virtual void OnLaunchFailed(KioskAppLaunchError::Error error) OVERRIDE {
KioskAppLaunchError::Save(error);
@@ -66,8 +49,6 @@ class AppLaunchManager : public StartupAppLauncher::Observer {
Cleanup();
}
- base::OneShotTimer<AppLaunchManager> network_wait_timer_;
- bool waiting_for_network_;
scoped_ptr<StartupAppLauncher> startup_app_launcher_;
DISALLOW_COPY_AND_ASSIGN(AppLaunchManager);
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index 4bdae77..9c269b5 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -54,9 +54,12 @@ bool IsAppInstalled(Profile* profile, const std::string& app_id) {
StartupAppLauncher::StartupAppLauncher(Profile* profile,
- const std::string& app_id)
+ const std::string& app_id,
+ StartupAppLauncher::Delegate* delegate)
: profile_(profile),
app_id_(app_id),
+ delegate_(delegate),
+ install_attempted_(false),
ready_to_launch_(false) {
DCHECK(profile_);
DCHECK(Extension::IdIsValid(app_id_));
@@ -67,25 +70,22 @@ StartupAppLauncher::~StartupAppLauncher() {
// through a user bailout shortcut.
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
->RemoveObserver(this);
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
void StartupAppLauncher::Initialize() {
- DVLOG(1) << "Starting... connection = "
- << net::NetworkChangeNotifier::GetConnectionType();
StartLoadingOAuthFile();
}
-void StartupAppLauncher::AddObserver(Observer* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void StartupAppLauncher::RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
+void StartupAppLauncher::ContinueWithNetworkReady() {
+ // Starts install if it is not started.
+ if (!install_attempted_) {
+ install_attempted_ = true;
+ BeginInstall();
+ }
}
void StartupAppLauncher::StartLoadingOAuthFile() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnLoadingOAuthFile());
+ delegate_->OnLoadingOAuthFile();
KioskOAuthParams* auth_params = new KioskOAuthParams();
BrowserThread::PostBlockingPoolTaskAndReply(
@@ -137,17 +137,11 @@ void StartupAppLauncher::OnOAuthFileLoaded(KioskOAuthParams* auth_params) {
}
void StartupAppLauncher::InitializeNetwork() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingNetwork());
-
- // TODO(tengs): Use NetworkStateInformer instead because it can handle
- // portal and proxy detection. We will need to do some refactoring to
- // make NetworkStateInformer more independent from the WebUI handlers.
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
- OnNetworkChanged(net::NetworkChangeNotifier::GetConnectionType());
+ delegate_->InitializeNetwork();
}
void StartupAppLauncher::InitializeTokenService() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingTokenService());
+ delegate_->OnInitializingTokenService();
ProfileOAuth2TokenService* profile_token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
@@ -190,14 +184,14 @@ void StartupAppLauncher::OnRefreshTokensLoaded() {
}
void StartupAppLauncher::OnLaunchSuccess() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchSucceeded());
+ delegate_->OnLaunchSucceeded();
}
void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
LOG(ERROR) << "App launch failed, error: " << error;
DCHECK_NE(KioskAppLaunchError::NONE, error);
- FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchFailed(error));
+ delegate_->OnLaunchFailed(error);
}
void StartupAppLauncher::LaunchApp() {
@@ -231,10 +225,7 @@ void StartupAppLauncher::LaunchApp() {
}
void StartupAppLauncher::BeginInstall() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnInstallingApp());
-
- DVLOG(1) << "BeginInstall... connection = "
- << net::NetworkChangeNotifier::GetConnectionType();
+ delegate_->OnInstallingApp();
if (IsAppInstalled(profile_, app_id_)) {
OnReadyToLaunch();
@@ -269,21 +260,7 @@ void StartupAppLauncher::InstallCallback(bool success,
void StartupAppLauncher::OnReadyToLaunch() {
ready_to_launch_ = true;
- FOR_EACH_OBSERVER(Observer, observer_list_, OnReadyToLaunch());
-}
-
-void StartupAppLauncher::OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- DVLOG(1) << "OnNetworkChanged... connection = "
- << net::NetworkChangeNotifier::GetConnectionType();
- if (!net::NetworkChangeNotifier::IsOffline()) {
- DVLOG(1) << "Network up and running!";
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-
- BeginInstall();
- } else {
- DVLOG(1) << "Network not running yet!";
- }
+ delegate_->OnReadyToLaunch();
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
index b7d7baf..43f7cbf 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
@@ -10,10 +10,8 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
#include "google_apis/gaia/oauth2_token_service.h"
-#include "net/base/network_change_notifier.h"
class Profile;
@@ -34,37 +32,40 @@ namespace chromeos {
// - If all goes good, launches the app and finish the flow;
class StartupAppLauncher
: public base::SupportsWeakPtr<StartupAppLauncher>,
- public OAuth2TokenService::Observer,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
+ public OAuth2TokenService::Observer {
public:
- class Observer {
+ class Delegate {
public:
+ // Invoked to perform actual network initialization work. Note the app
+ // launch flow is paused until ContinueWithNetworkReady is called.
+ virtual void InitializeNetwork() = 0;
+
virtual void OnLoadingOAuthFile() = 0;
virtual void OnInitializingTokenService() = 0;
- virtual void OnInitializingNetwork() = 0;
virtual void OnInstallingApp() = 0;
virtual void OnReadyToLaunch() = 0;
virtual void OnLaunchSucceeded() = 0;
virtual void OnLaunchFailed(KioskAppLaunchError::Error error) = 0;
protected:
- virtual ~Observer() {}
+ virtual ~Delegate() {}
};
- StartupAppLauncher(Profile* profile, const std::string& app_id);
+ StartupAppLauncher(Profile* profile,
+ const std::string& app_id,
+ Delegate* delegate);
virtual ~StartupAppLauncher();
// Prepares the environment for an app launch.
void Initialize();
+ // Continues the initialization after network is ready.
+ void ContinueWithNetworkReady();
+
// Launches the app after the initialization is successful.
void LaunchApp();
- // Add and remove observers for app launch procedure.
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
private:
// OAuth parameters from /home/chronos/kiosk_auth file.
struct KioskOAuthParams {
@@ -91,13 +92,10 @@ class StartupAppLauncher
virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
virtual void OnRefreshTokensLoaded() OVERRIDE;
- // net::NetworkChangeNotifier::NetworkChangeObserver overrides:
- virtual void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
-
Profile* profile_;
const std::string app_id_;
- ObserverList<Observer> observer_list_;
+ Delegate* delegate_;
+ bool install_attempted_;
bool ready_to_launch_;
scoped_refptr<extensions::WebstoreStandaloneInstaller> installer_;
diff --git a/chrome/browser/chromeos/login/app_launch_controller.cc b/chrome/browser/chromeos/login/app_launch_controller.cc
index ecaf9ae..cf415c0 100644
--- a/chrome/browser/chromeos/login/app_launch_controller.cc
+++ b/chrome/browser/chromeos/login/app_launch_controller.cc
@@ -10,6 +10,7 @@
#include "base/json/json_file_value_serializer.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
@@ -19,7 +20,9 @@
#include "chrome/browser/chromeos/login/oobe_display.h"
#include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
#include "chrome/browser/chromeos/login/webui_login_view.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
@@ -40,8 +43,10 @@ const int kAppInstallSplashScreenMinTimeMS = 3000;
bool AppLaunchController::skip_splash_wait_ = false;
int AppLaunchController::network_wait_time_ = 10;
base::Closure* AppLaunchController::network_timeout_callback_ = NULL;
-AppLaunchController::CanConfigureNetworkCallback*
+AppLaunchController::ReturnBoolCallback*
AppLaunchController::can_configure_network_callback_ = NULL;
+AppLaunchController::ReturnBoolCallback*
+ AppLaunchController::need_owner_auth_to_configure_network_callback_ = NULL;
////////////////////////////////////////////////////////////////////////////////
// AppLaunchController::AppWindowWatcher
@@ -88,15 +93,12 @@ AppLaunchController::AppLaunchController(const std::string& app_id,
oobe_display_(oobe_display),
app_launch_splash_screen_actor_(
oobe_display_->GetAppLaunchSplashScreenActor()),
- error_screen_actor_(oobe_display_->GetErrorScreenActor()),
webui_visible_(false),
launcher_ready_(false),
waiting_for_network_(false),
network_wait_timedout_(false),
showing_network_dialog_(false),
launch_splash_start_time_(0) {
- signin_screen_.reset(new AppLaunchSigninScreen(
- static_cast<OobeUI*>(oobe_display_), this));
}
AppLaunchController::~AppLaunchController() {
@@ -122,28 +124,40 @@ void AppLaunchController::StartAppLaunch() {
kiosk_profile_loader_->Start();
}
+// static
void AppLaunchController::SkipSplashWaitForTesting() {
skip_splash_wait_ = true;
}
+// static
void AppLaunchController::SetNetworkWaitForTesting(int wait_time_secs) {
network_wait_time_ = wait_time_secs;
}
+// static
void AppLaunchController::SetNetworkTimeoutCallbackForTesting(
base::Closure* callback) {
network_timeout_callback_ = callback;
}
+// static
void AppLaunchController::SetCanConfigureNetworkCallbackForTesting(
- CanConfigureNetworkCallback* can_configure_network_callback) {
+ ReturnBoolCallback* can_configure_network_callback) {
can_configure_network_callback_ = can_configure_network_callback;
}
+// static
+void AppLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+ ReturnBoolCallback* need_owner_auth_callback) {
+ need_owner_auth_to_configure_network_callback_ = need_owner_auth_callback;
+}
+
void AppLaunchController::OnConfigureNetwork() {
DCHECK(profile_);
showing_network_dialog_ = true;
- if (CanConfigureNetwork()) {
+ if (CanConfigureNetwork() && NeedOwnerAuthToConfigureNetwork()) {
+ signin_screen_.reset(new AppLaunchSigninScreen(
+ static_cast<OobeUI*>(oobe_display_), this));
signin_screen_->Show();
} else {
// If kiosk mode was configured through enterprise policy, we may
@@ -155,12 +169,7 @@ void AppLaunchController::OnConfigureNetwork() {
}
void AppLaunchController::OnOwnerSigninSuccess() {
- error_screen_actor_->SetErrorState(
- ErrorScreen::ERROR_STATE_OFFLINE, std::string());
- error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_KIOSK_MODE);
-
- error_screen_actor_->Show(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH, NULL);
-
+ app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
signin_screen_.reset();
}
@@ -183,13 +192,22 @@ void AppLaunchController::OnCancelAppLaunch() {
OnLaunchFailed(KioskAppLaunchError::USER_CANCEL);
}
+void AppLaunchController::OnNetworkStateChanged(bool online) {
+ if (!waiting_for_network_)
+ return;
+
+ if (online)
+ startup_app_launcher_->ContinueWithNetworkReady();
+ else if (network_wait_timedout_)
+ MaybeShowNetworkConfigureUI();
+}
+
void AppLaunchController::OnProfileLoaded(Profile* profile) {
DVLOG(1) << "Profile loaded... Starting app launch.";
profile_ = profile;
kiosk_profile_loader_.reset();
- startup_app_launcher_.reset(new StartupAppLauncher(profile_, app_id_));
- startup_app_launcher_->AddObserver(this);
+ startup_app_launcher_.reset(new StartupAppLauncher(profile_, app_id_, this));
startup_app_launcher_->Initialize();
}
@@ -212,12 +230,7 @@ void AppLaunchController::OnNetworkWaitTimedout() {
<< net::NetworkChangeNotifier::GetConnectionType();
network_wait_timedout_ = true;
- if (CanConfigureNetwork()) {
- app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
- } else {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT);
- }
+ MaybeShowNetworkConfigureUI();
if (network_timeout_callback_)
network_timeout_callback_->Run();
@@ -232,23 +245,43 @@ bool AppLaunchController::CanConfigureNetwork() {
if (can_configure_network_callback_)
return can_configure_network_callback_->Run();
+ if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
+ bool should_prompt;
+ if (CrosSettings::Get()->GetBoolean(
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
+ &should_prompt)) {
+ return should_prompt;
+ }
+
+ // Default to true to allow network configuration if the policy is missing.
+ return true;
+ }
+
return !UserManager::Get()->GetOwnerEmail().empty();
}
-void AppLaunchController::OnLoadingOAuthFile() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE);
-}
+bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() {
+ if (need_owner_auth_to_configure_network_callback_)
+ return need_owner_auth_to_configure_network_callback_->Run();
-void AppLaunchController::OnInitializingTokenService() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE);
+ return !g_browser_process->browser_policy_connector()->IsEnterpriseManaged();
}
-void AppLaunchController::OnInitializingNetwork() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
+void AppLaunchController::MaybeShowNetworkConfigureUI() {
+ if (CanConfigureNetwork()) {
+ if (NeedOwnerAuthToConfigureNetwork()) {
+ app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
+ } else {
+ showing_network_dialog_ = true;
+ app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
+ }
+ } else {
+ app_launch_splash_screen_actor_->UpdateAppLaunchState(
+ AppLaunchSplashScreenActor::APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT);
+ }
+}
+void AppLaunchController::InitializeNetwork() {
// Show the network configration dialog if network is not initialized
// after a brief wait time.
waiting_for_network_ = true;
@@ -256,12 +289,26 @@ void AppLaunchController::OnInitializingNetwork() {
FROM_HERE,
base::TimeDelta::FromSeconds(network_wait_time_),
this, &AppLaunchController::OnNetworkWaitTimedout);
+
+ app_launch_splash_screen_actor_->UpdateAppLaunchState(
+ AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
+}
+
+void AppLaunchController::OnLoadingOAuthFile() {
+ app_launch_splash_screen_actor_->UpdateAppLaunchState(
+ AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE);
+}
+
+void AppLaunchController::OnInitializingTokenService() {
+ app_launch_splash_screen_actor_->UpdateAppLaunchState(
+ AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE);
}
void AppLaunchController::OnInstallingApp() {
app_launch_splash_screen_actor_->UpdateAppLaunchState(
AppLaunchSplashScreenActor::APP_LAUNCH_STATE_INSTALLING_APPLICATION);
+ waiting_for_network_ = false;
network_wait_timer_.Stop();
app_launch_splash_screen_actor_->ToggleNetworkConfig(false);
diff --git a/chrome/browser/chromeos/login/app_launch_controller.h b/chrome/browser/chromeos/login/app_launch_controller.h
index 382cb55..be2d463 100644
--- a/chrome/browser/chromeos/login/app_launch_controller.h
+++ b/chrome/browser/chromeos/login/app_launch_controller.h
@@ -17,7 +17,6 @@
#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h"
#include "chrome/browser/chromeos/login/app_launch_signin_screen.h"
#include "chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h"
-#include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -36,11 +35,11 @@ class AppLaunchController
: public base::SupportsWeakPtr<AppLaunchController>,
public AppLaunchSplashScreenActor::Delegate,
public KioskProfileLoader::Delegate,
- public StartupAppLauncher::Observer,
+ public StartupAppLauncher::Delegate,
public AppLaunchSigninScreen::Delegate,
public content::NotificationObserver {
public:
- typedef base::Callback<bool()> CanConfigureNetworkCallback;
+ typedef base::Callback<bool()> ReturnBoolCallback;
AppLaunchController(const std::string& app_id,
LoginDisplayHost* host,
@@ -59,7 +58,9 @@ class AppLaunchController
static void SetNetworkTimeoutCallbackForTesting(base::Closure* callback);
static void SetNetworkWaitForTesting(int wait_time_secs);
static void SetCanConfigureNetworkCallbackForTesting(
- CanConfigureNetworkCallback* can_configure_network_callback);
+ ReturnBoolCallback* can_configure_network_callback);
+ static void SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+ ReturnBoolCallback* need_owner_auth_callback);
private:
// A class to watch app window creation.
@@ -74,6 +75,13 @@ class AppLaunchController
// Whether the network could be configured during launching.
bool CanConfigureNetwork();
+ // Whether the owner password is needed to configure network.
+ bool NeedOwnerAuthToConfigureNetwork();
+
+ // Show network configuration UI if it is allowed. For consumer mode,
+ // owner password might be checked before showing the network configure UI.
+ void MaybeShowNetworkConfigureUI();
+
// KioskProfileLoader::Delegate overrides:
virtual void OnProfileLoaded(Profile* profile) OVERRIDE;
virtual void OnProfileLoadFailed(KioskAppLaunchError::Error error) OVERRIDE;
@@ -81,11 +89,12 @@ class AppLaunchController
// AppLaunchSplashScreenActor::Delegate overrides:
virtual void OnConfigureNetwork() OVERRIDE;
virtual void OnCancelAppLaunch() OVERRIDE;
+ virtual void OnNetworkStateChanged(bool online) OVERRIDE;
- // StartupAppLauncher::Observer overrides:
+ // StartupAppLauncher::Delegate overrides:
+ virtual void InitializeNetwork() OVERRIDE;
virtual void OnLoadingOAuthFile() OVERRIDE;
virtual void OnInitializingTokenService() OVERRIDE;
- virtual void OnInitializingNetwork() OVERRIDE;
virtual void OnInstallingApp() OVERRIDE;
virtual void OnReadyToLaunch() OVERRIDE;
virtual void OnLaunchSucceeded() OVERRIDE;
@@ -104,7 +113,6 @@ class AppLaunchController
LoginDisplayHost* host_;
OobeDisplay* oobe_display_;
AppLaunchSplashScreenActor* app_launch_splash_screen_actor_;
- ErrorScreenActor* error_screen_actor_;
scoped_ptr<KioskProfileLoader> kiosk_profile_loader_;
scoped_ptr<StartupAppLauncher> startup_app_launcher_;
scoped_ptr<AppLaunchSigninScreen> signin_screen_;
@@ -123,7 +131,8 @@ class AppLaunchController
static bool skip_splash_wait_;
static int network_wait_time_;
static base::Closure* network_timeout_callback_;
- static CanConfigureNetworkCallback* can_configure_network_callback_;
+ static ReturnBoolCallback* can_configure_network_callback_;
+ static ReturnBoolCallback* need_owner_auth_to_configure_network_callback_;
DISALLOW_COPY_AND_ASSIGN(AppLaunchController);
};
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index fd65deb..acdab07 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -10,6 +10,7 @@
#include "ash/shell.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
@@ -32,6 +33,7 @@
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
@@ -102,6 +104,9 @@ const char kTestEnterpriseServiceAccountId[] = "service_account@example.com";
const char kTestRefreshToken[] = "fake-refresh-token";
const char kTestAccessToken[] = "fake-access-token";
+// Note the path name must be the same as in shill stub.
+const char kStubEthernetServicePath[] = "eth1";
+
// Helper function for GetConsumerKioskModeStatusCallback.
void ConsumerKioskModeStatusCheck(
KioskAppManager::ConsumerKioskModeStatus* out_status,
@@ -136,58 +141,44 @@ void CopyTokenService(DeviceOAuth2TokenService** out_token_service,
// Helper functions for CanConfigureNetwork mock.
class ScopedCanConfigureNetwork {
public:
- explicit ScopedCanConfigureNetwork(bool can_configure)
+ ScopedCanConfigureNetwork(bool can_configure, bool needs_owner_auth)
: can_configure_(can_configure),
- callback_(base::Bind(&ScopedCanConfigureNetwork::CanConfigureNetwork,
- base::Unretained(this))) {
- AppLaunchController::SetCanConfigureNetworkCallbackForTesting(&callback_);
+ needs_owner_auth_(needs_owner_auth),
+ can_configure_network_callback_(
+ base::Bind(&ScopedCanConfigureNetwork::CanConfigureNetwork,
+ base::Unretained(this))),
+ needs_owner_auth_callback_(base::Bind(
+ &ScopedCanConfigureNetwork::NeedsOwnerAuthToConfigureNetwork,
+ base::Unretained(this))) {
+ AppLaunchController::SetCanConfigureNetworkCallbackForTesting(
+ &can_configure_network_callback_);
+ AppLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+ &needs_owner_auth_callback_);
}
~ScopedCanConfigureNetwork() {
AppLaunchController::SetCanConfigureNetworkCallbackForTesting(NULL);
+ AppLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+ NULL);
}
bool CanConfigureNetwork() {
return can_configure_;
}
+ bool NeedsOwnerAuthToConfigureNetwork() {
+ return needs_owner_auth_;
+ }
+
private:
bool can_configure_;
- AppLaunchController::CanConfigureNetworkCallback callback_;
+ bool needs_owner_auth_;
+ AppLaunchController::ReturnBoolCallback can_configure_network_callback_;
+ AppLaunchController::ReturnBoolCallback needs_owner_auth_callback_;
DISALLOW_COPY_AND_ASSIGN(ScopedCanConfigureNetwork);
};
} // namespace
-// Fake NetworkChangeNotifier used to simulate network connectivity.
-class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier {
- public:
- FakeNetworkChangeNotifier() : connection_type_(CONNECTION_NONE) {}
-
- virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
- return connection_type_;
- }
-
- void GoOnline() {
- SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
- }
-
- void GoOffline() {
- SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
- }
-
- void SetConnectionType(ConnectionType type) {
- connection_type_ = type;
- NotifyObserversOfNetworkChange(type);
- base::RunLoop().RunUntilIdle();
- }
-
- virtual ~FakeNetworkChangeNotifier() {}
-
- private:
- ConnectionType connection_type_;
- DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifier);
-};
-
// Helper class that monitors app windows to wait for a window to appear.
class ShellWindowObserver : public apps::ShellWindowRegistry::Observer {
public:
@@ -262,6 +253,11 @@ class KioskTest : public InProcessBrowserTest {
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
host_resolver()->AddRule("*", "127.0.0.1");
+
+ network_portal_detector_ = new NetworkPortalDetectorTestImpl();
+ NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+ network_portal_detector_->SetDefaultNetworkPathForTesting(
+ kStubEthernetServicePath);
}
virtual void SetUpOnMainThread() OVERRIDE {
@@ -270,10 +266,6 @@ class KioskTest : public InProcessBrowserTest {
}
virtual void CleanUpOnMainThread() OVERRIDE {
- // We need to clean up these objects in this specific order.
- fake_network_notifier_.reset(NULL);
- disable_network_notifier_.reset(NULL);
-
AppLaunchController::SetNetworkTimeoutCallbackForTesting(NULL);
AppLaunchSigninScreen::SetUserManagerForTesting(NULL);
@@ -331,7 +323,7 @@ class KioskTest : public InProcessBrowserTest {
KioskAppManager::Get()->SetAutoLaunchApp(kTestKioskApp);
}
- void StartAppLaunchFromLoginScreen(bool has_connectivity) {
+ void StartAppLaunchFromLoginScreen(const base::Closure& network_setup_cb) {
EnableConsumerKioskMode();
// Start UI, find menu entry for this app and launch it.
@@ -352,8 +344,8 @@ class KioskTest : public InProcessBrowserTest {
ReloadKioskApps();
apps_loaded_signal.Wait();
- if (!has_connectivity)
- SimulateNetworkOffline();
+ if (!network_setup_cb.is_null())
+ network_setup_cb.Run();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
@@ -410,15 +402,43 @@ class KioskTest : public InProcessBrowserTest {
}
void SimulateNetworkOffline() {
- disable_network_notifier_.reset(
- new net::NetworkChangeNotifier::DisableForTest);
+ NetworkPortalDetector::CaptivePortalState offline_state;
+ offline_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE;
+ network_portal_detector_->SetDetectionResultsForTesting(
+ kStubEthernetServicePath, offline_state);
+ network_portal_detector_->NotifyObserversForTesting();
+ }
- fake_network_notifier_.reset(new FakeNetworkChangeNotifier);
+ base::Closure SimulateNetworkOfflineClosure() {
+ return base::Bind(&KioskTest::SimulateNetworkOffline,
+ base::Unretained(this));
}
void SimulateNetworkOnline() {
- if (fake_network_notifier_.get())
- fake_network_notifier_->GoOnline();
+ NetworkPortalDetector::CaptivePortalState online_state;
+ online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
+ online_state.response_code = 204;
+ network_portal_detector_->SetDetectionResultsForTesting(
+ kStubEthernetServicePath, online_state);
+ network_portal_detector_->NotifyObserversForTesting();
+ }
+
+ base::Closure SimulateNetworkOnlineClosure() {
+ return base::Bind(&KioskTest::SimulateNetworkOnline,
+ base::Unretained(this));
+ }
+
+ void SimulateNetworkPortal() {
+ NetworkPortalDetector::CaptivePortalState portal_state;
+ portal_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
+ network_portal_detector_->SetDetectionResultsForTesting(
+ kStubEthernetServicePath, portal_state);
+ network_portal_detector_->NotifyObserversForTesting();
+ }
+
+ base::Closure SimulateNetworkPortalClosure() {
+ return base::Bind(&KioskTest::SimulateNetworkPortal,
+ base::Unretained(this));
}
void WaitForAppLaunchNetworkTimeout() {
@@ -491,23 +511,21 @@ class KioskTest : public InProcessBrowserTest {
}
FakeGaia fake_gaia_;
- scoped_ptr<net::NetworkChangeNotifier::DisableForTest>
- disable_network_notifier_;
- scoped_ptr<FakeNetworkChangeNotifier> fake_network_notifier_;
scoped_ptr<MockUserManager> mock_user_manager_;
+ NetworkPortalDetectorTestImpl* network_portal_detector_;
};
IN_PROC_BROWSER_TEST_F(KioskTest, InstallAndLaunchApp) {
- StartAppLaunchFromLoginScreen(true);
+ StartAppLaunchFromLoginScreen(SimulateNetworkOnlineClosure());
WaitForAppLaunchSuccess();
}
IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDown) {
- // Mock network could be configured.
- ScopedCanConfigureNetwork can_configure_network(true);
+ // Mock network could be configured with owner's password.
+ ScopedCanConfigureNetwork can_configure_network(true, true);
// Start app launch and wait for network connectivity timeout.
- StartAppLaunchFromLoginScreen(false);
+ StartAppLaunchFromLoginScreen(SimulateNetworkOfflineClosure());
OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH);
splash_waiter.Wait();
WaitForAppLaunchNetworkTimeout();
@@ -540,10 +558,10 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDown) {
IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDownConfigureNotAllowed) {
// Mock network could not be configured.
- ScopedCanConfigureNetwork can_configure_network(false);
+ ScopedCanConfigureNetwork can_configure_network(false, true);
// Start app launch and wait for network connectivity timeout.
- StartAppLaunchFromLoginScreen(false);
+ StartAppLaunchFromLoginScreen(SimulateNetworkOfflineClosure());
OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH);
splash_waiter.Wait();
WaitForAppLaunchNetworkTimeout();
@@ -555,8 +573,26 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDownConfigureNotAllowed) {
WaitForAppLaunchSuccess();
}
+IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkPortal) {
+ // Mock network could be configured without the owner password.
+ ScopedCanConfigureNetwork can_configure_network(true, false);
+
+ // Start app launch with network portal state.
+ StartAppLaunchFromLoginScreen(SimulateNetworkPortalClosure());
+ OobeScreenWaiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH)
+ .WaitNoAssertCurrentScreen();
+ WaitForAppLaunchNetworkTimeout();
+
+ // Network error should show up automatically since this test does not
+ // require owner auth to configure network.
+ OobeScreenWaiter(OobeDisplay::SCREEN_ERROR_MESSAGE).Wait();
+
+ ASSERT_TRUE(GetAppLaunchController()->showing_network_dialog());
+ WaitForAppLaunchSuccess();
+}
+
IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppUserCancel) {
- StartAppLaunchFromLoginScreen(false);
+ StartAppLaunchFromLoginScreen(SimulateNetworkOfflineClosure());
OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH);
splash_waiter.Wait();
diff --git a/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
index 83ad878..2547466 100644
--- a/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
+++ b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
@@ -23,9 +23,16 @@ class AppLaunchSplashScreenActor {
class Delegate {
public:
+ // Invoked when the configure network control is clicked.
virtual void OnConfigureNetwork() = 0;
+
+ // Invoked when the app launch bailout shortcut key is pressed.
virtual void OnCancelAppLaunch() = 0;
+ // Invoked when network state is changed. |online| is true if the device
+ // is connected to the Internet.
+ virtual void OnNetworkStateChanged(bool online) = 0;
+
protected:
virtual ~Delegate() {}
};
@@ -47,8 +54,11 @@ class AppLaunchSplashScreenActor {
// Set the current app launch state.
virtual void UpdateAppLaunchState(AppLaunchState state) = 0;
- // Sets whether continue control is enabled.
+ // Sets whether configure network control is visible.
virtual void ToggleNetworkConfig(bool visible) = 0;
+
+ // Shows the network error and configure UI.
+ virtual void ShowNetworkConfigureUI() = 0;
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
index 456bd4c..1e2b44b 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
@@ -22,16 +22,20 @@ OobeScreenWaiter::~OobeScreenWaiter() {
}
void OobeScreenWaiter::Wait() {
- if (GetOobeUI()->current_screen() == expected_screen_) {
+ WaitNoAssertCurrentScreen();
+
+ ASSERT_EQ(expected_screen_, GetOobeUI()->current_screen());
+}
+
+void OobeScreenWaiter::WaitNoAssertCurrentScreen() {
+ if (GetOobeUI()->current_screen() == expected_screen_)
return;
- }
waiting_for_screen_ = true;
GetOobeUI()->AddObserver(this);
runner_ = new content::MessageLoopRunner;
runner_->Run();
- ASSERT_EQ(expected_screen_, GetOobeUI()->current_screen());
ASSERT_FALSE(waiting_for_screen_);
}
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
index 4704f37..8df9b8b 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
@@ -21,8 +21,14 @@ class OobeScreenWaiter : public OobeUI::Observer {
explicit OobeScreenWaiter(OobeDisplay::Screen expected_screen);
virtual ~OobeScreenWaiter();
+ // Run message loop to wait for the expected_screen.
void Wait();
+ // Similar to Wait() but does not assert the current screen is
+ // expected_screen on exit. Use this when there are multiple screen changes
+ // during the wait and the screen to be waited is not the final one.
+ void WaitNoAssertCurrentScreen();
+
// OobeUI::Observer implementation:
virtual void OnCurrentScreenChanged(
OobeDisplay::Screen current_screen,
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index acf85b7..ea40489 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -182,6 +182,14 @@ void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy,
container.enable_auto_login_bailout()),
NULL);
}
+ if (container.has_prompt_for_network_when_offline()) {
+ policies->Set(key::kDeviceLocalAccountPromptForNetworkWhenOffline,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_MACHINE,
+ Value::CreateBooleanValue(
+ container.prompt_for_network_when_offline()),
+ NULL);
+ }
}
if (policy.has_supervised_users_settings()) {
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 6ed8114..439c271b 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -51,6 +51,7 @@ const char* kKnownSettings[] = {
kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
kAccountsPrefDeviceLocalAccountAutoLoginDelay,
kAccountsPrefDeviceLocalAccountAutoLoginId,
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
kAccountsPrefEphemeralUsersEnabled,
kAccountsPrefShowUserNamesOnSignIn,
kAccountsPrefSupervisedUsersEnabled,
@@ -307,6 +308,15 @@ void DeviceSettingsProvider::SetInPolicy() {
device_local_accounts->set_enable_auto_login_bailout(enabled);
else
NOTREACHED();
+ } else if (prop ==
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline) {
+ em::DeviceLocalAccountsProto* device_local_accounts =
+ device_settings_.mutable_device_local_accounts();
+ bool should_prompt;
+ if (value->GetAsBoolean(&should_prompt))
+ device_local_accounts->set_prompt_for_network_when_offline(should_prompt);
+ else
+ NOTREACHED();
} else if (prop == kSignedDataRoamingEnabled) {
em::DataRoamingEnabledProto* roam =
device_settings_.mutable_data_roaming_enabled();
@@ -554,6 +564,9 @@ void DeviceSettingsProvider::DecodeLoginPolicies(
new_values_cache->SetBoolean(
kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
policy.device_local_accounts().enable_auto_login_bailout());
+ new_values_cache->SetBoolean(
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
+ policy.device_local_accounts().prompt_for_network_when_offline());
if (policy.has_start_up_flags()) {
base::ListValue* list = new base::ListValue();
@@ -816,9 +829,9 @@ void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
migration_values_.SetValue(kStatsReportingPref,
base::Value::CreateBooleanValue(new_value));
AttemptMigration();
- LOG(INFO) << "No metrics policy set will revert to checking "
- << "consent file which is "
- << (new_value ? "on." : "off.");
+ VLOG(1) << "No metrics policy set will revert to checking "
+ << "consent file which is "
+ << (new_value ? "on." : "off.");
UMA_HISTOGRAM_COUNTS("DeviceSettings.MetricsMigrated", 1);
}
VLOG(1) << "Metrics policy is being set to : " << new_value
diff --git a/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto b/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
index 911866b..b841f1f 100644
--- a/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
+++ b/chrome/browser/policy/proto/chromeos/chrome_device_policy.proto
@@ -313,9 +313,19 @@ message DeviceLocalAccountsProto {
// Whether the keyboard shortcut to prevent zero-delay auto-login should be
// enabled or not. If this keyboard shortcut is engaged, the auto-login will
- // be delayed by 3 minutes so administrators can log in or make configuration
+ // be delayed by 3 seconds so administrators can log in or make configuration
// changes.
optional bool enable_auto_login_bailout = 4 [default = true];
+
+ // Whether network configuration should be offered or not when the device
+ // does not have access to the Internet. If the policy is omitted or set to
+ // true, the network configuration will be offered. Otherwise, only an error
+ // message is displayed.
+ // Note: If both this policy and enable_auto_login_bailout policy above is
+ // set to false, there are chances that the device might become totally
+ // unusable when there is no Internet access and has to go through the
+ // recovery process.
+ optional bool prompt_for_network_when_offline = 5 [default = true];
}
message AllowRedeemChromeOsRegistrationOffersProto {
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.css b/chrome/browser/resources/chromeos/login/screen_error_message.css
index 73ec409..3160803 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.css
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.css
@@ -93,3 +93,7 @@
.offline-network-list-label {
-webkit-margin-end: 10px;
}
+
+.button-spacer {
+ -webkit-box-flex: 1;
+}
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.js b/chrome/browser/resources/chromeos/login/screen_error_message.js
index 2c51904..039208c 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.js
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.js
@@ -165,6 +165,20 @@ login.createScreen('ErrorMessageScreen', 'error-message', function() {
get buttons() {
var buttons = [];
+ var rebootButton = this.ownerDocument.createElement('button');
+ rebootButton.textContent = loadTimeData.getString('rebootButton');
+ rebootButton.classList.add('show-with-ui-state-kiosk-mode');
+ rebootButton.addEventListener('click', function(e) {
+ chrome.send('rebootButtonClicked');
+ e.stopPropagation();
+ });
+ buttons.push(rebootButton);
+
+ var spacer = this.ownerDocument.createElement('div');
+ spacer.classList.add('button-spacer');
+ spacer.classList.add('show-with-ui-state-kiosk-mode');
+ buttons.push(spacer);
+
var powerwashButton = this.ownerDocument.createElement('button');
powerwashButton.id = 'error-message-restart-and-powerwash-button';
powerwashButton.textContent =
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
index 5542049..e95fa2e 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
@@ -5,7 +5,10 @@
#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "grit/browser_resources.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/chromium_strings.h"
@@ -18,18 +21,34 @@ namespace {
const char kJsScreenPath[] = "login.AppLaunchSplashScreen";
+// Returns network name by service path.
+std::string GetNetworkName(const std::string& service_path) {
+ const chromeos::NetworkState* network =
+ chromeos::NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+ service_path);
+ if (!network)
+ return std::string();
+ return network->name();
+}
+
} // namespace
namespace chromeos {
-AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler()
+AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler(
+ const scoped_refptr<NetworkStateInformer>& network_state_informer,
+ ErrorScreenActor* error_screen_actor)
: BaseScreenHandler(kJsScreenPath),
delegate_(NULL),
show_on_init_(false),
- state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE) {
+ state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE),
+ network_state_informer_(network_state_informer),
+ error_screen_actor_(error_screen_actor) {
+ network_state_informer_->AddObserver(this);
}
AppLaunchSplashScreenHandler::~AppLaunchSplashScreenHandler() {
+ network_state_informer_->RemoveObserver(this);
}
void AppLaunchSplashScreenHandler::DeclareLocalizedValues(
@@ -103,6 +122,7 @@ void AppLaunchSplashScreenHandler::UpdateAppLaunchState(AppLaunchState state) {
SetLaunchText(
l10n_util::GetStringUTF8(GetProgressMessageFromState(state_)));
}
+ UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
}
void AppLaunchSplashScreenHandler::SetDelegate(
@@ -110,6 +130,71 @@ void AppLaunchSplashScreenHandler::SetDelegate(
delegate_ = delegate;
}
+void AppLaunchSplashScreenHandler::ShowNetworkConfigureUI() {
+ NetworkStateInformer::State state = network_state_informer_->state();
+ if (state == NetworkStateInformer::ONLINE) {
+ delegate_->OnNetworkStateChanged(true);
+ return;
+ }
+
+ const std::string network_path = network_state_informer_->network_path();
+ const std::string network_name = GetNetworkName(network_path);
+
+ error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_KIOSK_MODE);
+ error_screen_actor_->AllowGuestSignin(false);
+ error_screen_actor_->AllowOfflineLogin(false);
+
+ switch (state) {
+ case NetworkStateInformer::CAPTIVE_PORTAL: {
+ error_screen_actor_->SetErrorState(
+ ErrorScreen::ERROR_STATE_PORTAL, network_name);
+ error_screen_actor_->FixCaptivePortal();
+
+ break;
+ }
+ case NetworkStateInformer::PROXY_AUTH_REQUIRED: {
+ error_screen_actor_->SetErrorState(
+ ErrorScreen::ERROR_STATE_PROXY, network_name);
+ break;
+ }
+ case NetworkStateInformer::OFFLINE: {
+ error_screen_actor_->SetErrorState(
+ ErrorScreen::ERROR_STATE_OFFLINE, network_name);
+ break;
+ }
+ default:
+ error_screen_actor_->SetErrorState(
+ ErrorScreen::ERROR_STATE_OFFLINE, network_name);
+ NOTREACHED();
+ break;
+ };
+
+ OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
+ OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
+ if (oobe_ui)
+ screen = oobe_ui->current_screen();
+
+ if (screen != OobeUI::SCREEN_ERROR_MESSAGE)
+ error_screen_actor_->Show(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH, NULL);
+}
+
+void AppLaunchSplashScreenHandler::OnNetworkReady() {
+ // Purposely leave blank because the online case is handled in UpdateState
+ // call below.
+}
+
+void AppLaunchSplashScreenHandler::UpdateState(
+ ErrorScreenActor::ErrorReason reason) {
+ if (!delegate_ ||
+ (state_ != APP_LAUNCH_STATE_PREPARING_NETWORK &&
+ state_ != APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT)) {
+ return;
+ }
+
+ NetworkStateInformer::State state = network_state_informer_->state();
+ delegate_->OnNetworkStateChanged(state == NetworkStateInformer::ONLINE);
+}
+
void AppLaunchSplashScreenHandler::PopulateAppInfo(
base::DictionaryValue* out_info) {
KioskAppManager::App app;
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
index 72cc4b7..f2c10b5 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
@@ -10,14 +10,21 @@
#include "chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
namespace chromeos {
+class ErrorScreenActor;
+
// A class that handles the WebUI hooks for the app launch splash screen.
-class AppLaunchSplashScreenHandler : public BaseScreenHandler,
- public AppLaunchSplashScreenActor {
+class AppLaunchSplashScreenHandler
+ : public BaseScreenHandler,
+ public AppLaunchSplashScreenActor,
+ public NetworkStateInformer::NetworkStateInformerObserver {
public:
- AppLaunchSplashScreenHandler();
+ AppLaunchSplashScreenHandler(
+ const scoped_refptr<NetworkStateInformer>& network_state_informer,
+ ErrorScreenActor* error_screen_actor);
virtual ~AppLaunchSplashScreenHandler();
// BaseScreenHandler implementation:
@@ -35,6 +42,11 @@ class AppLaunchSplashScreenHandler : public BaseScreenHandler,
virtual void UpdateAppLaunchState(AppLaunchState state) OVERRIDE;
virtual void SetDelegate(
AppLaunchSplashScreenHandler::Delegate* delegate) OVERRIDE;
+ virtual void ShowNetworkConfigureUI() OVERRIDE;
+
+ // NetworkStateInformer::NetworkStateInformerObserver implementation:
+ virtual void OnNetworkReady() OVERRIDE;
+ virtual void UpdateState(ErrorScreenActor::ErrorReason reason) OVERRIDE;
private:
void PopulateAppInfo(base::DictionaryValue* out_info);
@@ -48,6 +60,9 @@ class AppLaunchSplashScreenHandler : public BaseScreenHandler,
std::string app_id_;
AppLaunchState state_;
+ scoped_refptr<NetworkStateInformer> network_state_informer_;
+ ErrorScreenActor* error_screen_actor_;
+
DISALLOW_COPY_AND_ASSIGN(AppLaunchSplashScreenHandler);
};
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index 978a67a..8d6f25a 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -140,6 +141,10 @@ void ErrorScreenHandler::HandleLocalStateErrorPowerwashButtonClicked() {
StartDeviceWipe();
}
+void ErrorScreenHandler::HandleRebootButtonClicked() {
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
+}
+
void ErrorScreenHandler::RegisterMessages() {
AddCallback("showCaptivePortal",
&ErrorScreenHandler::HandleShowCaptivePortal);
@@ -147,6 +152,8 @@ void ErrorScreenHandler::RegisterMessages() {
&ErrorScreenHandler::HandleHideCaptivePortal);
AddCallback("localStateErrorPowerwashButtonClicked",
&ErrorScreenHandler::HandleLocalStateErrorPowerwashButtonClicked);
+ AddCallback("rebootButtonClicked",
+ &ErrorScreenHandler::HandleRebootButtonClicked);
}
void ErrorScreenHandler::DeclareLocalizedValues(
@@ -168,6 +175,7 @@ void ErrorScreenHandler::DeclareLocalizedValues(
builder->Add("localStateErrorText1", IDS_LOCAL_STATE_ERROR_TEXT_1);
builder->Add("localStateErrorPowerwashButton",
IDS_LOCAL_STATE_ERROR_POWERWASH_BUTTON);
+ builder->Add("rebootButton", IDS_RELAUNCH_BUTTON);
}
void ErrorScreenHandler::Initialize() {
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
index 88eed50..8a53aae 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
@@ -53,6 +53,7 @@ class ErrorScreenHandler : public BaseScreenHandler,
void HandleShowCaptivePortal();
void HandleHideCaptivePortal();
void HandleLocalStateErrorPowerwashButtonClicked();
+ void HandleRebootButtonClicked();
// WebUIMessageHandler implementation:
virtual void RegisterMessages() OVERRIDE;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 35c60d3..f7adbe9 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -252,7 +252,8 @@ OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url)
AddScreenHandler(signin_screen_handler_);
AppLaunchSplashScreenHandler* app_launch_splash_screen_handler =
- new AppLaunchSplashScreenHandler();
+ new AppLaunchSplashScreenHandler(network_state_informer_,
+ error_screen_handler_);
AddScreenHandler(app_launch_splash_screen_handler);
app_launch_splash_screen_actor_ = app_launch_splash_screen_handler;
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 03c335a..925e7c1 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -2076,6 +2076,9 @@
"DeviceLocalAccountAutoLoginBailoutEnabled": {
},
+ "DeviceLocalAccountPromptForNetworkWhenOffline": {
+ },
+
"DeviceLoginScreenPowerManagement": {
},
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc
index fbc30a3..d28c01d 100644
--- a/chromeos/settings/cros_settings_names.cc
+++ b/chromeos/settings/cros_settings_names.cc
@@ -30,6 +30,8 @@ const char kAccountsPrefDeviceLocalAccountAutoLoginDelay[] =
"cros.accounts.deviceLocalAccountAutoLoginDelay";
const char kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[] =
"cros.accounts.deviceLocalAccountAutoLoginBailoutEnabled";
+const char kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline[] =
+ "cros.accounts.deviceLocalAccountPromptForNetworkWhenOffline";
const char kAccountsPrefSupervisedUsersEnabled[] =
"cros.accounts.supervisedUsersEnabled";
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h
index ffaf6f4..854c6bc 100644
--- a/chromeos/settings/cros_settings_names.h
+++ b/chromeos/settings/cros_settings_names.h
@@ -27,6 +27,8 @@ CHROMEOS_EXPORT extern const char
kAccountsPrefDeviceLocalAccountAutoLoginDelay[];
CHROMEOS_EXPORT extern const char
kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled[];
+CHROMEOS_EXPORT extern const char
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline[];
CHROMEOS_EXPORT extern const char kAccountsPrefSupervisedUsersEnabled[];
CHROMEOS_EXPORT extern const char kSignedDataRoamingEnabled[];
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3f00da2..c855889 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -22997,6 +22997,7 @@ other types of suffix sets.
session"/>
<int value="248" label="Report device users"/>
<int value="249" label="User avatar image"/>
+ <int value="250" label="Enable network configuration prompt when offline"/>
</enum>
<enum name="EnterprisePolicyInvalidations" type="int">