1 // Copyright 2014 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.
5 #include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h"
9 #include "base/files/file.h"
10 #include "base/files/file_path.h"
11 #include "base/json/json_reader.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/file_system_provider/operations/test_util.h"
16 #include "chrome/common/extensions/api/file_system_provider.h"
17 #include "chrome/common/extensions/api/file_system_provider_internal.h"
18 #include "extensions/browser/event_router.h"
19 #include "storage/browser/fileapi/async_file_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 namespace file_system_provider {
24 namespace operations {
27 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
28 const char kFileSystemId[] = "testing-file-system";
29 const char kMimeType[] = "text/plain";
30 const int kRequestId = 2;
31 const base::FilePath::CharType kDirectoryPath[] = "/directory";
33 // URLs are case insensitive, so it should pass the sanity check.
34 const char kThumbnail[] = "DaTa:ImAgE/pNg;base64,";
36 // Callback invocation logger. Acts as a fileapi end-point.
37 class CallbackLogger {
41 Event(scoped_ptr<EntryMetadata> metadata, base::File::Error result)
42 : metadata_(metadata.Pass()), result_(result) {}
45 const EntryMetadata* metadata() const { return metadata_.get(); }
46 base::File::Error result() const { return result_; }
49 scoped_ptr<EntryMetadata> metadata_;
50 base::File::Error result_;
52 DISALLOW_COPY_AND_ASSIGN(Event);
56 virtual ~CallbackLogger() {}
58 void OnGetMetadata(scoped_ptr<EntryMetadata> metadata,
59 base::File::Error result) {
60 events_.push_back(new Event(metadata.Pass(), result));
63 const ScopedVector<Event>& events() const { return events_; }
66 ScopedVector<Event> events_;
69 DISALLOW_COPY_AND_ASSIGN(CallbackLogger);
74 class FileSystemProviderOperationsGetMetadataTest : public testing::Test {
76 FileSystemProviderOperationsGetMetadataTest() {}
77 virtual ~FileSystemProviderOperationsGetMetadataTest() {}
79 virtual void SetUp() override {
80 file_system_info_ = ProvidedFileSystemInfo(
82 MountOptions(kFileSystemId, "" /* display_name */),
86 ProvidedFileSystemInfo file_system_info_;
89 TEST_F(FileSystemProviderOperationsGetMetadataTest, Execute) {
90 using extensions::api::file_system_provider::GetMetadataRequestedOptions;
92 util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
93 CallbackLogger callback_logger;
95 GetMetadata get_metadata(
98 base::FilePath::FromUTF8Unsafe(kDirectoryPath),
99 ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
100 base::Bind(&CallbackLogger::OnGetMetadata,
101 base::Unretained(&callback_logger)));
102 get_metadata.SetDispatchEventImplForTesting(
103 base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
104 base::Unretained(&dispatcher)));
106 EXPECT_TRUE(get_metadata.Execute(kRequestId));
108 ASSERT_EQ(1u, dispatcher.events().size());
109 extensions::Event* event = dispatcher.events()[0];
111 extensions::api::file_system_provider::OnGetMetadataRequested::kEventName,
113 base::ListValue* event_args = event->event_args.get();
114 ASSERT_EQ(1u, event_args->GetSize());
116 const base::DictionaryValue* options_as_value = NULL;
117 ASSERT_TRUE(event_args->GetDictionary(0, &options_as_value));
119 GetMetadataRequestedOptions options;
121 GetMetadataRequestedOptions::Populate(*options_as_value, &options));
122 EXPECT_EQ(kFileSystemId, options.file_system_id);
123 EXPECT_EQ(kRequestId, options.request_id);
124 EXPECT_EQ(kDirectoryPath, options.entry_path);
125 EXPECT_TRUE(options.thumbnail);
128 TEST_F(FileSystemProviderOperationsGetMetadataTest, Execute_NoListener) {
129 util::LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
130 CallbackLogger callback_logger;
132 GetMetadata get_metadata(
135 base::FilePath::FromUTF8Unsafe(kDirectoryPath),
136 ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
137 base::Bind(&CallbackLogger::OnGetMetadata,
138 base::Unretained(&callback_logger)));
139 get_metadata.SetDispatchEventImplForTesting(
140 base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
141 base::Unretained(&dispatcher)));
143 EXPECT_FALSE(get_metadata.Execute(kRequestId));
146 TEST_F(FileSystemProviderOperationsGetMetadataTest, OnSuccess) {
147 using extensions::api::file_system_provider_internal::
148 GetMetadataRequestedSuccess::Params;
150 util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
151 CallbackLogger callback_logger;
153 GetMetadata get_metadata(
156 base::FilePath::FromUTF8Unsafe(kDirectoryPath),
157 ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
158 base::Bind(&CallbackLogger::OnGetMetadata,
159 base::Unretained(&callback_logger)));
160 get_metadata.SetDispatchEventImplForTesting(
161 base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
162 base::Unretained(&dispatcher)));
164 EXPECT_TRUE(get_metadata.Execute(kRequestId));
166 // Sample input as JSON. Keep in sync with file_system_provider_api.idl.
167 // As for now, it is impossible to create *::Params class directly, not from
169 const std::string input =
171 " \"testing-file-system\",\n" // kFileSystemId
172 " 2,\n" // kRequestId
174 " \"isDirectory\": false,\n"
175 " \"name\": \"blueberries.txt\",\n"
177 " \"modificationTime\": {\n"
178 " \"value\": \"Thu Apr 24 00:46:52 UTC 2014\"\n"
180 " \"mimeType\": \"text/plain\",\n" // kMimeType
181 " \"thumbnail\": \"DaTa:ImAgE/pNg;base64,\"\n" // kThumbnail
183 " 0\n" // execution_time
187 std::string json_error_msg;
188 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
189 input, base::JSON_PARSE_RFC, &json_error_code, &json_error_msg));
190 ASSERT_TRUE(value.get()) << json_error_msg;
192 base::ListValue* value_as_list;
193 ASSERT_TRUE(value->GetAsList(&value_as_list));
194 scoped_ptr<Params> params(Params::Create(*value_as_list));
195 ASSERT_TRUE(params.get());
196 scoped_ptr<RequestValue> request_value(
197 RequestValue::CreateForGetMetadataSuccess(params.Pass()));
198 ASSERT_TRUE(request_value.get());
200 const bool has_more = false;
201 get_metadata.OnSuccess(kRequestId, request_value.Pass(), has_more);
203 ASSERT_EQ(1u, callback_logger.events().size());
204 CallbackLogger::Event* event = callback_logger.events()[0];
205 EXPECT_EQ(base::File::FILE_OK, event->result());
207 const EntryMetadata* metadata = event->metadata();
208 EXPECT_FALSE(metadata->is_directory);
209 EXPECT_EQ(4096, metadata->size);
210 base::Time expected_time;
212 base::Time::FromString("Thu Apr 24 00:46:52 UTC 2014", &expected_time));
213 EXPECT_EQ(expected_time, metadata->modification_time);
214 EXPECT_EQ(kMimeType, metadata->mime_type);
215 EXPECT_EQ(kThumbnail, metadata->thumbnail);
218 TEST_F(FileSystemProviderOperationsGetMetadataTest,
219 OnSuccess_InvalidThumbnail) {
220 using extensions::api::file_system_provider_internal::
221 GetMetadataRequestedSuccess::Params;
223 util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
224 CallbackLogger callback_logger;
226 GetMetadata get_metadata(
229 base::FilePath::FromUTF8Unsafe(kDirectoryPath),
230 ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
231 base::Bind(&CallbackLogger::OnGetMetadata,
232 base::Unretained(&callback_logger)));
233 get_metadata.SetDispatchEventImplForTesting(
234 base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
235 base::Unretained(&dispatcher)));
237 EXPECT_TRUE(get_metadata.Execute(kRequestId));
239 // Sample input as JSON. Keep in sync with file_system_provider_api.idl.
240 // As for now, it is impossible to create *::Params class directly, not from
242 const std::string input =
244 " \"testing-file-system\",\n" // kFileSystemId
245 " 2,\n" // kRequestId
247 " \"isDirectory\": false,\n"
248 " \"name\": \"blueberries.txt\",\n"
250 " \"modificationTime\": {\n"
251 " \"value\": \"Thu Apr 24 00:46:52 UTC 2014\"\n"
253 " \"mimeType\": \"text/plain\",\n" // kMimeType
254 " \"thumbnail\": \"http://www.foobar.com/evil\"\n" // kThumbnail
256 " 0\n" // execution_time
260 std::string json_error_msg;
261 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
262 input, base::JSON_PARSE_RFC, &json_error_code, &json_error_msg));
263 ASSERT_TRUE(value.get()) << json_error_msg;
265 base::ListValue* value_as_list;
266 ASSERT_TRUE(value->GetAsList(&value_as_list));
267 scoped_ptr<Params> params(Params::Create(*value_as_list));
268 ASSERT_TRUE(params.get());
269 scoped_ptr<RequestValue> request_value(
270 RequestValue::CreateForGetMetadataSuccess(params.Pass()));
271 ASSERT_TRUE(request_value.get());
273 const bool has_more = false;
274 get_metadata.OnSuccess(kRequestId, request_value.Pass(), has_more);
276 ASSERT_EQ(1u, callback_logger.events().size());
277 CallbackLogger::Event* event = callback_logger.events()[0];
278 EXPECT_EQ(base::File::FILE_ERROR_IO, event->result());
280 const EntryMetadata* metadata = event->metadata();
281 EXPECT_FALSE(metadata);
284 TEST_F(FileSystemProviderOperationsGetMetadataTest, OnError) {
285 util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
286 CallbackLogger callback_logger;
288 GetMetadata get_metadata(
291 base::FilePath::FromUTF8Unsafe(kDirectoryPath),
292 ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
293 base::Bind(&CallbackLogger::OnGetMetadata,
294 base::Unretained(&callback_logger)));
295 get_metadata.SetDispatchEventImplForTesting(
296 base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
297 base::Unretained(&dispatcher)));
299 EXPECT_TRUE(get_metadata.Execute(kRequestId));
301 get_metadata.OnError(kRequestId,
302 scoped_ptr<RequestValue>(new RequestValue()),
303 base::File::FILE_ERROR_TOO_MANY_OPENED);
305 ASSERT_EQ(1u, callback_logger.events().size());
306 CallbackLogger::Event* event = callback_logger.events()[0];
307 EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, event->result());
310 } // namespace operations
311 } // namespace file_system_provider
312 } // namespace chromeos