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/scoped_platform_file_closer.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 chrome {
     22 
     23 namespace {
     24 
     25 // Arbitrary limit to sanity check the file size.
     26 const int kMaxImageFileSize = 50*1014*1024;
     27 
     28 scoped_ptr<std::string> ReadOnFileThread(const base::FilePath& path) {
     29   base::ThreadRestrictions::AssertIOAllowed();
     30   scoped_ptr<std::string> result;
     31 
     32   base::PlatformFile file = base::CreatePlatformFile(
     33       path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
     34   if (file == base::kInvalidPlatformFileValue)
     35     return result.Pass();
     36   base::ScopedPlatformFileCloser file_closer(&file);
     37 
     38   base::PlatformFileInfo file_info;
     39   if (!base::GetPlatformFileInfo(file, &file_info) ||
     40       file_info.size > kMaxImageFileSize) {
     41     return result.Pass();
     42   }
     43 
     44   result.reset(new std::string);
     45   result->resize(file_info.size);
     46   if (base::ReadPlatformFile(file, 0, string_as_array(result.get()),
     47                              file_info.size) != file_info.size) {
     48     result.reset();
     49   }
     50 
     51   return result.Pass();
     52 }
     53 
     54 class ImageDecoderDelegateAdapter : public ImageDecoder::Delegate {
     55  public:
     56   ImageDecoderDelegateAdapter(
     57       scoped_ptr<std::string> data,
     58       const fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
     59       : data_(data.Pass()),
     60         callback_(callback) {
     61     DCHECK(data_);
     62   }
     63 
     64   const std::string& data() {
     65     return *data_;
     66   }
     67 
     68   // ImageDecoder::Delegate methods.
     69   virtual void OnImageDecoded(const ImageDecoder* /*decoder*/,
     70                               const SkBitmap& /*decoded_image*/) OVERRIDE {
     71     callback_.Run(base::PLATFORM_FILE_OK);
     72     delete this;
     73   }
     74 
     75   virtual void OnDecodeImageFailed(const ImageDecoder* /*decoder*/) OVERRIDE {
     76     callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
     77     delete this;
     78   }
     79 
     80  private:
     81   scoped_ptr<std::string> data_;
     82   fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
     83 
     84   DISALLOW_COPY_AND_ASSIGN(ImageDecoderDelegateAdapter);
     85 };
     86 
     87 }  // namespace
     88 
     89 SupportedImageTypeValidator::~SupportedImageTypeValidator() {}
     90 
     91 // static
     92 bool SupportedImageTypeValidator::SupportsFileType(const base::FilePath& path) {
     93   base::FilePath::StringType extension = path.Extension();
     94   return extension == FILE_PATH_LITERAL(".bmp") ||
     95          extension == FILE_PATH_LITERAL(".gif") ||
     96          extension == FILE_PATH_LITERAL(".jfif") ||
     97          extension == FILE_PATH_LITERAL(".jpeg") ||
     98          extension == FILE_PATH_LITERAL(".jpg") ||
     99          extension == FILE_PATH_LITERAL(".pjp") ||
    100          extension == FILE_PATH_LITERAL(".pjpeg") ||
    101          extension == FILE_PATH_LITERAL(".png") ||
    102          extension == FILE_PATH_LITERAL(".webp");
    103 }
    104 
    105 void SupportedImageTypeValidator::StartPreWriteValidation(
    106     const ResultCallback& result_callback) {
    107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    108   DCHECK(callback_.is_null());
    109   callback_ = result_callback;
    110 
    111   BrowserThread::PostTaskAndReplyWithResult(
    112       BrowserThread::FILE,
    113       FROM_HERE,
    114       base::Bind(&ReadOnFileThread, path_),
    115       base::Bind(&SupportedImageTypeValidator::OnFileOpen,
    116                  weak_factory_.GetWeakPtr()));
    117 }
    118 
    119 SupportedImageTypeValidator::SupportedImageTypeValidator(
    120     const base::FilePath& path)
    121     : path_(path),
    122       weak_factory_(this) {
    123 }
    124 
    125 void SupportedImageTypeValidator::OnFileOpen(scoped_ptr<std::string> data) {
    126   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    127   if (!data.get()) {
    128     callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
    129     return;
    130   }
    131 
    132   // |adapter| will delete itself after a completion message is received.
    133   ImageDecoderDelegateAdapter* adapter =
    134       new ImageDecoderDelegateAdapter(data.Pass(), callback_);
    135   decoder_ = new ImageDecoder(adapter, adapter->data(),
    136                               ImageDecoder::DEFAULT_CODEC);
    137   decoder_->Start(content::BrowserThread::GetMessageLoopProxyForThread(
    138       BrowserThread::IO));
    139 }
    140 
    141 }  // namespace chrome
    142