Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / file_manager / file_browser_handler_api_test.cc
1 // Copyright (c) 2012 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 // File contains browser tests for the fileBrowserHandler api.
6
7 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h"
8
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_apitest.h"
15 #include "chrome/browser/extensions/extension_function_test_utils.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/browser_context.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/test/result_catcher.h"
23 #include "storage/browser/fileapi/external_mount_points.h"
24 #include "storage/common/fileapi/file_system_types.h"
25
26 namespace utils = extension_function_test_utils;
27
28 using content::BrowserContext;
29 using extensions::Extension;
30
31 namespace {
32
33 // Data that defines FileSelector behaviour in each test case.
34 struct TestCase {
35   TestCase(const base::FilePath& suggested_name,
36            const std::vector<std::string>& allowed_extensions,
37            bool success,
38            const base::FilePath& selected_path)
39       : suggested_name(suggested_name),
40         allowed_extensions(allowed_extensions),
41         success(success),
42         selected_path(selected_path) {
43   }
44   ~TestCase() {}
45
46   // Path that we expect to be suggested to the file selector.
47   base::FilePath suggested_name;
48
49   // Extensions that we expect to be allowed to the file selector.
50   std::vector<std::string> allowed_extensions;
51
52   // Whether file selector should fail.
53   bool success;
54   // The path file selector should return back to the function.
55   base::FilePath selected_path;
56 };
57
58 // Checks that file under path |selected_path| contains |expected_contents|.
59 // Must be called on the file thread.
60 void ExpectFileContentEquals(const base::FilePath& selected_path,
61                              const std::string& expected_contents) {
62   std::string test_file_contents;
63   ASSERT_TRUE(base::ReadFileToString(selected_path, &test_file_contents));
64   EXPECT_EQ(expected_contents, test_file_contents);
65 }
66
67 // Mocks FileSelector used by FileBrowserHandlerInternalSelectFileFunction.
68 // When |SelectFile| is called, it will check that file name suggestion is as
69 // expected, and respond to the extension function with specified selection
70 // results.
71 class MockFileSelector : public file_manager::FileSelector {
72  public:
73   MockFileSelector(const base::FilePath& suggested_name,
74                    const std::vector<std::string>& allowed_extensions,
75                    bool success,
76                    const base::FilePath& selected_path)
77       : suggested_name_(suggested_name),
78         allowed_extensions_(allowed_extensions),
79         success_(success),
80         selected_path_(selected_path) {
81   }
82   virtual ~MockFileSelector() {}
83
84   // file_manager::FileSelector implementation.
85   // |browser| is not used.
86   virtual void SelectFile(
87       const base::FilePath& suggested_name,
88       const std::vector<std::string>& allowed_extensions,
89       Browser* browser,
90       FileBrowserHandlerInternalSelectFileFunction* function) override {
91     // Confirm that the function suggested us the right name.
92     EXPECT_EQ(suggested_name_, suggested_name);
93     // Confirm that the function allowed us the right extensions.
94     EXPECT_EQ(allowed_extensions_.size(), allowed_extensions.size());
95     if (allowed_extensions_.size() == allowed_extensions.size()) {
96       for (size_t i = 0; i < allowed_extensions_.size(); ++i) {
97         EXPECT_EQ(allowed_extensions_[i], allowed_extensions[i]);
98       }
99     }
100
101     // Send response to the extension function.
102     // The callback will take a reference to the function and keep it alive.
103     base::MessageLoopProxy::current()->PostTask(FROM_HERE,
104         base::Bind(&FileBrowserHandlerInternalSelectFileFunction::
105                        OnFilePathSelected,
106                    function, success_, selected_path_));
107     delete this;
108   }
109
110  private:
111   // File name that is expected to be suggested by the function.
112   base::FilePath suggested_name_;
113
114   // Extensions that is expected to be allowed by the function.
115   std::vector<std::string> allowed_extensions_;
116
117   // Whether the selection should succeed.
118   bool success_;
119   // File path that should be returned to the function.
120   base::FilePath selected_path_;
121
122   DISALLOW_COPY_AND_ASSIGN(MockFileSelector);
123 };
124
125 // Mocks file selector factory for the test.
126 // When |CreateFileSelector| is invoked it will create mock file selector for
127 // the extension function with test parameters from the object ctor.
128 class MockFileSelectorFactory : public file_manager::FileSelectorFactory {
129  public:
130   explicit MockFileSelectorFactory(const TestCase& test_case)
131       : suggested_name_(test_case.suggested_name),
132         allowed_extensions_(test_case.allowed_extensions),
133         success_(test_case.success),
134         selected_path_(test_case.selected_path) {
135   }
136   virtual ~MockFileSelectorFactory() {}
137
138   // file_manager::FileSelectorFactory implementation.
139   virtual file_manager::FileSelector* CreateFileSelector() const override {
140     return new MockFileSelector(suggested_name_,
141                                 allowed_extensions_,
142                                 success_,
143                                 selected_path_);
144   }
145
146  private:
147   // File name that is expected to be suggested by the function.
148   base::FilePath suggested_name_;
149   // Extensions that is expected to be allowed by the function.
150   std::vector<std::string> allowed_extensions_;
151   // Whether the selection should succeed.
152   bool success_;
153   // File path that should be returned to the function.
154   base::FilePath selected_path_;
155
156   DISALLOW_COPY_AND_ASSIGN(MockFileSelectorFactory);
157 };
158
159 // Extension api test for the fileBrowserHandler extension API.
160 class FileBrowserHandlerExtensionTest : public ExtensionApiTest {
161  protected:
162   virtual void SetUp() override {
163     // Create mount point directory that will be used in the test.
164     // Mount point will be called "tmp", and it will be located in a tmp
165     // directory with an unique name.
166     ASSERT_TRUE(scoped_tmp_dir_.CreateUniqueTempDir());
167     tmp_mount_point_ = scoped_tmp_dir_.path().Append("tmp");
168     base::CreateDirectory(tmp_mount_point_);
169
170     ExtensionApiTest::SetUp();
171   }
172
173   // Creates new, test mount point.
174   void AddTmpMountPoint(const std::string& extension_id) {
175     BrowserContext::GetMountPoints(browser()->profile())
176         ->RegisterFileSystem("tmp",
177                              storage::kFileSystemTypeNativeLocal,
178                              storage::FileSystemMountOption(),
179                              tmp_mount_point_);
180   }
181
182   base::FilePath GetFullPathOnTmpMountPoint(
183       const base::FilePath& relative_path) {
184     return tmp_mount_point_.Append(relative_path);
185   }
186
187   // Creates a new FileBrowserHandlerInternalSelectFileFunction to be used in
188   // the test.  This function will be called from ExtensionFunctinoDispatcher
189   // whenever an extension function for fileBrowserHandlerInternal.selectFile
190   // will be needed.
191   static ExtensionFunction* TestSelectFileFunctionFactory() {
192     EXPECT_TRUE(test_cases_);
193     EXPECT_TRUE(!test_cases_ || current_test_case_ < test_cases_->size());
194
195     // If this happens, test failed. But, we still don't want to crash, so
196     // return valid extension function.
197     if (!test_cases_ || current_test_case_ >= test_cases_->size())
198       return new FileBrowserHandlerInternalSelectFileFunction();
199
200     // Create file creator factory for the current test case.
201     MockFileSelectorFactory* mock_factory =
202         new MockFileSelectorFactory(test_cases_->at(current_test_case_));
203     current_test_case_++;
204
205     return new FileBrowserHandlerInternalSelectFileFunction(
206         mock_factory, false);
207   }
208
209   // Sets up test parameters for extension function invocations that will be
210   // made during the test.
211   void SetTestCases(const std::vector<TestCase>* test_cases) {
212     test_cases_ = test_cases;
213     current_test_case_ = 0;
214   }
215
216  private:
217   // List of test parameters for each extension function invocation that will be
218   // made during a test.
219   // Should be owned by the test code.
220   static const std::vector<TestCase>* test_cases_;
221   static size_t current_test_case_;
222
223   base::ScopedTempDir scoped_tmp_dir_;
224   // Our test mount point path.
225   base::FilePath tmp_mount_point_;
226 };
227
228 const std::vector<TestCase>* FileBrowserHandlerExtensionTest::test_cases_ =
229     NULL;
230 size_t FileBrowserHandlerExtensionTest::current_test_case_ = 0;
231
232 // End to end test that verifies that fileBrowserHandler.selectFile works as
233 // expected. It will run test extension under
234 // chrome/test/data/extensions/api_test/file_browser/filehandler_create.
235 // The extension will invoke fileBrowserHandler.selectFile function twice.
236 // Once with suggested name "some_file_name.txt", and once with suggested name
237 // "fail". The file selection should succeed the first time, but fail the second
238 // time. When the file is selected the test extension will verify that it can
239 // create, read and write the file under the selected file path.
240 IN_PROC_BROWSER_TEST_F(FileBrowserHandlerExtensionTest, EndToEnd) {
241   // Path that will be "selected" by file selector.
242   const base::FilePath selected_path =
243       GetFullPathOnTmpMountPoint(base::FilePath("test_file.txt"));
244
245   std::vector<std::string> allowed_extensions;
246   allowed_extensions.push_back("txt");
247   allowed_extensions.push_back("html");
248
249   std::vector<TestCase> test_cases;
250   test_cases.push_back(
251       TestCase(base::FilePath("some_file_name.txt"),
252                allowed_extensions,
253                true,
254                selected_path));
255   test_cases.push_back(
256       TestCase(base::FilePath("fail"),
257                std::vector<std::string>(),
258                false,
259                base::FilePath()));
260
261   SetTestCases(&test_cases);
262
263   // Override extension function that will be used during the test.
264   ASSERT_TRUE(extensions::ExtensionFunctionDispatcher::OverrideFunction(
265       "fileBrowserHandlerInternal.selectFile",
266       FileBrowserHandlerExtensionTest::TestSelectFileFunctionFactory));
267
268   // Selected path should still not exist.
269   ASSERT_FALSE(base::PathExists(selected_path));
270
271   const Extension* extension = LoadExtension(
272       test_data_dir_.AppendASCII("file_browser/filehandler_create"));
273   ASSERT_TRUE(extension) << message_;
274
275   AddTmpMountPoint(extension->id());
276
277   extensions::ResultCatcher catcher;
278
279   GURL url = extension->GetResourceURL("test.html");
280   ui_test_utils::NavigateToURL(browser(), url);
281
282   ASSERT_TRUE(catcher.GetNextResult()) << message_;
283
284   // Selected path should have been created by the test extension after the
285   // extension function call.
286   ASSERT_TRUE(base::PathExists(selected_path));
287
288   // Let's check that the file has the expected content.
289   const std::string expected_contents = "hello from test extension.";
290   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
291       base::Bind(&ExpectFileContentEquals, selected_path, expected_contents));
292
293   // Make sure test doesn't finish until we check on file thread that the
294   // selected file's content is as expected.
295   content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
296
297   SetTestCases(NULL);
298 }
299
300 // Tests that verifies the fileBrowserHandlerInternal.selectFile function fails
301 // when invoked without user gesture.
302 IN_PROC_BROWSER_TEST_F(FileBrowserHandlerExtensionTest, NoUserGesture) {
303   scoped_refptr<FileBrowserHandlerInternalSelectFileFunction>
304       select_file_function(
305           new FileBrowserHandlerInternalSelectFileFunction());
306
307   std::string error =
308       utils::RunFunctionAndReturnError(
309           select_file_function.get(),
310           "[{\"suggestedName\": \"foo\"}]",
311           browser());
312
313   const std::string expected_error =
314       "This method can only be called in response to user gesture, such as a "
315       "mouse click or key press.";
316   EXPECT_EQ(expected_error, error);
317 }
318
319 // Tests that checks that the fileHandlerInternal.selectFile function returns
320 // dictionary with |success == false| and no file entry when user cancels file
321 // selection.
322 IN_PROC_BROWSER_TEST_F(FileBrowserHandlerExtensionTest, SelectionFailed) {
323   TestCase test_case(base::FilePath("some_file_name.txt"),
324                      std::vector<std::string>(),
325                      false,
326                      base::FilePath());
327
328   scoped_refptr<FileBrowserHandlerInternalSelectFileFunction>
329       select_file_function(
330           new FileBrowserHandlerInternalSelectFileFunction(
331               new MockFileSelectorFactory(test_case),
332               false));
333
334   select_file_function->set_has_callback(true);
335   select_file_function->set_user_gesture(true);
336
337   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
338       utils::RunFunctionAndReturnSingleResult(
339           select_file_function.get(),
340           "[{\"suggestedName\": \"some_file_name.txt\"}]",
341           browser())));
342
343   EXPECT_FALSE(utils::GetBoolean(result.get(), "success"));
344   base::DictionaryValue* entry_info;
345   EXPECT_FALSE(result->GetDictionary("entry", &entry_info));
346 }
347
348 // Tests that user cannot be suggested a full file path when selecting a file,
349 // only a file name (i.e. that extension function caller has no influence on
350 // which directory contents will be initially displayed in selection dialog).
351 IN_PROC_BROWSER_TEST_F(FileBrowserHandlerExtensionTest, SuggestedFullPath) {
352   TestCase test_case(base::FilePath("some_file_name.txt"),
353                      std::vector<std::string>(),
354                      false,
355                      base::FilePath());
356
357   scoped_refptr<FileBrowserHandlerInternalSelectFileFunction>
358       select_file_function(
359           new FileBrowserHandlerInternalSelectFileFunction(
360               new MockFileSelectorFactory(test_case),
361               false));
362
363   select_file_function->set_has_callback(true);
364   select_file_function->set_user_gesture(true);
365
366   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
367       utils::RunFunctionAndReturnSingleResult(
368           select_file_function.get(),
369           "[{\"suggestedName\": \"/path_to_file/some_file_name.txt\"}]",
370           browser())));
371
372   EXPECT_FALSE(utils::GetBoolean(result.get(), "success"));
373   base::DictionaryValue* entry_info;
374   EXPECT_FALSE(result->GetDictionary("entry", &entry_info));
375 }
376
377 }  // namespace