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

Side by Side Diff: chrome/browser/image_decoder.cc

Issue 1067593005: Fix race conditions in ImageDecoder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use TestBrowserThreadBundle, cleanup tests Created 5 years, 8 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
« no previous file with comments | « chrome/browser/image_decoder.h ('k') | chrome/browser/image_decoder_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/image_decoder.h" 5 #include "chrome/browser/image_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/thread_task_runner_handle.h"
8 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/browser_process.h"
9 #include "chrome/common/chrome_utility_messages.h" 10 #include "chrome/common/chrome_utility_messages.h"
10 #include "chrome/grit/generated_resources.h" 11 #include "chrome/grit/generated_resources.h"
11 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/utility_process_host.h" 13 #include "content/public/browser/utility_process_host.h"
13 #include "ui/base/l10n/l10n_util.h" 14 #include "ui/base/l10n/l10n_util.h"
14 15
15 using content::BrowserThread; 16 using content::BrowserThread;
16 using content::UtilityProcessHost; 17 using content::UtilityProcessHost;
17 18
(...skipping 11 matching lines...) Expand all
29 ImageDecoder::ImageDecoder() 30 ImageDecoder::ImageDecoder()
30 : image_request_id_counter_(0), last_request_(base::TimeTicks::Now()) { 31 : image_request_id_counter_(0), last_request_(base::TimeTicks::Now()) {
31 // A single ImageDecoder instance should live for the life of the program. 32 // A single ImageDecoder instance should live for the life of the program.
32 // Explicitly add a reference so the object isn't deleted. 33 // Explicitly add a reference so the object isn't deleted.
33 AddRef(); 34 AddRef();
34 } 35 }
35 36
36 ImageDecoder::~ImageDecoder() { 37 ImageDecoder::~ImageDecoder() {
37 } 38 }
38 39
40 ImageDecoder::ImageRequest::ImageRequest()
41 : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
42 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
43 }
44
39 ImageDecoder::ImageRequest::ImageRequest( 45 ImageDecoder::ImageRequest::ImageRequest(
40 const scoped_refptr<base::SequencedTaskRunner>& task_runner) 46 const scoped_refptr<base::SequencedTaskRunner>& task_runner)
41 : task_runner_(task_runner) { 47 : task_runner_(task_runner) {
48 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
42 } 49 }
43 50
44 ImageDecoder::ImageRequest::~ImageRequest() { 51 ImageDecoder::ImageRequest::~ImageRequest() {
52 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
45 ImageDecoder::Cancel(this); 53 ImageDecoder::Cancel(this);
46 } 54 }
47 55
48 // static 56 // static
49 void ImageDecoder::Start(ImageRequest* image_request, 57 void ImageDecoder::Start(ImageRequest* image_request,
50 const std::string& image_data) { 58 const std::string& image_data) {
51 StartWithOptions(image_request, image_data, DEFAULT_CODEC, false); 59 StartWithOptions(image_request, image_data, DEFAULT_CODEC, false);
52 } 60 }
53 61
54 // static 62 // static
55 void ImageDecoder::StartWithOptions(ImageRequest* image_request, 63 void ImageDecoder::StartWithOptions(ImageRequest* image_request,
56 const std::string& image_data, 64 const std::string& image_data,
57 ImageCodec image_codec, 65 ImageCodec image_codec,
58 bool shrink_to_fit) { 66 bool shrink_to_fit) {
67 g_decoder.Pointer()->StartWithOptionsImpl(image_request, image_data,
68 image_codec, shrink_to_fit);
69 }
70
71 void ImageDecoder::StartWithOptionsImpl(ImageRequest* image_request,
72 const std::string& image_data,
73 ImageCodec image_codec,
74 bool shrink_to_fit) {
59 DCHECK(image_request); 75 DCHECK(image_request);
60 DCHECK(image_request->task_runner()); 76 DCHECK(image_request->task_runner());
77
78 int request_id;
79 {
80 base::AutoLock lock(map_lock_);
81 request_id = image_request_id_counter_++;
82 image_request_id_map_.insert(std::make_pair(request_id, image_request));
83 }
84
61 BrowserThread::PostTask( 85 BrowserThread::PostTask(
62 BrowserThread::IO, FROM_HERE, 86 BrowserThread::IO, FROM_HERE,
63 base::Bind( 87 base::Bind(
64 &ImageDecoder::DecodeImageInSandbox, 88 &ImageDecoder::DecodeImageInSandbox,
65 g_decoder.Pointer(), image_request, 89 g_decoder.Pointer(), request_id,
66 std::vector<unsigned char>(image_data.begin(), image_data.end()), 90 std::vector<unsigned char>(image_data.begin(), image_data.end()),
67 image_codec, shrink_to_fit)); 91 image_codec, shrink_to_fit));
68 } 92 }
69 93
70 // static 94 // static
71 void ImageDecoder::Cancel(ImageRequest* image_request) { 95 void ImageDecoder::Cancel(ImageRequest* image_request) {
72 DCHECK(image_request); 96 DCHECK(image_request);
73 g_decoder.Pointer()->CancelImpl(image_request); 97 g_decoder.Pointer()->CancelImpl(image_request);
74 } 98 }
75 99
76 void ImageDecoder::DecodeImageInSandbox( 100 void ImageDecoder::DecodeImageInSandbox(
77 ImageRequest* image_request, 101 int request_id,
78 const std::vector<unsigned char>& image_data, 102 const std::vector<unsigned char>& image_data,
79 ImageCodec image_codec, 103 ImageCodec image_codec,
80 bool shrink_to_fit) { 104 bool shrink_to_fit) {
81 DCHECK_CURRENTLY_ON(BrowserThread::IO); 105 DCHECK_CURRENTLY_ON(BrowserThread::IO);
106 base::AutoLock lock(map_lock_);
107 const auto it = image_request_id_map_.find(request_id);
108 if (it == image_request_id_map_.end())
109 return;
110
111 ImageRequest* image_request = it->second;
82 if (!utility_process_host_) { 112 if (!utility_process_host_) {
83 StartBatchMode(); 113 StartBatchMode();
84 } 114 }
85 if (!utility_process_host_) { 115 if (!utility_process_host_) {
86 // Utility process failed to start; notify delegate and return. 116 // Utility process failed to start; notify delegate and return.
87 // Without this check, we were seeing crashes on startup. Further 117 // Without this check, we were seeing crashes on startup. Further
88 // investigation is needed to determine why the utility process 118 // investigation is needed to determine why the utility process
89 // is failing to start. See crbug.com/472272 119 // is failing to start. See crbug.com/472272
90 image_request->task_runner()->PostTask( 120 image_request->task_runner()->PostTask(
91 FROM_HERE, base::Bind(&ImageRequest::OnDecodeImageFailed, 121 FROM_HERE,
92 base::Unretained(image_request))); 122 base::Bind(&ImageDecoder::RunOnDecodeImageFailed, this, request_id));
93 return; 123 return;
94 } 124 }
95 125
96 last_request_ = base::TimeTicks::Now(); 126 last_request_ = base::TimeTicks::Now();
97 base::AutoLock lock(map_lock_);
98 image_request_id_map_.insert(
99 std::make_pair(image_request_id_counter_, image_request));
100 127
101 switch (image_codec) { 128 switch (image_codec) {
102 case ROBUST_JPEG_CODEC: 129 case ROBUST_JPEG_CODEC:
103 utility_process_host_->Send(new ChromeUtilityMsg_RobustJPEGDecodeImage( 130 utility_process_host_->Send(new ChromeUtilityMsg_RobustJPEGDecodeImage(
104 image_data, image_request_id_counter_)); 131 image_data, request_id));
105 break; 132 break;
106 case DEFAULT_CODEC: 133 case DEFAULT_CODEC:
107 utility_process_host_->Send(new ChromeUtilityMsg_DecodeImage( 134 utility_process_host_->Send(new ChromeUtilityMsg_DecodeImage(
108 image_data, shrink_to_fit, image_request_id_counter_)); 135 image_data, shrink_to_fit, request_id));
109 break; 136 break;
110 } 137 }
111
112 ++image_request_id_counter_;
113 } 138 }
114 139
115 void ImageDecoder::CancelImpl(ImageRequest* image_request) { 140 void ImageDecoder::CancelImpl(ImageRequest* image_request) {
116 base::AutoLock lock(map_lock_); 141 base::AutoLock lock(map_lock_);
117 for (auto it = image_request_id_map_.begin(); 142 for (auto it = image_request_id_map_.begin();
118 it != image_request_id_map_.end();) { 143 it != image_request_id_map_.end();) {
119 if (it->second == image_request) { 144 if (it->second == image_request) {
120 image_request_id_map_.erase(it++); 145 image_request_id_map_.erase(it++);
121 } else { 146 } else {
122 ++it; 147 ++it;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 IPC_END_MESSAGE_MAP() 191 IPC_END_MESSAGE_MAP()
167 return handled; 192 return handled;
168 } 193 }
169 194
170 void ImageDecoder::OnDecodeImageSucceeded( 195 void ImageDecoder::OnDecodeImageSucceeded(
171 const SkBitmap& decoded_image, 196 const SkBitmap& decoded_image,
172 int request_id) { 197 int request_id) {
173 DCHECK_CURRENTLY_ON(BrowserThread::IO); 198 DCHECK_CURRENTLY_ON(BrowserThread::IO);
174 base::AutoLock lock(map_lock_); 199 base::AutoLock lock(map_lock_);
175 auto it = image_request_id_map_.find(request_id); 200 auto it = image_request_id_map_.find(request_id);
176 if (it != image_request_id_map_.end()) { 201 if (it == image_request_id_map_.end())
177 ImageRequest* image_request = it->second; 202 return;
178 image_request->task_runner()->PostTask(
179 FROM_HERE, base::Bind(&ImageRequest::OnImageDecoded,
180 base::Unretained(image_request), decoded_image));
181 203
182 image_request_id_map_.erase(it); 204 ImageRequest* image_request = it->second;
183 } 205 image_request->task_runner()->PostTask(
206 FROM_HERE,
207 base::Bind(&ImageDecoder::RunOnImageDecoded,
208 this,
209 decoded_image,
210 request_id));
184 } 211 }
185 212
186 void ImageDecoder::OnDecodeImageFailed(int request_id) { 213 void ImageDecoder::OnDecodeImageFailed(int request_id) {
187 DCHECK_CURRENTLY_ON(BrowserThread::IO); 214 DCHECK_CURRENTLY_ON(BrowserThread::IO);
188 base::AutoLock lock(map_lock_); 215 base::AutoLock lock(map_lock_);
189 auto it = image_request_id_map_.find(request_id); 216 auto it = image_request_id_map_.find(request_id);
190 if (it != image_request_id_map_.end()) { 217 if (it == image_request_id_map_.end())
191 ImageRequest* image_request = it->second; 218 return;
192 image_request->task_runner()->PostTask(
193 FROM_HERE, base::Bind(&ImageRequest::OnDecodeImageFailed,
194 base::Unretained(image_request)));
195 219
220 ImageRequest* image_request = it->second;
221 image_request->task_runner()->PostTask(
222 FROM_HERE,
223 base::Bind(&ImageDecoder::RunOnDecodeImageFailed, this, request_id));
224 }
225
226 void ImageDecoder::RunOnImageDecoded(const SkBitmap& decoded_image,
227 int request_id) {
228 ImageRequest* image_request;
229 {
230 base::AutoLock lock(map_lock_);
231 auto it = image_request_id_map_.find(request_id);
232 if (it == image_request_id_map_.end())
233 return;
234 image_request = it->second;
196 image_request_id_map_.erase(it); 235 image_request_id_map_.erase(it);
197 } 236 }
237
238 DCHECK(image_request->task_runner()->RunsTasksOnCurrentThread());
239 image_request->OnImageDecoded(decoded_image);
198 } 240 }
241
242 void ImageDecoder::RunOnDecodeImageFailed(int request_id) {
243 ImageRequest* image_request;
244 {
245 base::AutoLock lock(map_lock_);
246 auto it = image_request_id_map_.find(request_id);
247 if (it == image_request_id_map_.end())
248 return;
249 image_request = it->second;
250 image_request_id_map_.erase(it);
251 }
252
253 DCHECK(image_request->task_runner()->RunsTasksOnCurrentThread());
254 image_request->OnDecodeImageFailed();
255 }
OLDNEW
« no previous file with comments | « chrome/browser/image_decoder.h ('k') | chrome/browser/image_decoder_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698