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 fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
     55       : data_(data.Pass()),
     56         callback_(callback) {
     57     DCHECK(data_);
     58   }
     59 
     60   const std::string& data() {
     61     return *data_;
     62   }
     63 
     64   // ImageDecoder::Delegate methods.
     65   virtual void OnImageDecoded(const ImageDecoder* /*decoder*/,
     66                               const SkBitmap& /*decoded_image*/) OVERRIDE {
     67     callback_.Run(base::File::FILE_OK);
     68     delete this;
     69   }
     70 
     71   virtual void OnDecodeImageFailed(const ImageDecoder* /*decoder*/) OVERRIDE {
     72     callback_.Run(base::File::FILE_ERROR_SECURITY);
     73     delete this;
     74   }
     75 
     76  private:
     77   scoped_ptr<std::string> data_;
     78   fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
     79 
     80   DISALLOW_COPY_AND_ASSIGN(ImageDecoderDelegateAdapter);
     81 };
     82 
     83 }  // namespace
     84 
     85 SupportedImageTypeValidator::~SupportedImageTypeValidator() {}
     86 
     87 // static
     88 bool SupportedImageTypeValidator::SupportsFileType(const base::FilePath& path) {
     89   base::FilePath::StringType extension = path.Extension();
     90   return extension == FILE_PATH_LITERAL(".bmp") ||
     91          extension == FILE_PATH_LITERAL(".gif") ||
     92          extension == FILE_PATH_LITERAL(".jfif") ||
     93          extension == FILE_PATH_LITERAL(".jpeg") ||
     94          extension == FILE_PATH_LITERAL(".jpg") ||
     95          extension == FILE_PATH_LITERAL(".pjp") ||
     96          extension == FILE_PATH_LITERAL(".pjpeg") ||
     97          extension == FILE_PATH_LITERAL(".png") ||
     98          extension == FILE_PATH_LITERAL(".webp");
     99 }
    100 
    101 void SupportedImageTypeValidator::StartPreWriteValidation(
    102     const ResultCallback& result_callback) {
    103   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    104   DCHECK(callback_.is_null());
    105   callback_ = result_callback;
    106 
    107   BrowserThread::PostTaskAndReplyWithResult(
    108       BrowserThread::FILE,
    109       FROM_HERE,
    110       base::Bind(&ReadOnFileThread, path_),
    111       base::Bind(&SupportedImageTypeValidator::OnFileOpen,
    112                  weak_factory_.GetWeakPtr()));
    113 }
    114 
    115 SupportedImageTypeValidator::SupportedImageTypeValidator(
    116     const base::FilePath& path)
    117     : path_(path),
    118       weak_factory_(this) {
    119 }
    120 
    121 void SupportedImageTypeValidator::OnFileOpen(scoped_ptr<std::string> data) {
    122   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    123   if (!data.get()) {
    124     callback_.Run(base::File::FILE_ERROR_SECURITY);
    125     return;
    126   }
    127 
    128   // |adapter| will delete itself after a completion message is received.
    129   ImageDecoderDelegateAdapter* adapter =
    130       new ImageDecoderDelegateAdapter(data.Pass(), callback_);
    131   decoder_ = new ImageDecoder(adapter, adapter->data(),
    132                               ImageDecoder::DEFAULT_CODEC);
    133   decoder_->Start(content::BrowserThread::GetMessageLoopProxyForThread(
    134       BrowserThread::IO));
    135 }
    136