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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_IMAGE_DECODER_IMAGE_DECODER_H_ 6 #define CHROME_BROWSER_IMAGE_DECODER_IMAGE_DECODER_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/macros.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/sequence_checker.h" 15 #include "base/sequenced_task_runner.h" 16 #include "base/synchronization/lock.h" 17 18 namespace data_decoder { 19 class DataDecoder; 20 } // namespace data_decoder 21 22 namespace gfx { 23 class Size; 24 } // namespace gfx 25 26 class SkBitmap; 27 28 // This is a helper class for decoding images safely in a sandboxed service. To 29 // use this, call ImageDecoder::Start(...) or 30 // ImageDecoder::StartWithOptions(...) on any thread. 31 // 32 // ImageRequest::OnImageDecoded or ImageRequest::OnDecodeImageFailed is posted 33 // back to the |task_runner_| associated with the ImageRequest. 34 // 35 // The Cancel() method runs on whichever thread called it. 36 // 37 // TODO(rockot): Use of this class should be replaced with direct image_decoder 38 // client library usage. 39 class ImageDecoder { 40 public: 41 // ImageRequest objects needs to be created and destroyed on the same 42 // SequencedTaskRunner. 43 class ImageRequest { 44 public: 45 // Called when image is decoded. 46 virtual void OnImageDecoded(const SkBitmap& decoded_image) = 0; 47 48 // Called when decoding image failed. ImageRequest can do some cleanup in 49 // this handler. OnDecodeImageFailed()50 virtual void OnDecodeImageFailed() {} 51 task_runner()52 base::SequencedTaskRunner* task_runner() const { 53 return task_runner_.get(); 54 } 55 data_decoder()56 data_decoder::DataDecoder* data_decoder() { return data_decoder_; } 57 58 protected: 59 // Creates an ImageRequest that runs on the thread which created it. 60 ImageRequest(); 61 // Explicitly pass in |task_runner| if the current thread is part of a 62 // thread pool. 63 explicit ImageRequest( 64 const scoped_refptr<base::SequencedTaskRunner>& task_runner); 65 // Explicitly pass in |data_decoder| if there's a specific decoder that 66 // should be used; otherwise, an isolated decoder will created and used. 67 explicit ImageRequest(data_decoder::DataDecoder* data_decoder); 68 virtual ~ImageRequest(); 69 70 private: 71 // The thread to post OnImageDecoded() or OnDecodeImageFailed() once the 72 // the image has been decoded. 73 const scoped_refptr<base::SequencedTaskRunner> task_runner_; 74 75 // If null, will use a new decoder via DecodeImageIsolated() instead. 76 data_decoder::DataDecoder* const data_decoder_ = nullptr; 77 78 SEQUENCE_CHECKER(sequence_checker_); 79 }; 80 81 enum ImageCodec { 82 DEFAULT_CODEC = 0, // Uses WebKit image decoding (via WebImage). 83 #if defined(OS_CHROMEOS) 84 ROBUST_PNG_CODEC, // Restrict decoding to robust PNG codec. 85 #endif // defined(OS_CHROMEOS) 86 }; 87 88 static ImageDecoder* GetInstance(); 89 90 // Calls StartWithOptions() with ImageCodec::DEFAULT_CODEC and 91 // shrink_to_fit = false. 92 static void Start(ImageRequest* image_request, 93 std::vector<uint8_t> image_data); 94 // Deprecated. Use std::vector<uint8_t> version to avoid an extra copy. 95 static void Start(ImageRequest* image_request, const std::string& image_data); 96 97 // Starts asynchronous image decoding. Once finished, the callback will be 98 // posted back to image_request's |task_runner_|. 99 // For images with multiple frames (e.g. ico files), a frame with a size as 100 // close as possible to |desired_image_frame_size| is chosen (tries to take 101 // one in larger size if there's no precise match). Passing gfx::Size() as 102 // |desired_image_frame_size| is also supported and will result in chosing the 103 // smallest available size. 104 static void StartWithOptions(ImageRequest* image_request, 105 std::vector<uint8_t> image_data, 106 ImageCodec image_codec, 107 bool shrink_to_fit, 108 const gfx::Size& desired_image_frame_size); 109 // Deprecated. Use std::vector<uint8_t> version to avoid an extra copy. 110 static void StartWithOptions(ImageRequest* image_request, 111 const std::string& image_data, 112 ImageCodec image_codec, 113 bool shrink_to_fit); 114 115 // Removes all instances of |image_request| from |image_request_id_map_|, 116 // ensuring callbacks are not made to the image_request after it is destroyed. 117 static void Cancel(ImageRequest* image_request); 118 119 private: 120 using RequestMap = std::map<int, ImageRequest*>; 121 122 ImageDecoder(); 123 ~ImageDecoder() = delete; 124 125 void StartWithOptionsImpl(ImageRequest* image_request, 126 std::vector<uint8_t> image_data, 127 ImageCodec image_codec, 128 bool shrink_to_fit, 129 const gfx::Size& desired_image_frame_size); 130 131 void CancelImpl(ImageRequest* image_request); 132 133 // IPC message handlers. 134 void OnDecodeImageSucceeded(const SkBitmap& decoded_image, int request_id); 135 void OnDecodeImageFailed(int request_id); 136 137 // id to use for the next Start() request that comes in. 138 int image_request_id_counter_; 139 140 // Map of request id's to ImageRequests. 141 RequestMap image_request_id_map_; 142 143 // Protects |image_request_id_map_| and |image_request_id_counter_|. 144 base::Lock map_lock_; 145 146 DISALLOW_COPY_AND_ASSIGN(ImageDecoder); 147 }; 148 149 #endif // CHROME_BROWSER_IMAGE_DECODER_IMAGE_DECODER_H_ 150