supported_image_type_validator.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/supported_image_type_validator.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/callback.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/location.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/weak_ptr.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/image_decoder.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::BrowserThread;
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace chrome {
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Arbitrary limit to sanity check the file size.
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kMaxImageFileSize = 50*1014*1024;
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct PlatformFileCloser {
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void operator()(base::PlatformFile* file) const {
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (file && *file != base::kInvalidPlatformFileValue)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::ClosePlatformFile(*file);
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)typedef scoped_ptr<base::PlatformFile, PlatformFileCloser>
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ScopedPlatformFile;
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<std::string> ReadOnFileThread(const base::FilePath& path) {
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<std::string> result;
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::PlatformFile file = base::CreatePlatformFile(
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScopedPlatformFile file_closer(&file);
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (file == base::kInvalidPlatformFileValue)
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result.Pass();
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::PlatformFileInfo file_info;
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!base::GetPlatformFileInfo(file, &file_info) ||
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_info.size > kMaxImageFileSize) {
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result.Pass();
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result.reset(new std::string);
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result->resize(file_info.size);
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (base::ReadPlatformFile(file, 0, string_as_array(result.get()),
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             file_info.size) != file_info.size) {
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result.reset();
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result.Pass();
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ImageDecoderDelegateAdapter : public ImageDecoder::Delegate {
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ImageDecoderDelegateAdapter(
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<std::string> data,
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : data_(data.Pass()),
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        callback_(callback) {
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(data_);
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::string& data() {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return *data_;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // ImageDecoder::Delegate methods.
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void OnImageDecoded(const ImageDecoder* /*decoder*/,
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkBitmap& /*decoded_image*/) OVERRIDE {
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            base::Bind(callback_, base::PLATFORM_FILE_OK));
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delete this;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void OnDecodeImageFailed(const ImageDecoder* /*decoder*/) OVERRIDE {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            base::Bind(callback_,
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       base::PLATFORM_FILE_ERROR_SECURITY));
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delete this;
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<std::string> data_;
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ImageDecoderDelegateAdapter);
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SupportedImageTypeValidator::~SupportedImageTypeValidator() {}
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool SupportedImageTypeValidator::SupportsFileType(const base::FilePath& path) {
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FilePath::StringType extension = path.Extension();
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return extension == FILE_PATH_LITERAL(".bmp") ||
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".gif") ||
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".jfif") ||
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".jpeg") ||
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".jpg") ||
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".pjp") ||
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".pjpeg") ||
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".png") ||
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         extension == FILE_PATH_LITERAL(".webp");
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SupportedImageTypeValidator::StartValidation(
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const fileapi::CopyOrMoveFileValidator::ResultCallback& result_callback) {
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(callback_.is_null());
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback_ = result_callback;
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BrowserThread::PostTaskAndReplyWithResult(
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BrowserThread::FILE,
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      FROM_HERE,
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&ReadOnFileThread, path_),
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&SupportedImageTypeValidator::OnFileOpen,
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 weak_factory_.GetWeakPtr()));
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SupportedImageTypeValidator::SupportedImageTypeValidator(
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& path)
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : path_(path),
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      weak_factory_(this) {
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SupportedImageTypeValidator::OnFileOpen(scoped_ptr<std::string> data) {
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!data.get()) {
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // |adapter| will delete itself after a completion message is received.
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ImageDecoderDelegateAdapter* adapter =
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new ImageDecoderDelegateAdapter(data.Pass(), callback_);
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  decoder_ = new ImageDecoder(adapter, adapter->data(),
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              ImageDecoder::DEFAULT_CODEC);
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::SequencedWorkerPool* workerpool = BrowserThread::GetBlockingPool();
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  decoder_->Start(workerpool->GetSequencedTaskRunnerWithShutdownBehavior(
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        workerpool->GetSequenceToken(),
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace chrome
157