Roll src/third_party/WebKit 8b42d1d:744641d (svn 186770:186771)
[chromium-blink-merge.git] / chrome / browser / chromeos / kiosk_mode / kiosk_mode_screensaver.cc
blob158eef314628167b13b0ce5ddafe6ecc8881970d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.h"
7 #include "ash/screensaver/screensaver_view.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
15 #include "chrome/browser/chromeos/login/existing_user_controller.h"
16 #include "chrome/browser/chromeos/login/signin_specifics.h"
17 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
18 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
19 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/browser/extensions/extension_garbage_collector_chromeos.h"
22 #include "chrome/browser/extensions/extension_service.h"
23 #include "chrome/browser/extensions/sandboxed_unpacker.h"
24 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
25 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
26 #include "chromeos/login/auth/user_context.h"
27 #include "chromeos/login/login_state.h"
28 #include "chromeos/login/user_names.h"
29 #include "components/user_manager/user_type.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/notification_service.h"
32 #include "extensions/browser/extension_system.h"
33 #include "extensions/common/extension.h"
34 #include "extensions/common/file_util.h"
35 #include "ui/wm/core/user_activity_detector.h"
37 using extensions::Extension;
38 using extensions::ExtensionGarbageCollectorChromeOS;
39 using extensions::SandboxedUnpacker;
41 namespace chromeos {
43 namespace {
45 ExtensionService* GetDefaultExtensionService() {
46 Profile* default_profile = ProfileHelper::GetSigninProfile();
47 if (!default_profile)
48 return NULL;
49 return extensions::ExtensionSystem::Get(
50 default_profile)->extension_service();
53 ExtensionGarbageCollectorChromeOS* GetDefaultExtensionGarbageCollector() {
54 Profile* default_profile = ProfileHelper::GetSigninProfile();
55 if (!default_profile)
56 return NULL;
57 return ExtensionGarbageCollectorChromeOS::Get(default_profile);
60 typedef base::Callback<void(
61 scoped_refptr<Extension>,
62 const base::FilePath&)> UnpackCallback;
64 class ScreensaverUnpackerClient
65 : public extensions::SandboxedUnpackerClient {
66 public:
67 ScreensaverUnpackerClient(const base::FilePath& crx_path,
68 const UnpackCallback& unpacker_callback)
69 : crx_path_(crx_path),
70 unpack_callback_(unpacker_callback) {}
72 virtual void OnUnpackSuccess(const base::FilePath& temp_dir,
73 const base::FilePath& extension_root,
74 const base::DictionaryValue* original_manifest,
75 const Extension* extension,
76 const SkBitmap& install_icon) override;
77 virtual void OnUnpackFailure(const base::string16& error) override;
79 protected:
80 virtual ~ScreensaverUnpackerClient() {}
82 private:
83 void LoadScreensaverExtension(
84 const base::FilePath& extension_base_path,
85 const base::FilePath& screensaver_extension_path);
87 void NotifyAppPackOfDamagedFile();
89 base::FilePath crx_path_;
90 UnpackCallback unpack_callback_;
92 DISALLOW_COPY_AND_ASSIGN(ScreensaverUnpackerClient);
95 void ScreensaverUnpackerClient::OnUnpackSuccess(
96 const base::FilePath& temp_dir,
97 const base::FilePath& extension_root,
98 const base::DictionaryValue* original_manifest,
99 const Extension* extension,
100 const SkBitmap& install_icon) {
101 content::BrowserThread::PostTask(
102 content::BrowserThread::FILE,
103 FROM_HERE,
104 base::Bind(&ScreensaverUnpackerClient::LoadScreensaverExtension,
105 this,
106 temp_dir,
107 extension_root));
110 void ScreensaverUnpackerClient::OnUnpackFailure(const base::string16& error) {
111 LOG(ERROR) << "Couldn't unpack screensaver extension. Error: " << error;
112 NotifyAppPackOfDamagedFile();
115 void ScreensaverUnpackerClient::LoadScreensaverExtension(
116 const base::FilePath& extension_base_path,
117 const base::FilePath& screensaver_extension_path) {
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
120 // TODO(rkc): This is a HACK, please remove this method from extension
121 // service once this code is deprecated. See crbug.com/280363
122 ExtensionGarbageCollectorChromeOS* gc = GetDefaultExtensionGarbageCollector();
123 if (gc)
124 gc->disable_garbage_collection();
126 std::string error;
127 scoped_refptr<Extension> screensaver_extension =
128 extensions::file_util::LoadExtension(screensaver_extension_path,
129 extensions::Manifest::COMPONENT,
130 Extension::NO_FLAGS,
131 &error);
132 if (!screensaver_extension.get()) {
133 LOG(ERROR) << "Could not load screensaver extension from: "
134 << screensaver_extension_path.value() << " due to: " << error;
135 NotifyAppPackOfDamagedFile();
136 return;
139 content::BrowserThread::PostTask(
140 content::BrowserThread::UI,
141 FROM_HERE,
142 base::Bind(
143 unpack_callback_,
144 screensaver_extension,
145 extension_base_path));
148 void ScreensaverUnpackerClient::NotifyAppPackOfDamagedFile() {
149 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
150 content::BrowserThread::PostTask(
151 content::BrowserThread::UI, FROM_HERE,
152 base::Bind(&ScreensaverUnpackerClient::NotifyAppPackOfDamagedFile,
153 this));
154 return;
157 policy::BrowserPolicyConnectorChromeOS* connector =
158 g_browser_process->platform_part()->browser_policy_connector_chromeos();
159 policy::AppPackUpdater* updater = connector->GetAppPackUpdater();
160 if (updater)
161 updater->OnDamagedFileDetected(crx_path_);
164 } // namespace
166 KioskModeScreensaver::KioskModeScreensaver()
167 : weak_ptr_factory_(this) {
168 chromeos::KioskModeSettings* kiosk_mode_settings =
169 chromeos::KioskModeSettings::Get();
171 if (kiosk_mode_settings->is_initialized()) {
172 GetScreensaverCrxPath();
173 } else {
174 kiosk_mode_settings->Initialize(base::Bind(
175 &KioskModeScreensaver::GetScreensaverCrxPath,
176 weak_ptr_factory_.GetWeakPtr()));
180 KioskModeScreensaver::~KioskModeScreensaver() {
181 // If we are shutting down the system might already be gone and we shouldn't
182 // do anything (see crbug.com/288216).
183 if (!g_browser_process || g_browser_process->IsShuttingDown())
184 return;
186 // If the extension was unpacked.
187 if (!extension_base_path_.empty()) {
188 // TODO(rkc): This is a HACK, please remove this method from extension
189 // service once this code is deprecated. See crbug.com/280363
190 ExtensionGarbageCollectorChromeOS* gc =
191 GetDefaultExtensionGarbageCollector();
192 if (gc)
193 gc->enable_garbage_collection();
195 // Delete it.
196 content::BrowserThread::PostTask(
197 content::BrowserThread::FILE,
198 FROM_HERE,
199 base::Bind(
200 &extensions::file_util::DeleteFile, extension_base_path_, true));
203 // In case we're shutting down without ever triggering the active
204 // notification and/or logging in.
205 wm::UserActivityDetector* user_activity_detector =
206 wm::UserActivityDetector::Get();
207 if (user_activity_detector && user_activity_detector->HasObserver(this))
208 user_activity_detector->RemoveObserver(this);
211 void KioskModeScreensaver::GetScreensaverCrxPath() {
212 chromeos::KioskModeSettings::Get()->GetScreensaverPath(
213 base::Bind(&KioskModeScreensaver::ScreensaverPathCallback,
214 weak_ptr_factory_.GetWeakPtr()));
217 void KioskModeScreensaver::ScreensaverPathCallback(
218 const base::FilePath& screensaver_crx) {
219 if (screensaver_crx.empty())
220 return;
222 ExtensionService* extension_service = GetDefaultExtensionService();
223 if (!extension_service)
224 return;
225 base::FilePath extensions_dir = extension_service->install_directory();
226 scoped_refptr<SandboxedUnpacker> screensaver_unpacker(
227 new SandboxedUnpacker(
228 screensaver_crx,
229 extensions::Manifest::COMPONENT,
230 Extension::NO_FLAGS,
231 extensions_dir,
232 content::BrowserThread::GetMessageLoopProxyForThread(
233 content::BrowserThread::FILE).get(),
234 new ScreensaverUnpackerClient(
235 screensaver_crx,
236 base::Bind(
237 &KioskModeScreensaver::SetupScreensaver,
238 weak_ptr_factory_.GetWeakPtr()))));
240 // Fire off the unpacker on the file thread; don't need it to return.
241 content::BrowserThread::PostTask(
242 content::BrowserThread::FILE,
243 FROM_HERE,
244 base::Bind(
245 &SandboxedUnpacker::Start, screensaver_unpacker.get()));
248 void KioskModeScreensaver::SetupScreensaver(
249 scoped_refptr<Extension> extension,
250 const base::FilePath& extension_base_path) {
251 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
252 extension_base_path_ = extension_base_path;
254 // If the user is already logged in, don't need to display the screensaver.
255 if (chromeos::LoginState::Get()->IsUserLoggedIn())
256 return;
258 wm::UserActivityDetector::Get()->AddObserver(this);
260 ExtensionService* extension_service = GetDefaultExtensionService();
261 // Add the extension to the extension service and display the screensaver.
262 if (extension_service) {
263 extension_service->AddExtension(extension.get());
264 ash::ShowScreensaver(
265 extensions::AppLaunchInfo::GetFullLaunchURL(extension.get()));
266 } else {
267 LOG(ERROR) << "Couldn't get extension system. Unable to load screensaver!";
268 ShutdownKioskModeScreensaver();
272 void KioskModeScreensaver::OnUserActivity(const ui::Event* event) {
273 // We don't want to handle further user notifications; we'll either login
274 // the user and close out or or at least close the screensaver.
275 wm::UserActivityDetector::Get()->RemoveObserver(this);
277 // Find the retail mode login page.
278 if (LoginDisplayHostImpl::default_host()) {
279 LoginDisplayHostImpl* webui_host =
280 static_cast<LoginDisplayHostImpl*>(
281 LoginDisplayHostImpl::default_host());
282 OobeUI* oobe_ui = webui_host->GetOobeUI();
284 // Show the login spinner.
285 if (oobe_ui)
286 oobe_ui->ShowRetailModeLoginSpinner();
288 // Close the screensaver, our login spinner is already showing.
289 ash::CloseScreensaver();
291 // Log us in.
292 ExistingUserController* controller =
293 ExistingUserController::current_controller();
294 if (controller && !chromeos::LoginState::Get()->IsUserLoggedIn()) {
295 controller->Login(UserContext(user_manager::USER_TYPE_RETAIL_MODE,
296 chromeos::login::kRetailModeUserName),
297 SigninSpecifics());
299 } else {
300 // No default host for the WebUiLoginDisplay means that we're already in the
301 // process of logging in - shut down screensaver and do nothing else.
302 ash::CloseScreensaver();
305 ShutdownKioskModeScreensaver();
308 static KioskModeScreensaver* g_kiosk_mode_screensaver = NULL;
310 void InitializeKioskModeScreensaver() {
311 if (g_kiosk_mode_screensaver) {
312 LOG(WARNING) << "Screensaver was already initialized";
313 return;
316 g_kiosk_mode_screensaver = new KioskModeScreensaver();
319 void ShutdownKioskModeScreensaver() {
320 delete g_kiosk_mode_screensaver;
321 g_kiosk_mode_screensaver = NULL;
324 } // namespace chromeos