Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Side by Side Diff: chrome/browser/chromeos/extensions/file_manager_browsertest.cc

Issue 13779002: chromeos: Add a subdirectory "file_manager" to chrome/browser/chromeos/extensions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 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 // Browser test for basic Chrome OS file manager functionality:
6 // - The file list is updated when a file is added externally to the Downloads
7 // folder.
8 // - Selecting a file and copy-pasting it with the keyboard copies the file.
9 // - Selecting a file and pressing delete deletes it.
10
11 #include <algorithm>
12 #include <string>
13
14 #include "base/callback.h"
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_path_watcher.h"
18 #include "base/platform_file.h"
19 #include "base/threading/platform_thread.h"
20 #include "base/time.h"
21 #include "base/utf_string_conversions.h"
22 #include "chrome/browser/extensions/component_loader.h"
23 #include "chrome/browser/extensions/extension_apitest.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/extension_test_message_listener.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/extensions/extension.h"
31 #include "chrome/test/base/ui_test_utils.h"
32 #include "chromeos/chromeos_switches.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/render_view_host.h"
35 #include "net/base/escape.h"
36 #include "webkit/fileapi/external_mount_points.h"
37
38 namespace {
39
40 const char kFileManagerExtensionId[] = "hhaomjibdihmijegdhdafkllkbggdgoj";
41
42 const char kKeyboardTestFileName[] = "world.mpeg";
43 const int64 kKeyboardTestFileSize = 1000;
44 const char kKeyboardTestFileCopyName[] = "world (1).mpeg";
45
46 // The base test class. Used by FileManagerBrowserLocalTest and
47 // FileManagerBrowserDriveTest.
48 // TODO(satorux): Add the latter: crbug.com/224534.
49 class FileManagerBrowserTestBase : public ExtensionApiTest {
50 protected:
51 // Loads the file manager extension, navigating it to |directory_path| for
52 // testing, and waits for it to finish initializing. This is invoked at the
53 // start of each test (it crashes if run in SetUp).
54 void StartFileManager(const std::string& directory_path);
55
56 // Loads our testing extension and sends it a string identifying the current
57 // test.
58 void StartTest(const std::string& test_name);
59 };
60
61 void FileManagerBrowserTestBase::StartFileManager(
62 const std::string& directory_path) {
63 std::string file_manager_url =
64 (std::string("chrome-extension://") +
65 kFileManagerExtensionId +
66 "/main.html#" +
67 net::EscapeQueryParamValue(directory_path, false /* use_plus */));
68
69 ui_test_utils::NavigateToURL(browser(), GURL(file_manager_url));
70
71 // This is sent by the file manager when it's finished initializing.
72 ExtensionTestMessageListener listener("worker-initialized", false);
73 ASSERT_TRUE(listener.WaitUntilSatisfied());
74 }
75
76 void FileManagerBrowserTestBase::StartTest(const std::string& test_name) {
77 base::FilePath path = test_data_dir_.AppendASCII("file_manager_browsertest");
78 const extensions::Extension* extension = LoadExtensionAsComponent(path);
79 ASSERT_TRUE(extension);
80
81 ExtensionTestMessageListener listener("which test", true);
82 ASSERT_TRUE(listener.WaitUntilSatisfied());
83 listener.Reply(test_name);
84 }
85
86 // The boolean parameter, retrieved by GetParam(), is true if testing in the
87 // guest mode. See SetUpCommandLine() below for details.
88 class FileManagerBrowserLocalTest : public FileManagerBrowserTestBase,
89 public ::testing::WithParamInterface<bool> {
90 public:
91 virtual void SetUp() OVERRIDE {
92 extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
93
94 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
95 downloads_path_ = tmp_dir_.path().Append("Downloads");
96 ASSERT_TRUE(file_util::CreateDirectory(downloads_path_));
97
98 CreateTestFile("hello.txt", 123, "4 Sep 1998 12:34:56");
99 CreateTestFile("My Desktop Background.png", 1024, "18 Jan 2038 01:02:03");
100 CreateTestFile(kKeyboardTestFileName, kKeyboardTestFileSize,
101 "4 July 2012 10:35:00");
102 CreateTestDirectory("photos", "1 Jan 1980 23:59:59");
103 // Files starting with . are filtered out in
104 // file_manager/js/directory_contents.js, so this should not be shown.
105 CreateTestDirectory(".warez", "26 Oct 1985 13:39");
106
107 ExtensionApiTest::SetUp();
108 }
109
110 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
111 bool in_guest_mode = GetParam();
112 if (in_guest_mode) {
113 command_line->AppendSwitch(chromeos::switches::kGuestSession);
114 command_line->AppendSwitch(switches::kIncognito);
115 }
116 ExtensionApiTest::SetUpCommandLine(command_line);
117 }
118
119 protected:
120 // Creates a file with the given |name|, |length|, and |modification_time|.
121 void CreateTestFile(const std::string& name,
122 int length,
123 const std::string& modification_time);
124
125 // Creates an empty directory with the given |name| and |modification_time|.
126 void CreateTestDirectory(const std::string& name,
127 const std::string& modification_time);
128
129 // Add a mount point to the fake Downloads directory. Should be called
130 // before StartFileManager().
131 void AddMountPointToFakeDownloads();
132
133 // Path to the fake Downloads directory used in the test.
134 base::FilePath downloads_path_;
135
136 private:
137 base::ScopedTempDir tmp_dir_;
138 };
139
140 INSTANTIATE_TEST_CASE_P(InGuestMode,
141 FileManagerBrowserLocalTest,
142 ::testing::Values(true));
143
144 INSTANTIATE_TEST_CASE_P(InNonGuestMode,
145 FileManagerBrowserLocalTest,
146 ::testing::Values(false));
147
148 void FileManagerBrowserLocalTest::CreateTestFile(
149 const std::string& name,
150 int length,
151 const std::string& modification_time) {
152 ASSERT_GE(length, 0);
153 base::FilePath path = downloads_path_.AppendASCII(name);
154 int flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
155 bool created = false;
156 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
157 base::PlatformFile file = base::CreatePlatformFile(path, flags,
158 &created, &error);
159 ASSERT_TRUE(created);
160 ASSERT_FALSE(error) << error;
161 ASSERT_TRUE(base::TruncatePlatformFile(file, length));
162 ASSERT_TRUE(base::ClosePlatformFile(file));
163 base::Time time;
164 ASSERT_TRUE(base::Time::FromString(modification_time.c_str(), &time));
165 ASSERT_TRUE(file_util::SetLastModifiedTime(path, time));
166 }
167
168 void FileManagerBrowserLocalTest::CreateTestDirectory(
169 const std::string& name,
170 const std::string& modification_time) {
171 base::FilePath path = downloads_path_.AppendASCII(name);
172 ASSERT_TRUE(file_util::CreateDirectory(path));
173 base::Time time;
174 ASSERT_TRUE(base::Time::FromString(modification_time.c_str(), &time));
175 ASSERT_TRUE(file_util::SetLastModifiedTime(path, time));
176 }
177
178 void FileManagerBrowserLocalTest::AddMountPointToFakeDownloads() {
179 // Install our fake Downloads mount point first.
180 fileapi::ExternalMountPoints* mount_points =
181 content::BrowserContext::GetMountPoints(profile());
182 ASSERT_TRUE(mount_points->RevokeFileSystem("Downloads"));
183 ASSERT_TRUE(mount_points->RegisterFileSystem(
184 "Downloads", fileapi::kFileSystemTypeNativeLocal, downloads_path_));
185 }
186
187 // Monitors changes to a single file until the supplied condition callback
188 // returns true. Usage:
189 // TestFilePathWatcher watcher(path_to_file, MyConditionCallback);
190 // watcher.StartAndWaitUntilReady();
191 // ... trigger filesystem modification ...
192 // watcher.RunMessageLoopUntilConditionSatisfied();
193 class TestFilePathWatcher {
194 public:
195 typedef base::Callback<bool(const base::FilePath& file_path)>
196 ConditionCallback;
197
198 // Stores the supplied |path| and |condition| for later use (no side effects).
199 TestFilePathWatcher(const base::FilePath& path,
200 const ConditionCallback& condition);
201
202 // Waits (running a message pump) until the callback returns true or
203 // FilePathWatcher reports an error. Return true on success.
204 bool RunMessageLoopUntilConditionSatisfied();
205
206 private:
207 // Starts the FilePathWatcher to watch the target file. Also check if the
208 // condition is already met.
209 void StartWatching();
210
211 // FilePathWatcher callback (on the FILE thread). Posts Done() to the UI
212 // thread when the condition is satisfied or there is an error.
213 void FilePathWatcherCallback(const base::FilePath& path, bool error);
214
215 const base::FilePath path_;
216 ConditionCallback condition_;
217 scoped_ptr<base::FilePathWatcher> watcher_;
218 base::RunLoop run_loop_;
219 base::Closure quit_closure_;
220 bool failed_;
221 };
222
223 TestFilePathWatcher::TestFilePathWatcher(const base::FilePath& path,
224 const ConditionCallback& condition)
225 : path_(path),
226 condition_(condition),
227 quit_closure_(run_loop_.QuitClosure()),
228 failed_(false) {
229 }
230
231 void TestFilePathWatcher::StartWatching() {
232 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
233
234 watcher_.reset(new base::FilePathWatcher);
235 bool ok = watcher_->Watch(
236 path_, false /*recursive*/,
237 base::Bind(&TestFilePathWatcher::FilePathWatcherCallback,
238 base::Unretained(this)));
239 DCHECK(ok);
240
241 // If the condition was already met before FilePathWatcher was launched,
242 // FilePathWatcher won't be able to detect a change, so check the condition
243 // here.
244 if (condition_.Run(path_)) {
245 watcher_.reset();
246 content::BrowserThread::PostTask(content::BrowserThread::UI,
247 FROM_HERE,
248 quit_closure_);
249 return;
250 }
251 }
252
253 void TestFilePathWatcher::FilePathWatcherCallback(const base::FilePath& path,
254 bool failed) {
255 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
256 DCHECK_EQ(path_.value(), path.value());
257
258 if (failed || condition_.Run(path)) {
259 failed_ = failed;
260 watcher_.reset();
261 content::BrowserThread::PostTask(content::BrowserThread::UI,
262 FROM_HERE,
263 quit_closure_);
264 }
265 }
266
267 bool TestFilePathWatcher::RunMessageLoopUntilConditionSatisfied() {
268 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
269
270 content::BrowserThread::PostTask(
271 content::BrowserThread::FILE,
272 FROM_HERE,
273 base::Bind(&TestFilePathWatcher::StartWatching,
274 base::Unretained(this)));
275
276 // Wait until the condition is met.
277 run_loop_.Run();
278 return !failed_;
279 }
280
281 // Returns true if a file with the given size is present at |path|.
282 bool FilePresentWithSize(const int64 file_size,
283 const base::FilePath& path) {
284 int64 copy_size = 0;
285 // If the file doesn't exist yet this will fail and we'll keep waiting.
286 if (!file_util::GetFileSize(path, &copy_size))
287 return false;
288 return (copy_size == file_size);
289 }
290
291 // Returns true if a file is not present at |path|.
292 bool FileNotPresent(const base::FilePath& path) {
293 return !file_util::PathExists(path);
294 };
295
296 IN_PROC_BROWSER_TEST_P(FileManagerBrowserLocalTest, TestFileDisplay) {
297 AddMountPointToFakeDownloads();
298 StartFileManager("/Downloads");
299
300 ResultCatcher catcher;
301
302 StartTest("file display");
303
304 ExtensionTestMessageListener listener("initial check done", true);
305 ASSERT_TRUE(listener.WaitUntilSatisfied());
306 CreateTestFile("newly added file.mp3", 2000, "4 Sep 1998 00:00:00");
307 listener.Reply("file added");
308
309 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
310 }
311
312 IN_PROC_BROWSER_TEST_P(FileManagerBrowserLocalTest, TestKeyboardCopy) {
313 AddMountPointToFakeDownloads();
314 StartFileManager("/Downloads");
315
316 base::FilePath copy_path =
317 downloads_path_.AppendASCII(kKeyboardTestFileCopyName);
318 ASSERT_FALSE(file_util::PathExists(copy_path));
319
320 ResultCatcher catcher;
321 StartTest("keyboard copy");
322
323 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
324
325 TestFilePathWatcher watcher(
326 copy_path,
327 base::Bind(FilePresentWithSize, kKeyboardTestFileSize));
328 ASSERT_TRUE(watcher.RunMessageLoopUntilConditionSatisfied());
329
330 // Check that it was a copy, not a move.
331 base::FilePath source_path =
332 downloads_path_.AppendASCII(kKeyboardTestFileName);
333 ASSERT_TRUE(file_util::PathExists(source_path));
334 }
335
336 IN_PROC_BROWSER_TEST_P(FileManagerBrowserLocalTest, TestKeyboardDelete) {
337 AddMountPointToFakeDownloads();
338 StartFileManager("/Downloads");
339
340 base::FilePath delete_path =
341 downloads_path_.AppendASCII(kKeyboardTestFileName);
342 ASSERT_TRUE(file_util::PathExists(delete_path));
343
344 ResultCatcher catcher;
345 StartTest("keyboard delete");
346 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
347
348 TestFilePathWatcher watcher(delete_path,
349 base::Bind(FileNotPresent));
350 ASSERT_TRUE(watcher.RunMessageLoopUntilConditionSatisfied());
351 }
352
353 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698