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. 4 5 #include <string> 6 #include <vector> 7 8 #include "base/files/file.h" 9 #include "base/files/file_path.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_vector.h" 12 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h" 13 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h" 14 #include "chrome/common/extensions/api/file_system_provider.h" 15 #include "chrome/common/extensions/api/file_system_provider_internal.h" 16 #include "extensions/browser/event_router.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "webkit/browser/fileapi/async_file_util.h" 19 20 namespace chromeos { 21 namespace file_system_provider { 22 namespace operations { 23 namespace { 24 25 const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj"; 26 const char kFileSystemId[] = "testing-file-system"; 27 const int kRequestId = 2; 28 const base::FilePath::CharType kFilePath[] = "/directory/blueberries.txt"; 29 30 // Fake event dispatcher implementation with extra logging capability. Acts as 31 // a providing extension end-point. 32 class LoggingDispatchEventImpl { 33 public: 34 explicit LoggingDispatchEventImpl(bool dispatch_reply) 35 : dispatch_reply_(dispatch_reply) {} 36 virtual ~LoggingDispatchEventImpl() {} 37 38 bool OnDispatchEventImpl(scoped_ptr<extensions::Event> event) { 39 events_.push_back(event->DeepCopy()); 40 return dispatch_reply_; 41 } 42 43 ScopedVector<extensions::Event>& events() { return events_; } 44 45 private: 46 ScopedVector<extensions::Event> events_; 47 bool dispatch_reply_; 48 49 DISALLOW_COPY_AND_ASSIGN(LoggingDispatchEventImpl); 50 }; 51 52 // Callback invocation logger. Acts as a fileapi end-point. 53 class CallbackLogger { 54 public: 55 class Event { 56 public: 57 Event(int file_handle, base::File::Error result) 58 : file_handle_(file_handle), result_(result) {} 59 virtual ~Event() {} 60 61 int file_handle() { return file_handle_; } 62 base::File::Error result() { return result_; } 63 64 private: 65 int file_handle_; 66 base::File::Error result_; 67 68 DISALLOW_COPY_AND_ASSIGN(Event); 69 }; 70 71 CallbackLogger() : weak_ptr_factory_(this) {} 72 virtual ~CallbackLogger() {} 73 74 void OnOpenFile(int file_handle, base::File::Error result) { 75 events_.push_back(new Event(file_handle, result)); 76 } 77 78 ScopedVector<Event>& events() { return events_; } 79 80 base::WeakPtr<CallbackLogger> GetWeakPtr() { 81 return weak_ptr_factory_.GetWeakPtr(); 82 } 83 84 private: 85 ScopedVector<Event> events_; 86 bool dispatch_reply_; 87 base::WeakPtrFactory<CallbackLogger> weak_ptr_factory_; 88 89 DISALLOW_COPY_AND_ASSIGN(CallbackLogger); 90 }; 91 92 } // namespace 93 94 class FileSystemProviderOperationsOpenFileTest : public testing::Test { 95 protected: 96 FileSystemProviderOperationsOpenFileTest() {} 97 virtual ~FileSystemProviderOperationsOpenFileTest() {} 98 99 virtual void SetUp() OVERRIDE { 100 file_system_info_ = 101 ProvidedFileSystemInfo(kExtensionId, 102 kFileSystemId, 103 "" /* file_system_name */, 104 base::FilePath() /* mount_path */); 105 } 106 107 ProvidedFileSystemInfo file_system_info_; 108 }; 109 110 TEST_F(FileSystemProviderOperationsOpenFileTest, Execute) { 111 LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); 112 CallbackLogger callback_logger; 113 114 OpenFile open_file( 115 NULL, 116 file_system_info_, 117 base::FilePath::FromUTF8Unsafe(kFilePath), 118 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, 119 false /* create */, 120 base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr())); 121 open_file.SetDispatchEventImplForTesting( 122 base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl, 123 base::Unretained(&dispatcher))); 124 125 EXPECT_TRUE(open_file.Execute(kRequestId)); 126 127 ASSERT_EQ(1u, dispatcher.events().size()); 128 extensions::Event* event = dispatcher.events()[0]; 129 EXPECT_EQ( 130 extensions::api::file_system_provider::OnOpenFileRequested::kEventName, 131 event->event_name); 132 base::ListValue* event_args = event->event_args.get(); 133 ASSERT_EQ(1u, event_args->GetSize()); 134 135 base::DictionaryValue* options = NULL; 136 ASSERT_TRUE(event_args->GetDictionary(0, &options)); 137 138 std::string event_file_system_id; 139 EXPECT_TRUE(options->GetString("fileSystemId", &event_file_system_id)); 140 EXPECT_EQ(kFileSystemId, event_file_system_id); 141 142 int event_request_id = -1; 143 EXPECT_TRUE(options->GetInteger("requestId", &event_request_id)); 144 EXPECT_EQ(kRequestId, event_request_id); 145 146 std::string event_file_path; 147 EXPECT_TRUE(options->GetString("filePath", &event_file_path)); 148 EXPECT_EQ(kFilePath, event_file_path); 149 150 std::string event_file_open_mode; 151 EXPECT_TRUE(options->GetString("mode", &event_file_open_mode)); 152 const std::string expected_file_open_mode = 153 extensions::api::file_system_provider::ToString( 154 extensions::api::file_system_provider::OPEN_FILE_MODE_READ); 155 EXPECT_EQ(expected_file_open_mode, event_file_open_mode); 156 157 bool event_create; 158 EXPECT_TRUE(options->GetBoolean("create", &event_create)); 159 EXPECT_FALSE(event_create); 160 } 161 162 TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_NoListener) { 163 LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */); 164 CallbackLogger callback_logger; 165 166 OpenFile open_file( 167 NULL, 168 file_system_info_, 169 base::FilePath::FromUTF8Unsafe(kFilePath), 170 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, 171 false /* create */, 172 base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr())); 173 open_file.SetDispatchEventImplForTesting( 174 base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl, 175 base::Unretained(&dispatcher))); 176 177 EXPECT_FALSE(open_file.Execute(kRequestId)); 178 } 179 180 TEST_F(FileSystemProviderOperationsOpenFileTest, OnSuccess) { 181 using extensions::api::file_system_provider_internal:: 182 OpenFileRequestedSuccess::Params; 183 184 LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); 185 CallbackLogger callback_logger; 186 187 OpenFile open_file( 188 NULL, 189 file_system_info_, 190 base::FilePath::FromUTF8Unsafe(kFilePath), 191 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, 192 false /* create */, 193 base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr())); 194 open_file.SetDispatchEventImplForTesting( 195 base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl, 196 base::Unretained(&dispatcher))); 197 198 EXPECT_TRUE(open_file.Execute(kRequestId)); 199 200 open_file.OnSuccess(kRequestId, 201 scoped_ptr<RequestValue>(new RequestValue()), 202 false /* 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()); 206 EXPECT_LT(0, event->file_handle()); 207 } 208 209 TEST_F(FileSystemProviderOperationsOpenFileTest, OnError) { 210 using extensions::api::file_system_provider_internal::OpenFileRequestedError:: 211 Params; 212 213 LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); 214 CallbackLogger callback_logger; 215 216 OpenFile open_file( 217 NULL, 218 file_system_info_, 219 base::FilePath::FromUTF8Unsafe(kFilePath), 220 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, 221 false /* create */, 222 base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr())); 223 open_file.SetDispatchEventImplForTesting( 224 base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl, 225 base::Unretained(&dispatcher))); 226 227 EXPECT_TRUE(open_file.Execute(kRequestId)); 228 229 open_file.OnError(kRequestId, base::File::FILE_ERROR_TOO_MANY_OPENED); 230 ASSERT_EQ(1u, callback_logger.events().size()); 231 CallbackLogger::Event* event = callback_logger.events()[0]; 232 EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, event->result()); 233 ASSERT_EQ(0, event->file_handle()); 234 } 235 236 } // namespace operations 237 } // namespace file_system_provider 238 } // namespace chromeos 239