#include "chrome/browser/chromeos/login/app_launch_controller.h"
-#include "apps/shell_window_registry.h"
+#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.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"
#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h"
-#include "chrome/browser/chromeos/login/login_display_host.h"
-#include "chrome/browser/chromeos/login/login_display_host_impl.h"
-#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/login/ui/login_display_host.h"
+#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
+#include "chrome/browser/chromeos/login/ui/oobe_display.h"
+#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/lifetime/application_lifetime.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"
-#include "content/public/browser/browser_thread.h"
+#include "components/user_manager/user_manager.h"
#include "content/public/browser/notification_service.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/app_window_registry.h"
#include "net/base/network_change_notifier.h"
namespace chromeos {
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
class AppLaunchController::AppWindowWatcher
- : public apps::ShellWindowRegistry::Observer {
+ : public extensions::AppWindowRegistry::Observer {
public:
- explicit AppWindowWatcher(AppLaunchController* controller)
- : controller_(controller),
- window_registry_(apps::ShellWindowRegistry::Get(controller->profile_)) {
- window_registry_->AddObserver(this);
+ explicit AppWindowWatcher(AppLaunchController* controller,
+ const std::string& app_id)
+ : controller_(controller),
+ app_id_(app_id),
+ window_registry_(
+ extensions::AppWindowRegistry::Get(controller->profile_)),
+ weak_factory_(this) {
+ if (!window_registry_->GetAppWindowsForApp(app_id).empty()) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AppWindowWatcher::NotifyAppWindowCreated,
+ weak_factory_.GetWeakPtr()));
+ return;
+ } else {
+ window_registry_->AddObserver(this);
+ }
}
virtual ~AppWindowWatcher() {
window_registry_->RemoveObserver(this);
}
private:
- // apps::ShellWindowRegistry::Observer overrides:
- virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {
- if (controller_) {
- controller_->OnAppWindowCreated();
- controller_= NULL;
+ // extensions::AppWindowRegistry::Observer overrides:
+ virtual void OnAppWindowAdded(extensions::AppWindow* app_window) OVERRIDE {
+ if (app_window->extension_id() == app_id_) {
+ window_registry_->RemoveObserver(this);
+ NotifyAppWindowCreated();
}
}
- virtual void OnShellWindowIconChanged(
- apps::ShellWindow* shell_window) OVERRIDE {}
- virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window) OVERRIDE {}
+
+ void NotifyAppWindowCreated() {
+ controller_->OnAppWindowCreated();
+ }
AppLaunchController* controller_;
- apps::ShellWindowRegistry* window_registry_;
+ std::string app_id_;
+ extensions::AppWindowRegistry* window_registry_;
+ base::WeakPtrFactory<AppWindowWatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AppWindowWatcher);
};
// AppLaunchController
AppLaunchController::AppLaunchController(const std::string& app_id,
+ bool diagnostic_mode,
LoginDisplayHost* host,
OobeDisplay* oobe_display)
: profile_(NULL),
app_id_(app_id),
+ diagnostic_mode_(diagnostic_mode),
host_(host),
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),
+ network_config_requested_(false),
launch_splash_start_time_(0) {
- signin_screen_.reset(new AppLaunchSigninScreen(
- static_cast<OobeUI*>(oobe_display_), this));
}
AppLaunchController::~AppLaunchController() {
app_launch_splash_screen_actor_->SetDelegate(this);
app_launch_splash_screen_actor_->Show(app_id_);
+ KioskAppManager::App app;
+ CHECK(KioskAppManager::Get());
+ CHECK(KioskAppManager::Get()->GetApp(app_id_, &app));
kiosk_profile_loader_.reset(
- new KioskProfileLoader(KioskAppManager::Get(), app_id_, this));
+ new KioskProfileLoader(app.user_id, false, this));
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
}
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();
}
OnLaunchFailed(KioskAppLaunchError::USER_CANCEL);
}
+void AppLaunchController::OnNetworkConfigRequested(bool requested) {
+ network_config_requested_ = requested;
+ if (requested)
+ MaybeShowNetworkConfigureUI();
+ else
+ startup_app_launcher_->RestartLauncher();
+}
+
+void AppLaunchController::OnNetworkStateChanged(bool online) {
+ if (!waiting_for_network_)
+ return;
+
+ if (online && !network_config_requested_)
+ startup_app_launcher_->ContinueWithNetworkReady();
+ else if (network_wait_timedout_)
+ MaybeShowNetworkConfigureUI();
+}
+
void AppLaunchController::OnProfileLoaded(Profile* profile) {
DVLOG(1) << "Profile loaded... Starting app launch.";
profile_ = profile;
+ // This is needed to trigger input method extensions being loaded.
+ profile_->InitChromeOSPreferences();
+
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_, diagnostic_mode_, this));
startup_app_launcher_->Initialize();
}
void AppLaunchController::CleanUp() {
kiosk_profile_loader_.reset();
startup_app_launcher_.reset();
+ splash_wait_timer_.Stop();
if (host_)
host_->Finalize();
<< 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();
if (can_configure_network_callback_)
return can_configure_network_callback_->Run();
- return !UserManager::Get()->GetOwnerEmail().empty();
-}
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()->browser_policy_connector_chromeos();
+ if (connector->IsEnterpriseManaged()) {
+ bool should_prompt;
+ if (CrosSettings::Get()->GetBoolean(
+ kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
+ &should_prompt)) {
+ return should_prompt;
+ }
-void AppLaunchController::OnLoadingOAuthFile() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_AUTH_FILE);
+ // Default to true to allow network configuration if the policy is missing.
+ return true;
+ }
+
+ return !user_manager::UserManager::Get()->GetOwnerEmail().empty();
}
-void AppLaunchController::OnInitializingTokenService() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE);
+bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() {
+ if (need_owner_auth_to_configure_network_callback_)
+ return need_owner_auth_to_configure_network_callback_->Run();
+
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()->browser_policy_connector_chromeos();
+ return !connector->IsEnterpriseManaged();
}
-void AppLaunchController::OnInitializingNetwork() {
- app_launch_splash_screen_actor_->UpdateAppLaunchState(
- AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
+void AppLaunchController::MaybeShowNetworkConfigureUI() {
+ if (CanConfigureNetwork()) {
+ if (NeedOwnerAuthToConfigureNetwork()) {
+ if (network_config_requested_)
+ OnConfigureNetwork();
+ else
+ 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);
+ }
+}
- // Show the network configration dialog if network is not initialized
+void AppLaunchController::InitializeNetwork() {
+ // Show the network configuration dialog if network is not initialized
// after a brief wait time.
waiting_for_network_ = true;
network_wait_timer_.Start(
FROM_HERE,
base::TimeDelta::FromSeconds(network_wait_time_),
this, &AppLaunchController::OnNetworkWaitTimedout);
+
+ app_launch_splash_screen_actor_->UpdateAppLaunchState(
+ AppLaunchSplashScreenActor::APP_LAUNCH_STATE_PREPARING_NETWORK);
+}
+
+bool AppLaunchController::IsNetworkReady() {
+ return app_launch_splash_screen_actor_->IsNetworkReady();
+}
+
+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);
void AppLaunchController::OnReadyToLaunch() {
launcher_ready_ = true;
+
+ if (network_config_requested_)
+ return;
+
if (!webui_visible_)
return;
+ if (splash_wait_timer_.IsRunning())
+ return;
+
const int64 time_taken_ms = (base::TimeTicks::Now() -
base::TimeTicks::FromInternalValue(launch_splash_start_time_)).
InMilliseconds();
// Enforce that we show app install splash screen for some minimum amount
// of time.
if (!skip_splash_wait_ && time_taken_ms < kAppInstallSplashScreenMinTimeMS) {
- content::BrowserThread::PostDelayedTask(
- content::BrowserThread::UI,
+ splash_wait_timer_.Start(
FROM_HERE,
- base::Bind(&AppLaunchController::OnReadyToLaunch, AsWeakPtr()),
base::TimeDelta::FromMilliseconds(
- kAppInstallSplashScreenMinTimeMS - time_taken_ms));
+ kAppInstallSplashScreenMinTimeMS - time_taken_ms),
+ this,
+ &AppLaunchController::OnReadyToLaunch);
return;
}
AppLaunchSplashScreenActor::APP_LAUNCH_STATE_WAITING_APP_WINDOW);
DCHECK(!app_window_watcher_);
- app_window_watcher_.reset(new AppWindowWatcher(this));
+ app_window_watcher_.reset(new AppWindowWatcher(this, app_id_));
}
void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
- LOG(ERROR) << "Kiosk launch failed. Will now shut down.";
+ LOG(ERROR) << "Kiosk launch failed. Will now shut down."
+ << ", error=" << error;
DCHECK_NE(KioskAppLaunchError::NONE, error);
// Saves the error and ends the session to go back to login screen.
CleanUp();
}
+bool AppLaunchController::IsShowingNetworkConfigScreen() {
+ return network_config_requested_;
+}
+
} // namespace chromeos