blob: 24a400b0188b00c8b71fa5e935aac7be85063edb [file] [log] [blame]
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001// 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"
Ben Murdoch558790d2013-07-30 15:19:42 +01009#include "base/files/scoped_platform_file_closer.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#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"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010015#include "base/threading/thread_restrictions.h"
16#include "chrome/browser/image_decoder.h"
17#include "content/public/browser/browser_thread.h"
18
19using content::BrowserThread;
20
21namespace chrome {
22
23namespace {
24
25// Arbitrary limit to sanity check the file size.
26const int kMaxImageFileSize = 50*1014*1024;
27
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010028scoped_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);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010034 if (file == base::kInvalidPlatformFileValue)
35 return result.Pass();
Ben Murdoch558790d2013-07-30 15:19:42 +010036 base::ScopedPlatformFileCloser file_closer(&file);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010037
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
54class 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 {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010071 callback_.Run(base::PLATFORM_FILE_OK);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010072 delete this;
73 }
74
75 virtual void OnDecodeImageFailed(const ImageDecoder* /*decoder*/) OVERRIDE {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010076 callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010077 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
89SupportedImageTypeValidator::~SupportedImageTypeValidator() {}
90
91// static
92bool 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
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100105void SupportedImageTypeValidator::StartPreWriteValidation(
106 const ResultCallback& result_callback) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100107 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
119SupportedImageTypeValidator::SupportedImageTypeValidator(
120 const base::FilePath& path)
121 : path_(path),
122 weak_factory_(this) {
123}
124
125void 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);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100137 decoder_->Start(content::BrowserThread::GetMessageLoopProxyForThread(
138 BrowserThread::IO));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100139}
140
141} // namespace chrome