1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/ui/app_launch_view.h" 6 7 #include "ash/shell.h" 8 #include "ash/shell_delegate.h" 9 #include "ash/shell_window_ids.h" 10 #include "base/bind.h" 11 #include "base/logging.h" 12 #include "base/values.h" 13 #include "chrome/browser/ui/webui/chromeos/app_launch_ui.h" 14 #include "chrome/common/url_constants.h" 15 #include "content/public/browser/browser_context.h" 16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/render_widget_host_view.h" 19 #include "content/public/browser/web_contents.h" 20 #include "grit/generated_resources.h" 21 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "ui/aura/root_window.h" 23 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/gfx/screen.h" 25 #include "ui/views/controls/webview/webview.h" 26 #include "ui/views/layout/fill_layout.h" 27 #include "ui/views/widget/widget.h" 28 29 using content::BrowserThread; 30 31 namespace chromeos { 32 33 internal::AppLaunchView* g_instance = NULL; 34 35 void ShowAppLaunchSplashScreen(const std::string& app_id) { 36 // TODO(zelidrag): Come up with a better UI for this purpose. 37 internal::AppLaunchView::ShowAppLaunchSplashScreen(app_id); 38 } 39 40 void UpdateAppLaunchSplashScreenState(AppLaunchState state) { 41 internal::AppLaunchView::UpdateAppLaunchState(state); 42 } 43 44 void CloseAppLaunchSplashScreen() { 45 internal::AppLaunchView::CloseAppLaunchSplashScreen(); 46 } 47 48 namespace internal { 49 50 int GetProgressMessageFromState(AppLaunchState state) { 51 switch (state) { 52 case APP_LAUNCH_STATE_LOADING_AUTH_FILE: 53 case APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE: 54 // TODO(zelidrag): Add better string for this one than "Please wait..." 55 return IDS_SYNC_SETUP_SPINNER_TITLE; 56 case APP_LAUNCH_STATE_PREPARING_NETWORK: 57 return IDS_APP_START_NETWORK_WAIT_MESSAGE; 58 case APP_LAUNCH_STATE_INSTALLING_APPLICATION: 59 return IDS_APP_START_APP_WAIT_MESSAGE; 60 } 61 return IDS_APP_START_NETWORK_WAIT_MESSAGE; 62 } 63 64 // static 65 void AppLaunchView::ShowAppLaunchSplashScreen(const std::string& app_id) { 66 if (!g_instance) { 67 g_instance = new AppLaunchView(app_id); 68 g_instance->Show(); 69 } 70 } 71 72 void AppLaunchView::UpdateAppLaunchState(AppLaunchState state) { 73 if (g_instance) 74 g_instance->UpdateState(state); 75 } 76 77 78 // static 79 void AppLaunchView::CloseAppLaunchSplashScreen() { 80 if (g_instance) { 81 g_instance->GetWidget()->Close(); 82 g_instance = NULL; 83 } 84 } 85 86 //////////////////////////////////////////////////////////////////////////////// 87 // AppLaunchView, views::WidgetDelegateView implementation. 88 views::View* AppLaunchView::GetContentsView() { 89 return this; 90 } 91 92 //////////////////////////////////////////////////////////////////////////////// 93 // AppLaunchView, content::WebContentsObserver implementation. 94 void AppLaunchView::RenderProcessGone( 95 base::TerminationStatus status) { 96 LOG(ERROR) << "Splash screen terminated with status " << status; 97 AppLaunchView::CloseAppLaunchSplashScreen(); 98 } 99 100 //////////////////////////////////////////////////////////////////////////////// 101 // AppLaunchView private methods. 102 AppLaunchView::AppLaunchView(const std::string& app_id) 103 : app_launch_webview_(NULL), 104 container_window_(NULL), 105 app_id_(app_id), 106 state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE), 107 app_launch_ui_(NULL) { 108 } 109 110 AppLaunchView::~AppLaunchView() { 111 } 112 113 void AppLaunchView::Show() { 114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 115 // Add the WebView to our view. 116 AddChildWebContents(); 117 // Initialize container window. 118 InitializeWindow(); 119 // Show the window. 120 ShowWindow(); 121 } 122 123 void AppLaunchView::AddChildWebContents() { 124 content::BrowserContext* context = 125 ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext(); 126 app_launch_webview_ = new views::WebView(context); 127 SetLayoutManager(new views::FillLayout); 128 AddChildView(app_launch_webview_); 129 130 LoadSplashScreen(); 131 content::WebContentsObserver::Observe( 132 app_launch_webview_->GetWebContents()); 133 } 134 135 void AppLaunchView::UpdateState(AppLaunchState state) { 136 if (state == state_) 137 return; 138 139 state_ = state; 140 if (!app_launch_ui_) 141 return; 142 143 app_launch_ui_->SetLaunchText( 144 l10n_util::GetStringUTF8(GetProgressMessageFromState(state_))); 145 } 146 147 void AppLaunchView::LoadSplashScreen() { 148 std::string url = chrome::kChromeUIAppLaunchURL; 149 url += "?app=" + app_id_; 150 151 app_launch_webview_->GetWebContents()->GetController().LoadURL( 152 GURL(url), 153 content::Referrer(), 154 content::PAGE_TRANSITION_AUTO_TOPLEVEL, 155 std::string()); 156 157 app_launch_ui_ = static_cast<AppLaunchUI*>( 158 app_launch_webview_->GetWebContents()->GetWebUI()->GetController()); 159 160 // Use a background with transparency to trigger transparency in Webkit. 161 SkBitmap background; 162 background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); 163 background.allocPixels(); 164 background.eraseARGB(0x00, 0x00, 0x00, 0x00); 165 content::RenderViewHost* host = 166 app_launch_webview_->GetWebContents()->GetRenderViewHost(); 167 host->GetView()->SetBackground(background); 168 } 169 170 void AppLaunchView::InitializeWindow() { 171 DCHECK(!container_window_); 172 aura::RootWindow* root_window = ash::Shell::GetPrimaryRootWindow(); 173 174 // We want to be the fullscreen topmost child of the root window. 175 // There should be nothing ever really that should show up on top of us. 176 container_window_ = new views::Widget(); 177 views::Widget::InitParams params( 178 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 179 params.delegate = this; 180 params.parent = ash::Shell::GetContainer( 181 root_window, 182 ash::internal::kShellWindowId_LockScreenContainer); 183 params.show_state = ui::SHOW_STATE_FULLSCREEN; 184 container_window_->Init(params); 185 } 186 187 void AppLaunchView::ShowWindow() { 188 DCHECK(container_window_); 189 container_window_->Show(); 190 } 191 192 } // namespace internal 193 194 } // namespace chromeos 195