Home | History | Annotate | Download | only in fileapi
      1 // Copyright 2013 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/media_galleries/fileapi/supported_image_type_validator.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/files/file.h"
     10 #include "base/location.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/stl_util.h"
     15 #include "base/threading/thread_restrictions.h"
     16 #include "chrome/browser/image_decoder.h"
     17 #include "content/public/browser/browser_thread.h"
     18 
     19 using content::BrowserThread;
     20 
     21 namespace {
     22 
     23 // Arbitrary limit to sanity check the file size.
     24 const int kMaxImageFileSize = 50*1014*1024;
     25 
     26 scoped_ptr<std::string> ReadOnFileThread(const base::FilePath& path) {
     27   base::ThreadRestrictions::AssertIOAllowed();
     28   scoped_ptr<std::string> result;
     29 
     30   base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     31   if (!file.IsValid())
     32     return result.Pass();
     33 
     34   base::File::Info file_info;
     35   if (!file.GetInfo(&file_info) ||
     36       file_info.size > kMaxImageFileSize) {
     37     return result.Pass();
     38   }
     39 
     40   result.reset(new std::string);
     41   result->resize(file_info.size);
     42   if (file.Read(0, string_as_array(result.get()), file_info.size) !=
     43       file_info.size) {
     44     result.reset();
     45   }
     46 
     47   return result.Pass();
     48 }
     49 
     50 class ImageDecoderDelegateAdapter : public ImageDecoder::Delegate {
     51  public:
     52   ImageDecoderDelegateAdapter(
     53       scoped_ptr<std::string> data,
     54       const storage::CopyOrMoveFileValidator::ResultCallback& callback)
     55       : data_(data.Pass()), callback_(callback) {
     56     DCHECK(data_);
     57   }
     58 
     59   const std::string& data() {
     60     return *data_;
     61   }
     62 
     63   // ImageDecoder::Delegate methods.
     64   virtual void OnImageDecoded(const ImageDecoder* /*decoder*/,
     65                               const SkBitmap& /*decoded_image*/) OVERRIDE {
     66     callback_.Run(base::File::FILE_OK);
     67     delete this;
     68   }
     69 
     70   virtual void OnDecodeImageFailed(const ImageDecoder* /*decoder*/) OVERRIDE {
     71     callback_.Run(base::File::FILE_ERROR_SECURITY);
     72     delete this;
     73   }
     74 
     75  private:
     76   scoped_ptr<std::string> data_;
     77   storage::CopyOrMoveFileValidator::ResultCallback callback_;
     78 
     79   DISALLOW_COPY_AND_ASSIGN(ImageDecoderDelegateAdapter);
     80 };
     81 
     82 }  // namespace
     83 
     84 SupportedImageTypeValidator::~SupportedImageTypeValidator() {}
     85 
     86 // static
     87 bool SupportedImageTypeValidator::SupportsFileType(const base::FilePath& path) {
     88   base::FilePath::StringType extension = path.Extension();
     89   return extension == FILE_PATH_LITERAL(".bmp") ||
     90          extension == FILE_PATH_LITERAL(".gif") ||
     91          extension == FILE_PATH_LITERAL(".jfif") ||
     92          extension == FILE_PATH_LITERAL(".jpeg") ||
     93          extension == FILE_PATH_LITERAL(".jpg") ||
     94          extension == FILE_PATH_LITERAL(".pjp") ||
     95          extension == FILE_PATH_LITERAL(".pjpeg") ||
     96          extension == FILE_PATH_LITERAL(".png") ||
     97          extension == FILE_PATH_LITERAL(".webp");
     98 }
     99 
    100 void SupportedImageTypeValidator::StartPreWriteValidation(
    101     const ResultCallback& result_callback) {
    102   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    103   DCHECK(callback_.is_null());
    104   callback_ = result_callback;
    105 
    106   BrowserThread::PostTaskAndReplyWithResult(
    107       BrowserThread::FILE,
    108       FROM_HERE,
    109       base::Bind(&ReadOnFileThread, path_),
    110       base::Bind(&SupportedImageTypeValidator::OnFileOpen,
    111                  weak_factory_.GetWeakPtr()));
    112 }
    113 
    114 SupportedImageTypeValidator::SupportedImageTypeValidator(
    115     const base::FilePath& path)
    116     : path_(path),
    117       weak_factory_(this) {
    118 }
    119 
    120 void SupportedImageTypeValidator::OnFileOpen(scoped_ptr<std::string> data) {
    121   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    122   if (!data.get()) {
    123     callback_.Run(base::File::FILE_ERROR_SECURITY);
    124     return;
    125   }
    126 
    127   // |adapter| will delete itself after a completion message is received.
    128   ImageDecoderDelegateAdapter* adapter =
    129       new ImageDecoderDelegateAdapter(data.Pass(), callback_);
    130   decoder_ = new ImageDecoder(adapter, adapter->data(),
    131                               ImageDecoder::DEFAULT_CODEC);
    132   decoder_->Start(content::BrowserThread::GetMessageLoopProxyForThread(
    133       BrowserThread::IO));
    134 }
    135