Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / users / avatar / user_image_loader.cc
bloba545a136f8d5a699e1ce8c2126fd7436afdf536f
1 // Copyright 2014 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/login/users/avatar/user_image_loader.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "chrome/browser/chromeos/login/helper.h"
16 #include "components/user_manager/user_image/user_image.h"
17 #include "skia/ext/image_operations.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "ui/gfx/codec/png_codec.h"
20 #include "ui/gfx/skbitmap_operations.h"
22 namespace chromeos {
24 UserImageLoader::ImageInfo::ImageInfo(const std::string& file_path,
25 int pixels_per_side,
26 const LoadedCallback& loaded_cb)
27 : file_path(file_path),
28 pixels_per_side(pixels_per_side),
29 loaded_cb(loaded_cb) {
32 UserImageLoader::ImageInfo::~ImageInfo() {
35 UserImageLoader::UserImageRequest::UserImageRequest(
36 const ImageInfo& image_info,
37 const std::string& image_data,
38 const scoped_refptr<UserImageLoader>& user_image_loader)
39 : ImageRequest(user_image_loader->background_task_runner_),
40 image_info_(image_info),
41 image_data_(image_data.begin(), image_data.end()),
42 user_image_loader_(user_image_loader) {
45 UserImageLoader::UserImageRequest::~UserImageRequest() {
48 UserImageLoader::UserImageLoader(
49 ImageDecoder::ImageCodec image_codec,
50 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
51 : foreground_task_runner_(base::ThreadTaskRunnerHandle::Get()),
52 background_task_runner_(background_task_runner),
53 image_codec_(image_codec) {
56 UserImageLoader::~UserImageLoader() {
59 void UserImageLoader::Start(const std::string& filepath,
60 int pixels_per_side,
61 const LoadedCallback& loaded_cb) {
62 background_task_runner_->PostTask(
63 FROM_HERE,
64 base::Bind(&UserImageLoader::ReadAndDecodeImage,
65 this,
66 ImageInfo(filepath, pixels_per_side, loaded_cb)));
69 void UserImageLoader::Start(scoped_ptr<std::string> data,
70 int pixels_per_side,
71 const LoadedCallback& loaded_cb) {
72 background_task_runner_->PostTask(
73 FROM_HERE,
74 base::Bind(&UserImageLoader::DecodeImage,
75 this,
76 base::Passed(&data),
77 ImageInfo(std::string(), pixels_per_side, loaded_cb)));
80 void UserImageLoader::ReadAndDecodeImage(const ImageInfo& image_info) {
81 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
83 scoped_ptr<std::string> data(new std::string);
84 if (!base::ReadFileToString(base::FilePath(image_info.file_path), data.get()))
85 LOG(ERROR) << "Failed to read image " << image_info.file_path;
87 // In case ReadFileToString() fails, |data| is empty and DecodeImage() calls
88 // back to OnDecodeImageFailed().
89 DecodeImage(data.Pass(), image_info);
92 void UserImageLoader::DecodeImage(const scoped_ptr<std::string> data,
93 const ImageInfo& image_info) {
94 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
96 UserImageRequest* image_request =
97 new UserImageRequest(image_info, *data, this);
98 ImageDecoder::StartWithOptions(image_request, *data, image_codec_, false);
101 void UserImageLoader::UserImageRequest::OnImageDecoded(
102 const SkBitmap& decoded_image) {
103 DCHECK(task_runner()->RunsTasksOnCurrentThread());
105 const int target_size = image_info_.pixels_per_side;
106 SkBitmap final_image = decoded_image;
108 if (target_size > 0) {
109 // Auto crop the image, taking the largest square in the center.
110 int pixels_per_side =
111 std::min(decoded_image.width(), decoded_image.height());
112 int x = (decoded_image.width() - pixels_per_side) / 2;
113 int y = (decoded_image.height() - pixels_per_side) / 2;
114 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap(
115 decoded_image, x, y, pixels_per_side, pixels_per_side);
116 if (pixels_per_side > target_size) {
117 // Also downsize the image to save space and memory.
118 final_image =
119 skia::ImageOperations::Resize(cropped_image,
120 skia::ImageOperations::RESIZE_LANCZOS3,
121 target_size,
122 target_size);
123 } else {
124 final_image = cropped_image;
127 // Make the SkBitmap immutable as we won't modify it. This is important
128 // because otherwise it gets duplicated during painting, wasting memory.
129 final_image.setImmutable();
130 gfx::ImageSkia final_image_skia =
131 gfx::ImageSkia::CreateFrom1xBitmap(final_image);
132 final_image_skia.MakeThreadSafe();
133 user_manager::UserImage user_image(final_image_skia, image_data_);
134 user_image.set_file_path(image_info_.file_path);
135 if (user_image_loader_->image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC)
136 user_image.MarkAsSafe();
137 user_image_loader_->foreground_task_runner_->PostTask(
138 FROM_HERE, base::Bind(image_info_.loaded_cb, user_image));
139 delete this;
142 void UserImageLoader::UserImageRequest::OnDecodeImageFailed() {
143 DCHECK(task_runner()->RunsTasksOnCurrentThread());
144 user_image_loader_->foreground_task_runner_->PostTask(
145 FROM_HERE, base::Bind(image_info_.loaded_cb, user_manager::UserImage()));
146 delete this;
149 } // namespace chromeos