OLD | NEW |
1 // Copyright (c) 2012 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/chromeos/login/user_image_loader.h" | 5 #include "chrome/browser/chromeos/login/user_image_loader.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/threading/worker_pool.h" |
12 #include "chrome/browser/chromeos/login/helper.h" | 13 #include "chrome/browser/chromeos/login/helper.h" |
13 #include "chrome/browser/chromeos/login/user_image.h" | 14 #include "chrome/browser/chromeos/login/user_image.h" |
14 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
15 #include "skia/ext/image_operations.h" | 16 #include "skia/ext/image_operations.h" |
16 #include "third_party/skia/include/core/SkBitmap.h" | 17 #include "third_party/skia/include/core/SkBitmap.h" |
17 #include "ui/gfx/codec/png_codec.h" | 18 #include "ui/gfx/codec/png_codec.h" |
18 #include "ui/gfx/skbitmap_operations.h" | 19 #include "ui/gfx/skbitmap_operations.h" |
19 | 20 |
20 using content::BrowserThread; | 21 using content::BrowserThread; |
21 | 22 |
22 namespace chromeos { | 23 namespace chromeos { |
23 | 24 |
| 25 typedef base::SequencedWorkerPool::SequenceToken SequenceToken; |
| 26 |
24 UserImageLoader::ImageInfo::ImageInfo(int size, | 27 UserImageLoader::ImageInfo::ImageInfo(int size, |
25 const LoadedCallback& loaded_cb) | 28 const LoadedCallback& loaded_cb) |
26 : size(size), | 29 : size(size), |
27 loaded_cb(loaded_cb) { | 30 loaded_cb(loaded_cb) { |
28 } | 31 } |
29 | 32 |
30 UserImageLoader::ImageInfo::~ImageInfo() { | 33 UserImageLoader::ImageInfo::~ImageInfo() { |
31 } | 34 } |
32 | 35 |
33 UserImageLoader::UserImageLoader(ImageDecoder::ImageCodec image_codec) | 36 UserImageLoader::UserImageLoader(ImageDecoder::ImageCodec image_codec) |
34 : target_message_loop_(NULL), | 37 : target_message_loop_(NULL), |
35 image_codec_(image_codec) { | 38 image_codec_(image_codec) { |
36 } | 39 } |
37 | 40 |
38 UserImageLoader::~UserImageLoader() { | 41 UserImageLoader::~UserImageLoader() { |
39 } | 42 } |
40 | 43 |
41 void UserImageLoader::Start(const std::string& filepath, | 44 void UserImageLoader::Start(const std::string& filepath, |
42 int size, | 45 int size, |
43 const LoadedCallback& loaded_cb) { | 46 const LoadedCallback& loaded_cb) { |
44 target_message_loop_ = MessageLoop::current(); | 47 target_message_loop_ = MessageLoop::current(); |
45 | 48 |
46 ImageInfo image_info(size, loaded_cb); | 49 ImageInfo image_info(size, loaded_cb); |
47 BrowserThread::PostTask( | 50 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); |
48 BrowserThread::FILE, FROM_HERE, | 51 SequenceToken sequence_token = pool->GetSequenceToken(); |
49 base::Bind(&UserImageLoader::LoadImage, this, filepath, image_info)); | 52 scoped_refptr<base::SequencedTaskRunner> task_runner = pool-> |
| 53 GetSequencedTaskRunnerWithShutdownBehavior(sequence_token, |
| 54 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 55 task_runner->PostTask( |
| 56 FROM_HERE, |
| 57 base::Bind(&UserImageLoader::LoadImage, this, filepath, image_info, |
| 58 task_runner)); |
50 } | 59 } |
51 | 60 |
52 void UserImageLoader::LoadImage(const std::string& filepath, | 61 void UserImageLoader::LoadImage( |
53 const ImageInfo& image_info) { | 62 const std::string& filepath, |
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 63 const ImageInfo& image_info, |
| 64 scoped_refptr<base::SequencedTaskRunner> task_runner) { |
| 65 DCHECK(task_runner->RunsTasksOnCurrentThread()); |
55 | 66 |
56 std::string image_data; | 67 std::string image_data; |
57 file_util::ReadFileToString(FilePath(filepath), &image_data); | 68 file_util::ReadFileToString(FilePath(filepath), &image_data); |
58 | 69 |
59 scoped_refptr<ImageDecoder> image_decoder = | 70 scoped_refptr<ImageDecoder> image_decoder = |
60 new ImageDecoder(this, image_data, image_codec_); | 71 new ImageDecoder(this, image_data, image_codec_); |
61 image_info_map_.insert(std::make_pair(image_decoder.get(), image_info)); | 72 { |
62 image_decoder->Start(); | 73 base::AutoLock lock(lock_); |
| 74 image_info_map_.insert(std::make_pair(image_decoder.get(), image_info)); |
| 75 } |
| 76 image_decoder->Start(task_runner); |
63 } | 77 } |
64 | 78 |
65 void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, | 79 void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, |
66 const SkBitmap& decoded_image) { | 80 const SkBitmap& decoded_image) { |
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 81 ImageInfoMap::iterator info_it; |
68 | 82 scoped_ptr<ImageInfo> image_info; |
69 ImageInfoMap::iterator info_it = image_info_map_.find(decoder); | 83 { |
70 if (info_it == image_info_map_.end()) { | 84 base::AutoLock lock(lock_); |
71 NOTREACHED(); | 85 info_it = image_info_map_.find(decoder); |
72 return; | 86 if (info_it == image_info_map_.end()) { |
| 87 NOTREACHED(); |
| 88 return; |
| 89 } |
| 90 image_info.reset( |
| 91 new ImageInfo(info_it->second.size, info_it->second.loaded_cb)); |
| 92 image_info_map_.erase(info_it); |
73 } | 93 } |
74 | 94 |
75 const ImageInfo& image_info = info_it->second; | |
76 SkBitmap final_image = decoded_image; | 95 SkBitmap final_image = decoded_image; |
77 | 96 |
78 if (image_info.size > 0) { | 97 if (image_info->size > 0) { |
79 // Auto crop the image, taking the largest square in the center. | 98 // Auto crop the image, taking the largest square in the center. |
80 int size = std::min(decoded_image.width(), decoded_image.height()); | 99 int size = std::min(decoded_image.width(), decoded_image.height()); |
81 int x = (decoded_image.width() - size) / 2; | 100 int x = (decoded_image.width() - size) / 2; |
82 int y = (decoded_image.height() - size) / 2; | 101 int y = (decoded_image.height() - size) / 2; |
83 SkBitmap cropped_image = | 102 SkBitmap cropped_image = |
84 SkBitmapOperations::CreateTiledBitmap(decoded_image, x, y, size, size); | 103 SkBitmapOperations::CreateTiledBitmap(decoded_image, x, y, size, size); |
85 if (size > image_info.size) { | 104 if (size > image_info->size) { |
86 // Also downsize the image to save space and memory. | 105 // Also downsize the image to save space and memory. |
87 final_image = | 106 final_image = |
88 skia::ImageOperations::Resize(cropped_image, | 107 skia::ImageOperations::Resize(cropped_image, |
89 skia::ImageOperations::RESIZE_LANCZOS3, | 108 skia::ImageOperations::RESIZE_LANCZOS3, |
90 image_info.size, | 109 image_info->size, |
91 image_info.size); | 110 image_info->size); |
92 } else { | 111 } else { |
93 final_image = cropped_image; | 112 final_image = cropped_image; |
94 } | 113 } |
95 } | 114 } |
96 gfx::ImageSkia final_image_skia = | 115 gfx::ImageSkia final_image_skia = |
97 gfx::ImageSkia::CreateFrom1xBitmap(final_image); | 116 gfx::ImageSkia::CreateFrom1xBitmap(final_image); |
98 final_image_skia.MakeThreadSafe(); | 117 final_image_skia.MakeThreadSafe(); |
99 UserImage user_image(final_image_skia, decoder->get_image_data()); | 118 UserImage user_image(final_image_skia, decoder->get_image_data()); |
100 if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC) | 119 if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC) |
101 user_image.MarkAsSafe(); | 120 user_image.MarkAsSafe(); |
102 target_message_loop_->PostTask( | 121 target_message_loop_->PostTask( |
103 FROM_HERE, | 122 FROM_HERE, |
104 base::Bind(image_info.loaded_cb, user_image)); | 123 base::Bind(image_info->loaded_cb, user_image)); |
105 | |
106 image_info_map_.erase(info_it); | |
107 } | 124 } |
108 | 125 |
109 void UserImageLoader::OnDecodeImageFailed(const ImageDecoder* decoder) { | 126 void UserImageLoader::OnDecodeImageFailed(const ImageDecoder* decoder) { |
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 127 ImageInfoMap::iterator info_it; |
111 | 128 scoped_ptr<ImageInfo> image_info; |
112 ImageInfoMap::iterator info_it = image_info_map_.find(decoder); | 129 { |
113 if (info_it == image_info_map_.end()) { | 130 base::AutoLock lock(lock_); |
114 NOTREACHED(); | 131 info_it = image_info_map_.find(decoder); |
115 return; | 132 if (info_it == image_info_map_.end()) { |
| 133 NOTREACHED(); |
| 134 return; |
| 135 } |
| 136 image_info.reset( |
| 137 new ImageInfo(info_it->second.size, info_it->second.loaded_cb)); |
| 138 image_info_map_.erase(decoder); |
116 } | 139 } |
117 | 140 |
118 const ImageInfo& image_info = info_it->second; | |
119 target_message_loop_->PostTask( | 141 target_message_loop_->PostTask( |
120 FROM_HERE, | 142 FROM_HERE, |
121 base::Bind(image_info.loaded_cb, UserImage())); | 143 base::Bind(image_info->loaded_cb, UserImage())); |
122 image_info_map_.erase(decoder); | |
123 } | 144 } |
124 | 145 |
125 } // namespace chromeos | 146 } // namespace chromeos |
OLD | NEW |