Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: chrome/browser/ui/webui/options2/chromeos/change_picture_options_handler.cc

Issue 10837331: Options: s/options2/options/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: wut Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/ui/webui/options2/chromeos/change_picture_options_handl er.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/metrics/histogram.h"
11 #include "base/path_service.h"
12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/login/camera_detector.h"
16 #include "chrome/browser/chromeos/login/default_user_images.h"
17 #include "chrome/browser/chromeos/login/user_image.h"
18 #include "chrome/browser/chromeos/login/user_manager.h"
19 #include "chrome/browser/chromeos/options/take_photo_dialog.h"
20 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/chrome_select_file_policy.h"
23 #include "chrome/browser/ui/webui/web_ui_util.h"
24 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/url_constants.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/web_ui.h"
30 #include "content/public/common/url_constants.h"
31 #include "googleurl/src/gurl.h"
32 #include "grit/generated_resources.h"
33 #include "grit/theme_resources.h"
34 #include "net/base/data_url.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/views/widget/widget.h"
38
39 namespace chromeos {
40 namespace options {
41
42 namespace {
43
44 // Returns info about extensions for files we support as user images.
45 ui::SelectFileDialog::FileTypeInfo GetUserImageFileTypeInfo() {
46 ui::SelectFileDialog::FileTypeInfo file_type_info;
47 file_type_info.extensions.resize(1);
48
49 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("bmp"));
50
51 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("jpg"));
52 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("jpeg"));
53
54 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("png"));
55
56 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("tif"));
57 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("tiff"));
58
59 file_type_info.extension_description_overrides.resize(1);
60 file_type_info.extension_description_overrides[0] =
61 l10n_util::GetStringUTF16(IDS_IMAGE_FILES);
62
63 return file_type_info;
64 }
65
66 // Time histogram suffix for profile image download.
67 const char kProfileDownloadReason[] = "Preferences";
68
69 } // namespace
70
71 ChangePictureOptionsHandler::ChangePictureOptionsHandler()
72 : previous_image_data_url_(chrome::kAboutBlankURL),
73 previous_image_index_(User::kInvalidImageIndex),
74 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
75 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
76 content::NotificationService::AllSources());
77 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
78 content::NotificationService::AllSources());
79 }
80
81 ChangePictureOptionsHandler::~ChangePictureOptionsHandler() {
82 if (select_file_dialog_.get())
83 select_file_dialog_->ListenerDestroyed();
84 if (image_decoder_.get())
85 image_decoder_->set_delegate(NULL);
86 }
87
88 void ChangePictureOptionsHandler::GetLocalizedValues(
89 DictionaryValue* localized_strings) {
90 DCHECK(localized_strings);
91 localized_strings->SetString("changePicturePage",
92 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TITLE));
93 localized_strings->SetString("changePicturePageDescription",
94 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT));
95 localized_strings->SetString("takePhoto",
96 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO));
97 localized_strings->SetString("chooseFile",
98 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_CHOOSE_FILE));
99 localized_strings->SetString("profilePhoto",
100 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_PROFILE_PHOTO));
101 localized_strings->SetString("profilePhotoLoading",
102 l10n_util::GetStringUTF16(
103 IDS_OPTIONS_CHANGE_PICTURE_PROFILE_LOADING_PHOTO));
104 localized_strings->SetString("previewAltText",
105 l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_PREVIEW_ALT));
106 localized_strings->SetString("authorCredit",
107 l10n_util::GetStringUTF16(IDS_OPTIONS_SET_WALLPAPER_AUTHOR_TEXT));
108 if (!CommandLine::ForCurrentProcess()->
109 HasSwitch(switches::kDisableHtml5Camera)) {
110 localized_strings->SetString("cameraType", "webrtc");
111 } else {
112 localized_strings->SetString("cameraType", "old");
113 }
114 }
115
116 void ChangePictureOptionsHandler::RegisterMessages() {
117 web_ui()->RegisterMessageCallback("chooseFile",
118 base::Bind(&ChangePictureOptionsHandler::HandleChooseFile,
119 base::Unretained(this)));
120 web_ui()->RegisterMessageCallback("takePhoto",
121 base::Bind(&ChangePictureOptionsHandler::HandleTakePhoto,
122 base::Unretained(this)));
123 web_ui()->RegisterMessageCallback("photoTaken",
124 base::Bind(&ChangePictureOptionsHandler::HandlePhotoTaken,
125 base::Unretained(this)));
126 web_ui()->RegisterMessageCallback("onChangePicturePageShown",
127 base::Bind(&ChangePictureOptionsHandler::HandlePageShown,
128 base::Unretained(this)));
129 web_ui()->RegisterMessageCallback("onChangePicturePageInitialized",
130 base::Bind(&ChangePictureOptionsHandler::HandlePageInitialized,
131 base::Unretained(this)));
132 web_ui()->RegisterMessageCallback("selectImage",
133 base::Bind(&ChangePictureOptionsHandler::HandleSelectImage,
134 base::Unretained(this)));
135 }
136
137 void ChangePictureOptionsHandler::SendDefaultImages() {
138 base::ListValue image_urls;
139 for (int i = kFirstDefaultImageIndex; i < kDefaultImagesCount; ++i) {
140 scoped_ptr<base::DictionaryValue> image_data(new base::DictionaryValue);
141 image_data->SetString("url", GetDefaultImageUrl(i));
142 image_data->SetString(
143 "author", l10n_util::GetStringUTF16(kDefaultImageAuthorIDs[i]));
144 image_data->SetString(
145 "website", l10n_util::GetStringUTF16(kDefaultImageWebsiteIDs[i]));
146 image_urls.Append(image_data.release());
147 }
148 web_ui()->CallJavascriptFunction("ChangePictureOptions.setDefaultImages",
149 image_urls);
150 }
151
152 void ChangePictureOptionsHandler::HandleChooseFile(const ListValue* args) {
153 DCHECK(args && args->empty());
154 select_file_dialog_ = ui::SelectFileDialog::Create(
155 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
156
157 FilePath downloads_path;
158 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &downloads_path)) {
159 NOTREACHED();
160 return;
161 }
162
163 // Static so we initialize it only once.
164 CR_DEFINE_STATIC_LOCAL(ui::SelectFileDialog::FileTypeInfo, file_type_info,
165 (GetUserImageFileTypeInfo()));
166
167 select_file_dialog_->SelectFile(
168 ui::SelectFileDialog::SELECT_OPEN_FILE,
169 l10n_util::GetStringUTF16(IDS_DOWNLOAD_TITLE),
170 downloads_path,
171 &file_type_info,
172 0,
173 FILE_PATH_LITERAL(""),
174 GetBrowserWindow(),
175 NULL);
176 }
177
178 void ChangePictureOptionsHandler::HandleTakePhoto(const ListValue* args) {
179 DCHECK(args && args->empty());
180 views::Widget* window = views::Widget::CreateWindowWithParent(
181 new TakePhotoDialog(this), GetBrowserWindow());
182 window->SetAlwaysOnTop(true);
183 window->Show();
184 }
185
186 void ChangePictureOptionsHandler::HandlePhotoTaken(
187 const base::ListValue* args) {
188 std::string image_url;
189 if (!args || args->GetSize() != 1 || !args->GetString(0, &image_url))
190 NOTREACHED();
191 DCHECK(!image_url.empty());
192
193 std::string mime_type, charset, raw_data;
194 if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data))
195 NOTREACHED();
196 DCHECK_EQ("image/png", mime_type);
197
198 user_photo_ = gfx::ImageSkia();
199 user_photo_data_url_ = image_url;
200
201 if (image_decoder_.get())
202 image_decoder_->set_delegate(NULL);
203 image_decoder_ = new ImageDecoder(this, raw_data);
204 image_decoder_->Start();
205 }
206
207 void ChangePictureOptionsHandler::HandlePageInitialized(
208 const base::ListValue* args) {
209 DCHECK(args && args->empty());
210
211 if (CommandLine::ForCurrentProcess()->
212 HasSwitch(switches::kDisableHtml5Camera)) {
213 // If no camera presence check has been performed in this session,
214 // start one now.
215 if (CameraDetector::camera_presence() ==
216 CameraDetector::kCameraPresenceUnknown) {
217 CheckCameraPresence();
218 }
219
220 // While the check is in progress, use previous camera presence state and
221 // presume it is present if no check has been performed yet.
222 SetCameraPresent(CameraDetector::camera_presence() !=
223 CameraDetector::kCameraAbsent);
224 }
225
226 SendDefaultImages();
227 }
228
229 void ChangePictureOptionsHandler::HandlePageShown(const base::ListValue* args) {
230 DCHECK(args && args->empty());
231 // TODO(ivankr): If user opens settings and goes to Change Picture page right
232 // after the check started |HandlePageInitialized| has been completed,
233 // |CheckCameraPresence| will be called twice, should be throttled.
234 CheckCameraPresence();
235 SendSelectedImage();
236 UpdateProfileImage();
237 }
238
239 void ChangePictureOptionsHandler::SendSelectedImage() {
240 const User& user = UserManager::Get()->GetLoggedInUser();
241 DCHECK(!user.email().empty());
242
243 previous_image_index_ = user.image_index();
244 switch (previous_image_index_) {
245 case User::kExternalImageIndex: {
246 // User has image from camera/file, record it and add to the image list.
247 previous_image_ = user.image();
248 previous_image_data_url_ = web_ui_util::GetImageDataUrl(previous_image_);
249 web_ui()->CallJavascriptFunction("ChangePictureOptions.setOldImage");
250 break;
251 }
252 case User::kProfileImageIndex: {
253 // User has his/her Profile image as the current image.
254 SendProfileImage(user.image(), true);
255 break;
256 }
257 default: {
258 DCHECK(previous_image_index_ >= 0 &&
259 previous_image_index_ < kDefaultImagesCount);
260 if (previous_image_index_ >= kFirstDefaultImageIndex) {
261 // User has image from the current set of default images.
262 base::StringValue image_url(GetDefaultImageUrl(previous_image_index_));
263 web_ui()->CallJavascriptFunction(
264 "ChangePictureOptions.setSelectedImage", image_url);
265 } else {
266 // User has an old default image, so present it in the same manner as a
267 // previous image from file.
268 web_ui()->CallJavascriptFunction("ChangePictureOptions.setOldImage");
269 }
270 }
271 }
272 }
273
274 void ChangePictureOptionsHandler::SendProfileImage(const gfx::ImageSkia& image,
275 bool should_select) {
276 base::StringValue data_url(web_ui_util::GetImageDataUrl(image));
277 base::FundamentalValue select(should_select);
278 web_ui()->CallJavascriptFunction("ChangePictureOptions.setProfileImage",
279 data_url, select);
280 }
281
282 void ChangePictureOptionsHandler::UpdateProfileImage() {
283 UserManager* user_manager = UserManager::Get();
284
285 // If we have a downloaded profile image and haven't sent it in
286 // |SendSelectedImage|, send it now (without selecting).
287 if (previous_image_index_ != User::kProfileImageIndex &&
288 !user_manager->DownloadedProfileImage().empty())
289 SendProfileImage(user_manager->DownloadedProfileImage(), false);
290
291 user_manager->DownloadProfileImage(kProfileDownloadReason);
292 }
293
294 void ChangePictureOptionsHandler::HandleSelectImage(const ListValue* args) {
295 std::string image_url;
296 if (!args ||
297 args->GetSize() != 1 ||
298 !args->GetString(0, &image_url)) {
299 NOTREACHED();
300 return;
301 }
302 DCHECK(!image_url.empty());
303
304 UserManager* user_manager = UserManager::Get();
305 const User& user = user_manager->GetLoggedInUser();
306 int image_index = User::kInvalidImageIndex;
307 bool waiting_for_camera_photo = false;
308
309 if (StartsWithASCII(image_url, chrome::kChromeUIUserImageURL, false)) {
310 // Image from file/camera uses |kChromeUIUserImageURL| as URL while
311 // current profile image always has a full data URL.
312 // This way transition from (current profile image) to
313 // (profile image, current image from file) is easier.
314 // Also, old (not available for selection any more) default images use
315 // this URL, too.
316
317 if (previous_image_index_ == User::kExternalImageIndex) {
318 DCHECK(!previous_image_.empty());
319 user_manager->SaveUserImage(user.email(),
320 UserImage::CreateAndEncode(previous_image_));
321 } else {
322 DCHECK(previous_image_index_ >= 0 &&
323 previous_image_index_ < kFirstDefaultImageIndex);
324 user_manager->SaveUserDefaultImageIndex(user.email(),
325 previous_image_index_);
326 }
327
328 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
329 kHistogramImageOld,
330 kHistogramImagesCount);
331 VLOG(1) << "Selected old user image";
332 } else if (IsDefaultImageUrl(image_url, &image_index)) {
333 // One of the default user images.
334 user_manager->SaveUserDefaultImageIndex(user.email(), image_index);
335
336 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
337 GetDefaultImageHistogramValue(image_index),
338 kHistogramImagesCount);
339 VLOG(1) << "Selected default user image: " << image_index;
340 } else if (image_url == user_photo_data_url_) {
341 // Camera image is selected.
342 if (user_photo_.empty()) {
343 DCHECK(image_decoder_.get());
344 waiting_for_camera_photo = true;
345 VLOG(1) << "Still waiting for camera image to decode";
346 } else {
347 OnPhotoAccepted(user_photo_);
348 }
349 } else {
350 // Profile image selected. Could be previous (old) user image.
351 user_manager->SaveUserImageFromProfileImage(user.email());
352
353 if (previous_image_index_ == User::kProfileImageIndex) {
354 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
355 kHistogramImageOld,
356 kHistogramImagesCount);
357 VLOG(1) << "Selected old (profile) user image";
358 } else {
359 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
360 kHistogramImageFromProfile,
361 kHistogramImagesCount);
362 VLOG(1) << "Selected profile image";
363 }
364 }
365
366 // Ignore the result of the previous decoding if it's no longer needed.
367 if (!waiting_for_camera_photo && image_decoder_.get())
368 image_decoder_->set_delegate(NULL);
369 }
370
371 void ChangePictureOptionsHandler::FileSelected(const FilePath& path,
372 int index,
373 void* params) {
374 UserManager* user_manager = UserManager::Get();
375 user_manager->SaveUserImageFromFile(user_manager->GetLoggedInUser().email(),
376 path);
377 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
378 kHistogramImageFromFile,
379 kHistogramImagesCount);
380 VLOG(1) << "Selected image from file";
381 }
382
383 void ChangePictureOptionsHandler::OnPhotoAccepted(const gfx::ImageSkia& photo) {
384 UserManager* user_manager = UserManager::Get();
385 // TODO(ivankr): once old camera UI is gone, there's always raw data in
386 // |image_decoder_|, pass UserImage and user it instead.
387 user_manager->SaveUserImage(user_manager->GetLoggedInUser().email(),
388 UserImage::CreateAndEncode(photo));
389 UMA_HISTOGRAM_ENUMERATION("UserImage.ChangeChoice",
390 kHistogramImageFromCamera,
391 kHistogramImagesCount);
392 VLOG(1) << "Selected camera photo";
393 }
394
395 void ChangePictureOptionsHandler::CheckCameraPresence() {
396 // For WebRTC, camera presence checked is done on JS side.
397 if (!CommandLine::ForCurrentProcess()->
398 HasSwitch(switches::kDisableHtml5Camera)) {
399 return;
400 }
401 CameraDetector::StartPresenceCheck(
402 base::Bind(&ChangePictureOptionsHandler::OnCameraPresenceCheckDone,
403 weak_factory_.GetWeakPtr()));
404 }
405
406 void ChangePictureOptionsHandler::SetCameraPresent(bool present) {
407 base::FundamentalValue present_value(present);
408 web_ui()->CallJavascriptFunction("ChangePictureOptions.setCameraPresent",
409 present_value);
410 }
411
412 void ChangePictureOptionsHandler::OnCameraPresenceCheckDone() {
413 SetCameraPresent(CameraDetector::camera_presence() ==
414 CameraDetector::kCameraPresent);
415 }
416
417 void ChangePictureOptionsHandler::Observe(
418 int type,
419 const content::NotificationSource& source,
420 const content::NotificationDetails& details) {
421 OptionsPageUIHandler::Observe(type, source, details);
422 if (type == chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED) {
423 // User profile image has been updated.
424 SendProfileImage(*content::Details<const gfx::ImageSkia>(details).ptr(),
425 false);
426 }
427 }
428
429 gfx::NativeWindow ChangePictureOptionsHandler::GetBrowserWindow() const {
430 Browser* browser =
431 browser::FindBrowserWithWebContents(web_ui()->GetWebContents());
432 return browser->window()->GetNativeWindow();
433 }
434
435 void ChangePictureOptionsHandler::OnImageDecoded(
436 const ImageDecoder* decoder,
437 const SkBitmap& decoded_image) {
438 DCHECK_EQ(image_decoder_.get(), decoder);
439 image_decoder_ = NULL;
440 user_photo_ = gfx::ImageSkia(decoded_image);
441 OnPhotoAccepted(user_photo_);
442 }
443
444 void ChangePictureOptionsHandler::OnDecodeImageFailed(
445 const ImageDecoder* decoder) {
446 NOTREACHED() << "Failed to decode PNG image from WebUI";
447 }
448
449 } // namespace options
450 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698