user_image_screen.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2010 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/login/user_image_screen.h"
6
7#include "base/compiler_specific.h"
8#include "base/threading/thread_restrictions.h"
9#include "base/time.h"
10#include "chrome/browser/chromeos/login/login_utils.h"
11#include "chrome/browser/chromeos/login/screen_observer.h"
12#include "chrome/browser/chromeos/login/user_image_downloader.h"
13#include "chrome/browser/chromeos/login/user_image_view.h"
14#include "chrome/browser/chromeos/login/user_manager.h"
15#include "chrome/common/notification_service.h"
16#include "chrome/common/notification_type.h"
17#include "grit/theme_resources.h"
18#include "ui/base/resource/resource_bundle.h"
19
20namespace chromeos {
21
22namespace {
23
24// The resolution of the picture we want to get from the camera.
25const int kFrameWidth = 480;
26const int kFrameHeight = 480;
27
28// Maximum number of capture failures we ignore before we try to initialize
29// the camera again.
30const int kMaxCaptureFailureCounter = 5;
31
32// Maximum number of camera initialization retries.
33const int kMaxCameraInitFailureCounter = 3;
34
35// Name for camera thread.
36const char kCameraThreadName[] = "Chrome_CameraThread";
37
38}  // namespace
39
40UserImageScreen::UserImageScreen(WizardScreenDelegate* delegate)
41    : ViewScreen<UserImageView>(delegate),
42      capture_failure_counter_(0),
43      camera_init_failure_counter_(0) {
44  camera_thread_.reset(new base::Thread(kCameraThreadName));
45  registrar_.Add(
46      this,
47      NotificationType::SCREEN_LOCK_STATE_CHANGED,
48      NotificationService::AllSources());
49}
50
51UserImageScreen::~UserImageScreen() {
52  if (camera_.get())
53    camera_->set_delegate(NULL);
54  {
55    // A ScopedAllowIO object is required to join the thread when calling Stop.
56    // See http://crosbug.com/11392.
57    base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
58    camera_thread_.reset();
59  }
60}
61
62void UserImageScreen::Refresh() {
63  camera_thread_->Start();
64  camera_ = new Camera(this, camera_thread_.get(), true);
65  InitCamera();
66}
67
68void UserImageScreen::Hide() {
69  if (camera_.get())
70    camera_->StopCapturing();
71  ViewScreen<UserImageView>::Hide();
72}
73
74UserImageView* UserImageScreen::AllocateView() {
75  return new UserImageView(this);
76}
77
78void UserImageScreen::OnInitializeSuccess() {
79  if (camera_.get())
80    camera_->StartCapturing();
81}
82
83void UserImageScreen::OnInitializeFailure() {
84  ++camera_init_failure_counter_;
85  if (camera_init_failure_counter_ > kMaxCameraInitFailureCounter) {
86    if (view())
87      view()->ShowCameraError();
88    return;
89  }
90  // Retry initializing the camera.
91  if (camera_.get()) {
92    camera_->Uninitialize();
93    InitCamera();
94  }
95}
96
97void UserImageScreen::OnStartCapturingSuccess() {
98}
99
100void UserImageScreen::OnStartCapturingFailure() {
101  // Try to reinitialize camera.
102  OnInitializeFailure();
103}
104
105void UserImageScreen::OnCaptureSuccess() {
106  capture_failure_counter_ = 0;
107  camera_init_failure_counter_ = 0;
108  if (view() && camera_.get()) {
109    SkBitmap frame;
110    camera_->GetFrame(&frame);
111    if (!frame.isNull())
112      view()->UpdateVideoFrame(frame);
113  }
114}
115
116void UserImageScreen::OnCaptureFailure() {
117  ++capture_failure_counter_;
118  if (capture_failure_counter_ < kMaxCaptureFailureCounter)
119    return;
120
121  capture_failure_counter_ = 0;
122  OnInitializeFailure();
123}
124
125void UserImageScreen::OnOK(const SkBitmap& image) {
126  if (camera_.get())
127    camera_->Uninitialize();
128  UserManager* user_manager = UserManager::Get();
129  DCHECK(user_manager);
130
131  const UserManager::User& user = user_manager->logged_in_user();
132  DCHECK(!user.email().empty());
133
134  user_manager->SetLoggedInUserImage(image);
135  user_manager->SaveUserImage(user.email(), image);
136  if (delegate())
137    delegate()->GetObserver(this)->OnExit(ScreenObserver::USER_IMAGE_SELECTED);
138}
139
140void UserImageScreen::OnSkip() {
141  if (camera_.get())
142    camera_->Uninitialize();
143  if (delegate())
144    delegate()->GetObserver(this)->OnExit(ScreenObserver::USER_IMAGE_SKIPPED);
145}
146
147void UserImageScreen::Observe(NotificationType type,
148                              const NotificationSource& source,
149                              const NotificationDetails& details) {
150  if (type != NotificationType::SCREEN_LOCK_STATE_CHANGED ||
151      !camera_.get())
152    return;
153
154  bool is_screen_locked = *Details<bool>(details).ptr();
155  if (is_screen_locked)
156    camera_->Uninitialize();
157  else
158    InitCamera();
159}
160
161void UserImageScreen::InitCamera() {
162  if (view())
163    view()->ShowCameraInitializing();
164  camera_->Initialize(kFrameWidth, kFrameHeight);
165}
166
167}  // namespace chromeos
168
169