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

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

Issue 1067593005: Fix race conditions in ImageDecoder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: do not use MessageLoopProxy 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
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 #ifndef CHROME_BROWSER_IMAGE_DECODER_H_ 5 #ifndef CHROME_BROWSER_IMAGE_DECODER_H_
6 #define CHROME_BROWSER_IMAGE_DECODER_H_ 6 #define CHROME_BROWSER_IMAGE_DECODER_H_
7 7
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/compiler_specific.h"
13 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
14 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
14 #include "base/sequence_checker.h"
15 #include "base/sequenced_task_runner.h"
15 #include "base/synchronization/lock.h" 16 #include "base/synchronization/lock.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "base/timer/timer.h" 17 #include "base/timer/timer.h"
18 #include "content/public/browser/utility_process_host.h" 18 #include "content/public/browser/utility_process_host.h"
19 #include "content/public/browser/utility_process_host_client.h" 19 #include "content/public/browser/utility_process_host_client.h"
20 20
21 class SkBitmap; 21 class SkBitmap;
22 22
23 // This is a helper class for decoding images safely in a utility process. To 23 // This is a helper class for decoding images safely in a utility process. To
24 // use this, call ImageDecoder::Start(...) or 24 // use this, call ImageDecoder::Start(...) or
25 // ImageDecoder::StartWithOptions(...) on any thread. 25 // ImageDecoder::StartWithOptions(...) on any thread.
26 // 26 //
27 // Internally, most of the work happens on the IO thread, and then 27 // Internally, most of the work happens on the IO thread, and then
28 // the callback (ImageRequest::OnImageDecoded or 28 // the callback (ImageRequest::OnImageDecoded or
29 // ImageRequest::OnDecodeImageFailed) is posted back to the |task_runner_| 29 // ImageRequest::OnDecodeImageFailed) is posted back to the |task_runner_|
30 // associated with the ImageRequest. 30 // associated with the ImageRequest.
31 // The Cancel() method runs on whichever thread called it. |map_lock_| is used 31 // The Cancel() method runs on whichever thread called it. |map_lock_| is used
32 // to protect the data that is accessed from multiple threads. 32 // to protect the data that is accessed from multiple threads.
33 class ImageDecoder : public content::UtilityProcessHostClient { 33 class ImageDecoder : public content::UtilityProcessHostClient {
34 public: 34 public:
35 // ImageRequest objects needs to be created and destroyed on the same
36 // SequencedTaskRunner.
35 class ImageRequest { 37 class ImageRequest {
36 public: 38 public:
37 // Called when image is decoded. 39 // Called when image is decoded.
38 virtual void OnImageDecoded(const SkBitmap& decoded_image) = 0; 40 virtual void OnImageDecoded(const SkBitmap& decoded_image) = 0;
39 41
40 // Called when decoding image failed. ImageRequest can do some cleanup in 42 // Called when decoding image failed. ImageRequest can do some cleanup in
41 // this handler. 43 // this handler.
42 virtual void OnDecodeImageFailed() {} 44 virtual void OnDecodeImageFailed() {}
43 45
44 base::SequencedTaskRunner* task_runner() const { 46 base::SequencedTaskRunner* task_runner() const {
45 return task_runner_.get(); 47 return task_runner_.get();
46 } 48 }
47 49
48 protected: 50 protected:
51 // Creates an ImageRequest that runs on the thread creating it.
52 ImageRequest();
Theresa 2015/04/20 22:35:26 I like this introduction, definitely makes things
53 // Explicitly pass in |task_runner| if the current thread is part of a
54 // thread pool.
49 explicit ImageRequest( 55 explicit ImageRequest(
50 const scoped_refptr<base::SequencedTaskRunner>& task_runner); 56 const scoped_refptr<base::SequencedTaskRunner>& task_runner);
51 virtual ~ImageRequest(); 57 virtual ~ImageRequest();
52 58
53 private: 59 private:
54 // The thread to post OnImageDecoded or OnDecodeImageFailed once the 60 // The thread to post OnImageDecoded() or OnDecodeImageFailed() once the
55 // the image has been decoded. 61 // the image has been decoded.
56 const scoped_refptr<base::SequencedTaskRunner> task_runner_; 62 const scoped_refptr<base::SequencedTaskRunner> task_runner_;
63
64 base::SequenceChecker sequence_checker_;
57 }; 65 };
58 66
59 enum ImageCodec { 67 enum ImageCodec {
60 DEFAULT_CODEC = 0, // Uses WebKit image decoding (via WebImage). 68 DEFAULT_CODEC = 0, // Uses WebKit image decoding (via WebImage).
61 ROBUST_JPEG_CODEC, // Restrict decoding to robust jpeg codec. 69 ROBUST_JPEG_CODEC, // Restrict decoding to robust jpeg codec.
62 }; 70 };
63 71
64 // Calls StartWithOptions with ImageCodec::DEFAULT_CODEC and 72 // Calls StartWithOptions() with ImageCodec::DEFAULT_CODEC and
65 // shrink_to_fit = false. 73 // shrink_to_fit = false.
66 static void Start(ImageRequest* image_request, 74 static void Start(ImageRequest* image_request,
67 const std::string& image_data); 75 const std::string& image_data);
68 76
69 // Starts asynchronous image decoding. Once finished, the callback will be 77 // Starts asynchronous image decoding. Once finished, the callback will be
70 // posted back to image_request's |task_runner_|. 78 // posted back to image_request's |task_runner_|.
71 static void StartWithOptions(ImageRequest* image_request, 79 static void StartWithOptions(ImageRequest* image_request,
72 const std::string& image_data, 80 const std::string& image_data,
73 ImageCodec image_codec, 81 ImageCodec image_codec,
74 bool shrink_to_fit); 82 bool shrink_to_fit);
75 83
76 // Removes all instances of image_request from |image_request_id_map_|, 84 // Removes all instances of |image_request| from |image_request_id_map_|,
77 // ensuring callbacks are not made to the image_request after it is destroyed. 85 // ensuring callbacks are not made to the image_request after it is destroyed.
78 static void Cancel(ImageRequest* image_request); 86 static void Cancel(ImageRequest* image_request);
79 87
80 private: 88 private:
81 friend struct base::DefaultLazyInstanceTraits<ImageDecoder>; 89 friend struct base::DefaultLazyInstanceTraits<ImageDecoder>;
82 90
91 using RequestMap = std::map<int, ImageRequest*>;
92
83 ImageDecoder(); 93 ImageDecoder();
84 // It's a reference counted object, so destructor is private. 94 // It's a reference counted object, so destructor is private.
85 ~ImageDecoder() override; 95 ~ImageDecoder() override;
86 96
87 // Sends a request to the sandboxed process to decode the image. Starts 97 // Sends a request to the sandboxed process to decode the image. Starts
88 // batch mode if necessary. If the utility process fails to start, 98 // batch mode if necessary. If the utility process fails to start,
89 // an OnDecodeImageFailed task is posted to image_request's |task_runner_|. 99 // an OnDecodeImageFailed task is posted to image_request's |task_runner_|.
90 void DecodeImageInSandbox(ImageRequest* image_request, 100 void DecodeImageInSandbox(int image_request_counter,
Theresa 2015/04/20 22:35:26 int request_id?
Lei Zhang 2015/04/21 00:44:00 Done.
91 const std::vector<unsigned char>& image_data, 101 const std::vector<unsigned char>& image_data,
92 ImageCodec image_codec, 102 ImageCodec image_codec,
93 bool shrink_to_fit); 103 bool shrink_to_fit);
94 104
105 void StartWithOptionsImpl(ImageRequest* image_request,
106 const std::string& image_data,
107 ImageCodec image_codec,
108 bool shrink_to_fit);
95 void CancelImpl(ImageRequest* image_request); 109 void CancelImpl(ImageRequest* image_request);
96 110
97 using RequestMap = std::map<int, ImageRequest*>;
98
99 // Starts UtilityProcessHost in batch mode and starts |batch_mode_timer_|. 111 // Starts UtilityProcessHost in batch mode and starts |batch_mode_timer_|.
100 // If the utility process fails to start, the method resets 112 // If the utility process fails to start, the method resets
101 // |utility_process_host_| and returns. 113 // |utility_process_host_| and returns.
102 void StartBatchMode(); 114 void StartBatchMode();
103 115
104 // Stops batch mode if no requests have come in since 116 // Stops batch mode if no requests have come in since
105 // kBatchModeTimeoutSeconds. 117 // |kBatchModeTimeoutSeconds|.
106 void StopBatchMode(); 118 void StopBatchMode();
107 119
108 // Overidden from UtilityProcessHostClient. 120 // Overidden from UtilityProcessHostClient.
109 bool OnMessageReceived(const IPC::Message& message) override; 121 bool OnMessageReceived(const IPC::Message& message) override;
110 122
111 // IPC message handlers. 123 // IPC message handlers.
112 void OnDecodeImageSucceeded(const SkBitmap& decoded_image, int request_id); 124 void OnDecodeImageSucceeded(const SkBitmap& decoded_image, int request_id);
113 void OnDecodeImageFailed(int request_id); 125 void OnDecodeImageFailed(int request_id);
114 126
115 // id to use for the next Start request that comes in. 127 // For the ImageRequest identified by |request_id|, call its OnImageDecoded()
128 // or OnDecodeImageFailed() method on its task runner thread.
129 void RunOnImageDecoded(const SkBitmap& decoded_image, int request_id);
130 void RunOnDecodeImageFailed(int request_id);
131
132 // id to use for the next Start() request that comes in.
116 int image_request_id_counter_; 133 int image_request_id_counter_;
117 134
118 // Map of request id's to ImageRequests. 135 // Map of request id's to ImageRequests.
119 RequestMap image_request_id_map_; 136 RequestMap image_request_id_map_;
120 137
121 // Protects |image_request_id_map_| and |image_request_id_counter_|. 138 // Protects |image_request_id_map_| and |image_request_id_counter_|.
122 base::Lock map_lock_; 139 base::Lock map_lock_;
123 140
124 // The UtilityProcessHost requests are sent to. 141 // The UtilityProcessHost requests are sent to.
125 base::WeakPtr<content::UtilityProcessHost> utility_process_host_; 142 base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
126 143
127 // Calls StopBatchMode after kBatchModeTimeoutSeconds have elapsed. 144 // Calls StopBatchMode() after |kBatchModeTimeoutSeconds| have elapsed.
128 base::RepeatingTimer<ImageDecoder> batch_mode_timer_; 145 base::RepeatingTimer<ImageDecoder> batch_mode_timer_;
129 146
130 // The time Start was last called. 147 // The time Start() was last called.
131 base::TimeTicks last_request_; 148 base::TimeTicks last_request_;
132 149
133 DISALLOW_COPY_AND_ASSIGN(ImageDecoder); 150 DISALLOW_COPY_AND_ASSIGN(ImageDecoder);
134 }; 151 };
135 152
136 #endif // CHROME_BROWSER_IMAGE_DECODER_H_ 153 #endif // CHROME_BROWSER_IMAGE_DECODER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698