Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / app_launch_controller.cc
index ecaf9ae..32263f6 100644 (file)
@@ -4,27 +4,35 @@
 
 #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 {
@@ -40,38 +48,55 @@ 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
 
 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);
 };
@@ -80,23 +105,23 @@ class AppLaunchController::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() {
@@ -117,33 +142,48 @@ void AppLaunchController::StartAppLaunch() {
   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
@@ -155,12 +195,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 +218,34 @@ void AppLaunchController::OnCancelAppLaunch() {
   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();
 }
 
@@ -201,6 +257,7 @@ void AppLaunchController::OnProfileLoadFailed(
 void AppLaunchController::CleanUp() {
   kiosk_profile_loader_.reset();
   startup_app_launcher_.reset();
+  splash_wait_timer_.Stop();
 
   if (host_)
     host_->Finalize();
@@ -212,12 +269,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,36 +284,81 @@ bool AppLaunchController::CanConfigureNetwork() {
   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);
 
@@ -276,9 +373,16 @@ void AppLaunchController::OnInstallingApp() {
 
 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();
@@ -286,12 +390,12 @@ void AppLaunchController::OnReadyToLaunch() {
   // 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;
   }
 
@@ -304,11 +408,12 @@ void AppLaunchController::OnLaunchSucceeded() {
       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.
@@ -317,4 +422,8 @@ void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
   CleanUp();
 }
 
+bool AppLaunchController::IsShowingNetworkConfigScreen() {
+  return network_config_requested_;
+}
+
 }   // namespace chromeos