// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_ #define EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_ #include #include #include #include #include #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/data_decoder/public/mojom/image_decoder.mojom.h" class SkBitmap; namespace data_decoder { class DataDecoder; } namespace extensions { // This class takes potentially unsafe images and decodes them in a sandboxed // process, then reencodes them so that they can later be safely used in the // browser process. class ImageSanitizer { public: enum class Status { kSuccess = 0, kImagePathError, kFileReadError, kFileDeleteError, kDecodingError, kEncodingError, kFileWriteError, }; class Client : public base::RefCountedThreadSafe { public: // Asks the client for a DataDecoder. Pushing the ownership of the // DataDecoder to Client implementations help ensure that the same decoder // can be reused across different decoding kinds (including non-image // decoding). virtual data_decoder::DataDecoder* GetDataDecoder() = 0; // Callback invoked exactly once - when the image sanitization is done. If // status is an error, |path| points to the file that caused the error. virtual void OnImageSanitizationDone(Status status, const base::FilePath& path) = 0; // Callback invoked on a background thread 0..N times (once per image from // `image_relative_paths`) whenever an image has been successfully decoded. virtual void OnImageDecoded(const base::FilePath& path, SkBitmap image) = 0; protected: friend class base::RefCountedThreadSafe; virtual ~Client(); }; // Creates an ImageSanitizer and starts the sanitization of the images in // |image_relative_paths|. These paths should be relative and not reference // their parent dir or an kImagePathError will be reported to |done_callback|. // These relative paths are resolved against |image_dir|. // // |client| provides the DataDecoder to use for image decoding. |client|'s // OnImageDecoded and OnImageSanitizationDone methods will be called with // sanitization results (if the returned ImageSanitizer instance is deleted // then these callback methods are not called and the sanitization stops // promptly (some background tasks may still run)). static std::unique_ptr CreateAndStart( scoped_refptr client, const base::FilePath& image_dir, const std::set& image_relative_paths, const scoped_refptr& task_runner); ImageSanitizer(const ImageSanitizer&) = delete; ImageSanitizer& operator=(const ImageSanitizer&) = delete; ~ImageSanitizer(); private: ImageSanitizer( scoped_refptr client, const base::FilePath& image_dir, const std::set& image_relative_paths, const scoped_refptr& io_task_runner); void Start(); void ImageFileRead( const base::FilePath& image_path, std::tuple, bool, bool> read_and_delete_result); void ImageDecoded(const base::FilePath& image_path, const SkBitmap& decoded_image); void ImageReencoded(const base::FilePath& image_path, std::pair> result); void ImageWritten(const base::FilePath& image_path, int expected_size, int actual_size); void ReportSuccess(); void ReportError(Status status, const base::FilePath& path); void CleanUp(); base::FilePath image_dir_; std::set image_paths_; scoped_refptr client_; scoped_refptr io_task_runner_; base::WeakPtrFactory weak_factory_{this}; }; } // namespace extensions #endif // EXTENSIONS_BROWSER_IMAGE_SANITIZER_H_