| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h" | 5 #include "chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| 11 #include "chrome/browser/chromeos/camera_detector.h" | |
| 12 #include "chrome/browser/chromeos/login/default_user_images.h" | 11 #include "chrome/browser/chromeos/login/default_user_images.h" |
| 13 #include "chrome/browser/chromeos/login/user.h" | 12 #include "chrome/browser/chromeos/login/user.h" |
| 14 #include "chrome/browser/chromeos/login/webui_login_display.h" | 13 #include "chrome/browser/chromeos/login/webui_login_display.h" |
| 15 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" | 14 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" |
| 16 #include "chrome/common/chrome_switches.h" | 15 #include "chrome/common/chrome_switches.h" |
| 17 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
| 18 #include "content/public/browser/browser_thread.h" | |
| 19 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
| 20 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 21 #include "net/base/data_url.h" | 19 #include "net/base/data_url.h" |
| 22 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
| 23 #include "ui/views/widget/widget.h" | 21 #include "ui/views/widget/widget.h" |
| 24 #include "ui/webui/web_ui_util.h" | |
| 25 | |
| 26 using content::BrowserThread; | |
| 27 | 22 |
| 28 namespace chromeos { | 23 namespace chromeos { |
| 29 | 24 |
| 30 UserImageScreenHandler::UserImageScreenHandler() | 25 UserImageScreenHandler::UserImageScreenHandler() |
| 31 : screen_(NULL), | 26 : screen_(NULL), |
| 32 show_on_init_(false), | 27 show_on_init_(false) { |
| 33 selected_image_(User::kInvalidImageIndex), | |
| 34 accept_photo_after_decoding_(false), | |
| 35 user_photo_data_url_(chrome::kAboutBlankURL), | |
| 36 profile_picture_data_url_(chrome::kAboutBlankURL), | |
| 37 profile_picture_absent_(false), | |
| 38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | |
| 39 } | 28 } |
| 40 | 29 |
| 41 UserImageScreenHandler::~UserImageScreenHandler() { | 30 UserImageScreenHandler::~UserImageScreenHandler() { |
| 42 if (screen_) | 31 if (screen_) |
| 43 screen_->OnActorDestroyed(this); | 32 screen_->OnActorDestroyed(this); |
| 44 if (image_decoder_.get()) | |
| 45 image_decoder_->set_delegate(NULL); | |
| 46 } | |
| 47 | |
| 48 void UserImageScreenHandler::DeclareLocalizedValues( | |
| 49 LocalizedValuesBuilder* builder) { | |
| 50 // TODO(ivankr): string should be renamed to something like | |
| 51 // IDS_USER_IMAGE_SCREEN_TITLE (currently used for Take Photo dialog). | |
| 52 builder->Add("userImageScreenTitle", IDS_OOBE_PICTURE); | |
| 53 builder->Add("userImageScreenDescription", | |
| 54 IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT); | |
| 55 builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO); | |
| 56 builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO); | |
| 57 builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO); | |
| 58 builder->Add("profilePhoto", IDS_IMAGE_SCREEN_PROFILE_PHOTO); | |
| 59 builder->Add("profilePhotoLoading", | |
| 60 IDS_IMAGE_SCREEN_PROFILE_LOADING_PHOTO); | |
| 61 builder->Add("okButtonText", IDS_OK); | |
| 62 builder->Add("authorCredit", IDS_OPTIONS_SET_WALLPAPER_AUTHOR_TEXT); | |
| 63 builder->Add("photoFromCamera", IDS_OPTIONS_CHANGE_PICTURE_PHOTO_FROM_CAMERA); | |
| 64 builder->Add("photoCaptureAccessibleText", | |
| 65 IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT); | |
| 66 builder->Add("photoDiscardAccessibleText", | |
| 67 IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT); | |
| 68 } | 33 } |
| 69 | 34 |
| 70 void UserImageScreenHandler::Initialize() { | 35 void UserImageScreenHandler::Initialize() { |
| 71 if (show_on_init_) { | 36 if (show_on_init_) { |
| 72 Show(); | 37 Show(); |
| 73 show_on_init_ = false; | 38 show_on_init_ = false; |
| 74 } | 39 } |
| 75 } | 40 } |
| 76 | 41 |
| 77 void UserImageScreenHandler::SetDelegate( | 42 void UserImageScreenHandler::SetDelegate( |
| 78 UserImageScreenActor::Delegate* screen) { | 43 UserImageScreenActor::Delegate* screen) { |
| 79 screen_ = screen; | 44 screen_ = screen; |
| 80 } | 45 } |
| 81 | 46 |
| 82 void UserImageScreenHandler::Show() { | 47 void UserImageScreenHandler::Show() { |
| 83 if (!page_is_ready()) { | 48 if (!page_is_ready()) { |
| 84 show_on_init_ = true; | 49 show_on_init_ = true; |
| 85 return; | 50 return; |
| 86 } | 51 } |
| 87 screen_show_time_ = base::Time::Now(); | 52 screen_show_time_ = base::Time::Now(); |
| 88 ShowScreen(OobeUI::kScreenUserImagePicker, NULL); | 53 ShowScreen(OobeUI::kScreenUserImagePicker, NULL); |
| 89 | 54 |
| 90 // When shown, query camera presence. | 55 // When shown, query camera presence. |
| 91 CheckCameraPresence(); | 56 if (!screen_) |
| 57 return; |
| 58 screen_->CheckCameraPresence(); |
| 92 } | 59 } |
| 93 | 60 |
| 94 void UserImageScreenHandler::Hide() { | 61 void UserImageScreenHandler::Hide() { |
| 95 } | 62 } |
| 96 | 63 |
| 97 void UserImageScreenHandler::PrepareToShow() { | 64 void UserImageScreenHandler::PrepareToShow() { |
| 98 } | 65 } |
| 99 | 66 |
| 100 void UserImageScreenHandler::SelectImage(int index) { | 67 void UserImageScreenHandler::DeclareLocalizedValues( |
| 101 selected_image_ = index; | 68 LocalizedValuesBuilder* builder) { |
| 102 if (page_is_ready()) { | 69 // TODO(ivankr): string should be renamed to something like |
| 103 base::StringValue image_url(GetDefaultImageUrl(index)); | 70 // IDS_USER_IMAGE_SCREEN_TITLE (currently used for Take Photo dialog). |
| 104 CallJS("oobe.UserImageScreen.setSelectedImage", | 71 builder->Add("userImageScreenTitle", IDS_OOBE_PICTURE); |
| 105 image_url); | 72 builder->Add("userImageScreenDescription", |
| 106 } | 73 IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT); |
| 107 } | 74 builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO); |
| 108 | 75 builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO); |
| 109 void UserImageScreenHandler::CheckCameraPresence() { | 76 builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO); |
| 110 CameraDetector::StartPresenceCheck( | 77 builder->Add("profilePhoto", IDS_IMAGE_SCREEN_PROFILE_PHOTO); |
| 111 base::Bind(&UserImageScreenHandler::OnCameraPresenceCheckDone, | 78 builder->Add("profilePhotoLoading", |
| 112 weak_factory_.GetWeakPtr())); | 79 IDS_IMAGE_SCREEN_PROFILE_LOADING_PHOTO); |
| 80 builder->Add("okButtonText", IDS_OK); |
| 81 builder->Add("authorCredit", IDS_OPTIONS_SET_WALLPAPER_AUTHOR_TEXT); |
| 82 builder->Add("photoFromCamera", IDS_OPTIONS_CHANGE_PICTURE_PHOTO_FROM_CAMERA); |
| 83 builder->Add("photoCaptureAccessibleText", |
| 84 IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT); |
| 85 builder->Add("photoDiscardAccessibleText", |
| 86 IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT); |
| 113 } | 87 } |
| 114 | 88 |
| 115 void UserImageScreenHandler::RegisterMessages() { | 89 void UserImageScreenHandler::RegisterMessages() { |
| 116 AddCallback("getImages", &UserImageScreenHandler::HandleGetImages); | 90 AddCallback("getImages", &UserImageScreenHandler::HandleGetImages); |
| 117 AddCallback("photoTaken", &UserImageScreenHandler::HandlePhotoTaken); | 91 AddCallback("photoTaken", &UserImageScreenHandler::HandlePhotoTaken); |
| 118 AddCallback("selectImage", &UserImageScreenHandler::HandleSelectImage); | 92 AddCallback("selectImage", &UserImageScreenHandler::HandleSelectImage); |
| 119 AddCallback("checkCameraPresence", | 93 AddCallback("checkCameraPresence", |
| 120 &UserImageScreenHandler::HandleCheckCameraPresence); | 94 &UserImageScreenHandler::HandleCheckCameraPresence); |
| 121 AddCallback("onUserImageAccepted", | 95 AddCallback("onUserImageAccepted", |
| 122 &UserImageScreenHandler::HandleImageAccepted); | 96 &UserImageScreenHandler::HandleImageAccepted); |
| 123 AddCallback("onUserImageScreenShown", | 97 AddCallback("onUserImageScreenShown", |
| 124 &UserImageScreenHandler::HandleScreenShown); | 98 &UserImageScreenHandler::HandleScreenShown); |
| 125 } | 99 } |
| 126 | 100 |
| 127 void UserImageScreenHandler::AddProfileImage(const gfx::ImageSkia& image) { | 101 void UserImageScreenHandler::SelectImage(int index) { |
| 128 profile_picture_data_url_ = webui::GetBitmapDataUrl(*image.bitmap()); | 102 if (page_is_ready()) { |
| 129 SendProfileImage(profile_picture_data_url_); | 103 CallJS("oobe.UserImageScreen.setSelectedImage", GetDefaultImageUrl(index)); |
| 104 } |
| 130 } | 105 } |
| 131 | 106 |
| 132 void UserImageScreenHandler::SendProfileImage(const std::string& data_url) { | 107 void UserImageScreenHandler::SendProfileImage(const std::string& data_url) { |
| 133 if (page_is_ready()) { | 108 if (page_is_ready()) { |
| 134 base::StringValue data_url_value(data_url); | 109 CallJS("oobe.UserImageScreen.setProfileImage", data_url); |
| 135 CallJS("oobe.UserImageScreen.setProfileImage", data_url_value); | |
| 136 } | 110 } |
| 137 } | 111 } |
| 138 | 112 |
| 139 void UserImageScreenHandler::OnProfileImageAbsent() { | 113 void UserImageScreenHandler::OnProfileImageAbsent() { |
| 140 profile_picture_absent_ = true; | |
| 141 if (page_is_ready()) { | 114 if (page_is_ready()) { |
| 142 scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); | 115 scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); |
| 143 CallJS("oobe.UserImageScreen.setProfileImage", *null_value); | 116 CallJS("oobe.UserImageScreen.setProfileImage", *null_value); |
| 144 } | 117 } |
| 145 } | 118 } |
| 146 | 119 |
| 120 // TODO(antrim) : It looks more like parameters for "Init" rather than callback. |
| 147 void UserImageScreenHandler::HandleGetImages() { | 121 void UserImageScreenHandler::HandleGetImages() { |
| 148 base::ListValue image_urls; | 122 base::ListValue image_urls; |
| 149 for (int i = kFirstDefaultImageIndex; i < kDefaultImagesCount; ++i) { | 123 for (int i = kFirstDefaultImageIndex; i < kDefaultImagesCount; ++i) { |
| 150 scoped_ptr<base::DictionaryValue> image_data(new base::DictionaryValue); | 124 scoped_ptr<base::DictionaryValue> image_data(new base::DictionaryValue); |
| 151 image_data->SetString("url", GetDefaultImageUrl(i)); | 125 image_data->SetString("url", GetDefaultImageUrl(i)); |
| 152 image_data->SetString( | 126 image_data->SetString( |
| 153 "author", l10n_util::GetStringUTF16(kDefaultImageAuthorIDs[i])); | 127 "author", l10n_util::GetStringUTF16(kDefaultImageAuthorIDs[i])); |
| 154 image_data->SetString( | 128 image_data->SetString( |
| 155 "website", l10n_util::GetStringUTF16(kDefaultImageWebsiteIDs[i])); | 129 "website", l10n_util::GetStringUTF16(kDefaultImageWebsiteIDs[i])); |
| 156 image_data->SetString("title", GetDefaultImageDescription(i)); | 130 image_data->SetString("title", GetDefaultImageDescription(i)); |
| 157 image_urls.Append(image_data.release()); | 131 image_urls.Append(image_data.release()); |
| 158 } | 132 } |
| 159 CallJS("oobe.UserImageScreen.setDefaultImages", image_urls); | 133 CallJS("oobe.UserImageScreen.setDefaultImages", image_urls); |
| 134 if (!screen_) |
| 135 return; |
| 136 if (screen_->selected_image() != User::kInvalidImageIndex) |
| 137 SelectImage(screen_->selected_image()); |
| 160 | 138 |
| 161 if (selected_image_ != User::kInvalidImageIndex) | 139 if (screen_->profile_picture_data_url() != chrome::kAboutBlankURL) |
| 162 SelectImage(selected_image_); | 140 SendProfileImage(screen_->profile_picture_data_url()); |
| 163 | 141 else if (screen_->profile_picture_absent()) |
| 164 if (profile_picture_data_url_ != chrome::kAboutBlankURL) | |
| 165 SendProfileImage(profile_picture_data_url_); | |
| 166 else if (profile_picture_absent_) | |
| 167 OnProfileImageAbsent(); | 142 OnProfileImageAbsent(); |
| 168 } | 143 } |
| 169 | 144 |
| 170 void UserImageScreenHandler::HandlePhotoTaken(const std::string& image_url) { | 145 void UserImageScreenHandler::HandlePhotoTaken(const std::string& image_url) { |
| 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 172 std::string mime_type, charset, raw_data; | 146 std::string mime_type, charset, raw_data; |
| 173 if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data)) | 147 if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data)) |
| 174 NOTREACHED(); | 148 NOTREACHED(); |
| 175 DCHECK_EQ("image/png", mime_type); | 149 DCHECK_EQ("image/png", mime_type); |
| 176 | 150 |
| 177 user_photo_ = gfx::ImageSkia(); | 151 if (screen_) |
| 178 user_photo_data_url_ = image_url; | 152 screen_->OnPhotoTaken(raw_data); |
| 179 | |
| 180 if (image_decoder_.get()) | |
| 181 image_decoder_->set_delegate(NULL); | |
| 182 image_decoder_ = new ImageDecoder(this, raw_data, | |
| 183 ImageDecoder::DEFAULT_CODEC); | |
| 184 scoped_refptr<base::MessageLoopProxy> task_runner = | |
| 185 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); | |
| 186 image_decoder_->Start(task_runner); | |
| 187 } | 153 } |
| 188 | 154 |
| 189 void UserImageScreenHandler::HandleCheckCameraPresence() { | 155 void UserImageScreenHandler::HandleCheckCameraPresence() { |
| 190 CheckCameraPresence(); | 156 if (!screen_) |
| 157 return; |
| 158 screen_->CheckCameraPresence(); |
| 191 } | 159 } |
| 192 | 160 |
| 193 void UserImageScreenHandler::HandleSelectImage(const std::string& image_url, | 161 void UserImageScreenHandler::HandleSelectImage(const std::string& image_url, |
| 194 const std::string& image_type) { | 162 const std::string& image_type) { |
| 195 if (image_url.empty()) | 163 if (screen_) |
| 196 return; | 164 screen_->OnImageSelected(image_type, image_url); |
| 197 | |
| 198 int user_image_index = User::kInvalidImageIndex; | |
| 199 if (image_type == "default" && | |
| 200 IsDefaultImageUrl(image_url, &user_image_index)) { | |
| 201 selected_image_ = user_image_index; | |
| 202 } else if (image_type == "camera") { | |
| 203 selected_image_ = User::kExternalImageIndex; | |
| 204 } else if (image_type == "profile") { | |
| 205 selected_image_ = User::kProfileImageIndex; | |
| 206 } else { | |
| 207 NOTREACHED() << "Unexpected image type: " << image_type; | |
| 208 } | |
| 209 } | 165 } |
| 210 | 166 |
| 211 void UserImageScreenHandler::HandleImageAccepted() { | 167 void UserImageScreenHandler::HandleImageAccepted() { |
| 212 if (!screen_) | 168 if (screen_) |
| 213 return; | 169 screen_->OnImageAccepted(); |
| 214 switch (selected_image_) { | |
| 215 case User::kExternalImageIndex: | |
| 216 // Photo decoding may not have been finished yet. | |
| 217 if (user_photo_.isNull()) | |
| 218 accept_photo_after_decoding_ = true; | |
| 219 else | |
| 220 screen_->OnPhotoTaken(user_photo_); | |
| 221 break; | |
| 222 | |
| 223 case User::kProfileImageIndex: | |
| 224 screen_->OnProfileImageSelected(); | |
| 225 break; | |
| 226 | |
| 227 default: | |
| 228 DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount); | |
| 229 screen_->OnDefaultImageSelected(selected_image_); | |
| 230 } | |
| 231 } | 170 } |
| 232 | 171 |
| 233 void UserImageScreenHandler::HandleScreenShown() { | 172 void UserImageScreenHandler::HandleScreenShown() { |
| 234 DCHECK(!screen_show_time_.is_null()); | 173 DCHECK(!screen_show_time_.is_null()); |
| 235 | 174 |
| 236 base::TimeDelta delta = base::Time::Now() - screen_show_time_; | 175 base::TimeDelta delta = base::Time::Now() - screen_show_time_; |
| 237 VLOG(1) << "Screen load time: " << delta.InSecondsF(); | 176 VLOG(1) << "Screen load time: " << delta.InSecondsF(); |
| 238 UMA_HISTOGRAM_TIMES("UserImage.ScreenIsShownTime", delta); | 177 UMA_HISTOGRAM_TIMES("UserImage.ScreenIsShownTime", delta); |
| 239 } | 178 } |
| 240 | 179 |
| 241 void UserImageScreenHandler::OnCameraPresenceCheckDone() { | 180 void UserImageScreenHandler::SetCameraPresent(bool present) { |
| 242 base::FundamentalValue present_value( | 181 CallJS("oobe.UserImageScreen.setCameraPresent", present); |
| 243 CameraDetector::camera_presence() == CameraDetector::kCameraPresent); | |
| 244 CallJS("oobe.UserImageScreen.setCameraPresent", present_value); | |
| 245 } | |
| 246 | |
| 247 void UserImageScreenHandler::OnImageDecoded(const ImageDecoder* decoder, | |
| 248 const SkBitmap& decoded_image) { | |
| 249 DCHECK_EQ(image_decoder_.get(), decoder); | |
| 250 user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image); | |
| 251 if (screen_ && accept_photo_after_decoding_) | |
| 252 screen_->OnPhotoTaken(user_photo_); | |
| 253 } | |
| 254 | |
| 255 void UserImageScreenHandler::OnDecodeImageFailed(const ImageDecoder* decoder) { | |
| 256 NOTREACHED() << "Failed to decode PNG image from WebUI"; | |
| 257 } | 182 } |
| 258 | 183 |
| 259 void UserImageScreenHandler::SetProfilePictureEnabled(bool enabled) { | 184 void UserImageScreenHandler::SetProfilePictureEnabled(bool enabled) { |
| 260 base::FundamentalValue present_value(enabled); | 185 CallJS("oobe.UserImageScreen.setProfilePictureEnabled", enabled); |
| 261 CallJS("oobe.UserImageScreen.setProfilePictureEnabled", present_value); | |
| 262 } | 186 } |
| 263 | 187 |
| 264 } // namespace chromeos | 188 } // namespace chromeos |
| OLD | NEW |