Chromium Code Reviews
[email protected] (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: chrome/browser/android/download/ui/thumbnail_provider.cc

Issue 2294983002: [Download Home] Add image thumbnail support (Closed)
Patch Set: TODO Created 4 years, 3 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
OLDNEW
(Empty)
1 // Copyright 2016 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/android/download/ui/thumbnail_provider.h"
6
7 #include "base/android/jni_string.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/memory/weak_ptr.h"
11 #include "chrome/browser/image_decoder.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "jni/ThumbnailProviderImpl_jni.h"
14 #include "skia/ext/image_operations.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "ui/gfx/android/java_bitmap.h"
17 #include "ui/gfx/skbitmap_operations.h"
18
19 class SkBitmap;
20
21 using base::android::JavaParamRef;
22
23 namespace {
24
25 // Ignore image files that are too large to avoid long delays.
26 const int64_t kMaxImageSize = 10 * 1024 * 1024; // 10 MB
27
28 class ImageThumbnailRequest : public ImageDecoder::ImageRequest {
29 public:
30 ImageThumbnailRequest(int icon_size,
31 const std::string& file_path,
32 base::WeakPtr<ThumbnailProvider> weak_provider)
33 : icon_size_(icon_size),
34 file_path_(file_path),
35 weak_provider_(weak_provider) {}
36
37 void Start() {
38 // Confirm that the file's size is within our threshold.
39 int64_t file_size;
40 base::FilePath path = base::FilePath::FromUTF8Unsafe(file_path_);
41 if (!base::GetFileSize(path, &file_size) || file_size > kMaxImageSize) {
42 LOG(ERROR) << "Unexpected file size: " << file_path_ << ", " << file_size;
43 FinishRequest(SkBitmap());
44 }
45
46 // Make sure the file isn't empty.
47 std::string data;
48 bool success = base::ReadFileToString(path, &data);
49 if (!success || data.empty()) {
50 LOG(ERROR) << "Failed to read file: " << file_path_;
51 FinishRequest(SkBitmap());
52 }
53
54 ImageDecoder::Start(this, data);
55 }
56
57 void OnImageDecoded(const SkBitmap& decoded_image) override {
58 SkBitmap thumbnail = decoded_image;
59 if (!decoded_image.drawsNothing()) {
60 // Shrink the image down so that its smallest dimension is equal to or
61 // smaller than the requested size.
62 int min_dimension =
63 std::min(decoded_image.width(), decoded_image.height());
64
65 if (min_dimension > icon_size_) {
66 uint64_t width = static_cast<uint64_t>(decoded_image.width());
67 uint64_t height = static_cast<uint64_t>(decoded_image.height());
68 thumbnail = skia::ImageOperations::Resize(
69 decoded_image, skia::ImageOperations::RESIZE_BEST,
70 width * icon_size_ / min_dimension,
71 height * icon_size_ / min_dimension);
72 }
73 }
74
75 FinishRequest(thumbnail);
76 }
77
78 void OnDecodeImageFailed() override {
79 LOG(ERROR) << "Failed to decode image: " << file_path_;
80 FinishRequest(SkBitmap());
81 }
82
83 private:
84 void FinishRequest(const SkBitmap& thumbnail) {
85 content::BrowserThread::PostTask(
86 content::BrowserThread::UI, FROM_HERE,
87 base::Bind(&ImageThumbnailRequest::FinishRequestOnUIThread,
88 base::Unretained(this), thumbnail));
Ted C 2016/08/31 20:14:40 same question as below, should you be passing the
Ian Wen 2016/08/31 20:43:30 IIRC, weak_ptr is only better than Unretained() if
gone 2016/08/31 22:10:53 This should be fine because the ImageThumbnailRequ
89 }
90
91 void FinishRequestOnUIThread(const SkBitmap& thumbnail) {
92 if (weak_provider_)
93 weak_provider_->OnThumbnailRetrieved(file_path_, thumbnail);
94 task_runner()->DeleteSoon(FROM_HERE, this);
95 }
96
97 const int icon_size_;
98 std::string file_path_;
99 base::WeakPtr<ThumbnailProvider> weak_provider_;
100
101 DISALLOW_IMPLICIT_CONSTRUCTORS(ImageThumbnailRequest);
102 };
103
104 } // namespace
105
106 ThumbnailProvider::ThumbnailProvider(const JavaParamRef<jobject>& jobj,
107 int icon_size)
Ted C 2016/08/31 20:14:41 icon_size isn't used
gone 2016/08/31 22:10:53 Whoops. Removed.
108 : java_delegate_(jobj), weak_factory_(this) {}
109
110 ThumbnailProvider::~ThumbnailProvider() {
111 java_delegate_.Reset();
112 }
113
114 void ThumbnailProvider::Destroy(JNIEnv* env,
115 const JavaParamRef<jobject>& jobj) {
116 delete this;
117 }
118
119 void ThumbnailProvider::OnThumbnailRetrieved(const std::string& file_path,
120 const SkBitmap& thumbnail) {
121 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
122
123 if (java_delegate_.is_null())
124 return;
125
126 // Send the bitmap back to Java-land.
127 JNIEnv* env = base::android::AttachCurrentThread();
128 Java_ThumbnailProviderImpl_onThumbnailRetrieved(
129 env, java_delegate_,
130 base::android::ConvertUTF8ToJavaString(env, file_path),
131 gfx::ConvertToJavaBitmap(&thumbnail));
132 }
133
134 void ThumbnailProvider::RetrieveThumbnail(JNIEnv* env,
Ted C 2016/08/31 20:14:41 What is the longer term plan for this? Should it
gone 2016/08/31 22:10:53 I'm planning on having this class delegate to diff
135 const JavaParamRef<jobject>& jobj,
136 jstring jfile_path,
137 jint icon_size) {
138 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
139
140 // The ImageThumbnailRequest deletes itself on completion.
141 std::string path = base::android::ConvertJavaStringToUTF8(env, jfile_path);
142
143 content::BrowserThread::PostTask(
144 content::BrowserThread::FILE, FROM_HERE,
145 base::Bind(&ThumbnailProvider::RetrieveThumbnailOnFileThread,
146 base::Unretained(this), path, icon_size));
Ted C 2016/08/31 20:14:40 I think you need to pass the weak_ptr here. You a
gone 2016/08/31 22:10:53 Blarghhh. Ian and I walked through the wonkiness
147 }
148
149 void ThumbnailProvider::RetrieveThumbnailOnFileThread(
150 const std::string& file_path,
151 int icon_size) {
152 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
153
154 ImageThumbnailRequest* request = new ImageThumbnailRequest(
155 icon_size, file_path, weak_factory_.GetWeakPtr());
156 request->Start();
157 }
158
159 // static
160 bool ThumbnailProvider::RegisterJNI(JNIEnv* env) {
161 return RegisterNativesImpl(env);
162 }
163
164 // static
165 static jlong Init(JNIEnv* env,
166 const JavaParamRef<jobject>& jobj,
167 int icon_size) {
168 return reinterpret_cast<intptr_t>(new ThumbnailProvider(jobj, icon_size));
169 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698