Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_manager / file_manager_browsertest.cc
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 <deque>
12 #include <string>
13
14 #include "apps/app_window.h"
15 #include "apps/app_window_registry.h"
16 #include "ash/session/session_state_delegate.h"
17 #include "ash/shell.h"
18 #include "base/bind.h"
19 #include "base/callback.h"
20 #include "base/file_util.h"
21 #include "base/files/file_path.h"
22 #include "base/json/json_reader.h"
23 #include "base/json/json_value_converter.h"
24 #include "base/json/json_writer.h"
25 #include "base/prefs/pref_service.h"
26 #include "base/strings/string_piece.h"
27 #include "base/strings/stringprintf.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/time/time.h"
30 #include "chrome/browser/browser_process.h"
31 #include "chrome/browser/chrome_notification_types.h"
32 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
33 #include "chrome/browser/chromeos/drive/file_system_interface.h"
34 #include "chrome/browser/chromeos/drive/test_util.h"
35 #include "chrome/browser/chromeos/file_manager/app_id.h"
36 #include "chrome/browser/chromeos/file_manager/drive_test_util.h"
37 #include "chrome/browser/chromeos/file_manager/path_util.h"
38 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
39 #include "chrome/browser/chromeos/login/user_manager.h"
40 #include "chrome/browser/chromeos/profiles/profile_helper.h"
41 #include "chrome/browser/drive/fake_drive_service.h"
42 #include "chrome/browser/extensions/component_loader.h"
43 #include "chrome/browser/extensions/extension_apitest.h"
44 #include "chrome/browser/extensions/extension_test_message_listener.h"
45 #include "chrome/browser/profiles/profile.h"
46 #include "chrome/browser/profiles/profile_manager.h"
47 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
48 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
49 #include "chrome/common/chrome_switches.h"
50 #include "chrome/common/pref_names.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "content/public/browser/browser_context.h"
53 #include "content/public/browser/notification_service.h"
54 #include "content/public/test/test_utils.h"
55 #include "extensions/browser/api/test/test_api.h"
56 #include "extensions/common/extension.h"
57 #include "google_apis/drive/gdata_wapi_parser.h"
58 #include "google_apis/drive/test_util.h"
59 #include "net/test/embedded_test_server/embedded_test_server.h"
60 #include "webkit/browser/fileapi/external_mount_points.h"
61
62 using drive::DriveIntegrationServiceFactory;
63
64 namespace file_manager {
65 namespace {
66
67 enum EntryType {
68   FILE,
69   DIRECTORY,
70 };
71
72 enum TargetVolume { LOCAL_VOLUME, DRIVE_VOLUME, USB_VOLUME, };
73
74 enum SharedOption {
75   NONE,
76   SHARED,
77 };
78
79 enum GuestMode {
80   NOT_IN_GUEST_MODE,
81   IN_GUEST_MODE,
82 };
83
84 // This global operator is used from Google Test to format error messages.
85 std::ostream& operator<<(std::ostream& os, const GuestMode& guest_mode) {
86   return os << (guest_mode == IN_GUEST_MODE ?
87                 "IN_GUEST_MODE" : "NOT_IN_GUEST_MODE");
88 }
89
90 // Maps the given string to EntryType. Returns true on success.
91 bool MapStringToEntryType(const base::StringPiece& value, EntryType* output) {
92   if (value == "file")
93     *output = FILE;
94   else if (value == "directory")
95     *output = DIRECTORY;
96   else
97     return false;
98   return true;
99 }
100
101 // Maps the given string to SharedOption. Returns true on success.
102 bool MapStringToSharedOption(const base::StringPiece& value,
103                              SharedOption* output) {
104   if (value == "shared")
105     *output = SHARED;
106   else if (value == "none")
107     *output = NONE;
108   else
109     return false;
110   return true;
111 }
112
113 // Maps the given string to TargetVolume. Returns true on success.
114 bool MapStringToTargetVolume(const base::StringPiece& value,
115                              TargetVolume* output) {
116   if (value == "drive")
117     *output = DRIVE_VOLUME;
118   else if (value == "local")
119     *output = LOCAL_VOLUME;
120   else if (value == "usb")
121     *output = USB_VOLUME;
122   else
123     return false;
124   return true;
125 }
126
127 // Maps the given string to base::Time. Returns true on success.
128 bool MapStringToTime(const base::StringPiece& value, base::Time* time) {
129   return base::Time::FromString(value.as_string().c_str(), time);
130 }
131
132 // Test data of file or directory.
133 struct TestEntryInfo {
134   TestEntryInfo() : type(FILE), shared_option(NONE) {}
135
136   TestEntryInfo(EntryType type,
137                 const std::string& source_file_name,
138                 const std::string& target_path,
139                 const std::string& mime_type,
140                 SharedOption shared_option,
141                 const base::Time& last_modified_time) :
142       type(type),
143       source_file_name(source_file_name),
144       target_path(target_path),
145       mime_type(mime_type),
146       shared_option(shared_option),
147       last_modified_time(last_modified_time) {
148   }
149
150   EntryType type;
151   std::string source_file_name;  // Source file name to be used as a prototype.
152   std::string target_path;  // Target file or directory path.
153   std::string mime_type;
154   SharedOption shared_option;
155   base::Time last_modified_time;
156
157   // Registers the member information to the given converter.
158   static void RegisterJSONConverter(
159       base::JSONValueConverter<TestEntryInfo>* converter);
160 };
161
162 // static
163 void TestEntryInfo::RegisterJSONConverter(
164     base::JSONValueConverter<TestEntryInfo>* converter) {
165   converter->RegisterCustomField("type",
166                                  &TestEntryInfo::type,
167                                  &MapStringToEntryType);
168   converter->RegisterStringField("sourceFileName",
169                                  &TestEntryInfo::source_file_name);
170   converter->RegisterStringField("targetPath", &TestEntryInfo::target_path);
171   converter->RegisterStringField("mimeType", &TestEntryInfo::mime_type);
172   converter->RegisterCustomField("sharedOption",
173                                  &TestEntryInfo::shared_option,
174                                  &MapStringToSharedOption);
175   converter->RegisterCustomField("lastModifiedTime",
176                                  &TestEntryInfo::last_modified_time,
177                                  &MapStringToTime);
178 }
179
180 // Message from JavaScript to add entries.
181 struct AddEntriesMessage {
182   // Target volume to be added the |entries|.
183   TargetVolume volume;
184
185   // Entries to be added.
186   ScopedVector<TestEntryInfo> entries;
187
188   // Registers the member information to the given converter.
189   static void RegisterJSONConverter(
190       base::JSONValueConverter<AddEntriesMessage>* converter);
191 };
192
193
194 // static
195 void AddEntriesMessage::RegisterJSONConverter(
196     base::JSONValueConverter<AddEntriesMessage>* converter) {
197   converter->RegisterCustomField("volume",
198                                  &AddEntriesMessage::volume,
199                                  &MapStringToTargetVolume);
200   converter->RegisterRepeatedMessage<TestEntryInfo>(
201       "entries",
202       &AddEntriesMessage::entries);
203 }
204
205 // Test volume.
206 class TestVolume {
207  protected:
208   explicit TestVolume(const std::string& name) : name_(name) {}
209   virtual ~TestVolume() {}
210
211   bool CreateRootDirectory(const Profile* profile) {
212     return root_.Set(profile->GetPath().Append(name_));
213   }
214
215   const std::string& name() { return name_; }
216   const base::FilePath root_path() { return root_.path(); }
217
218  private:
219   std::string name_;
220   base::ScopedTempDir root_;
221 };
222
223 // The local volume class for test.
224 // This class provides the operations for a test volume that simulates local
225 // drive.
226 class LocalTestVolume : public TestVolume {
227  public:
228   explicit LocalTestVolume(const std::string& name) : TestVolume(name) {}
229   virtual ~LocalTestVolume() {}
230
231   // Adds this volume to the file system as a local volume. Returns true on
232   // success.
233   virtual bool Mount(Profile* profile) = 0;
234
235   void CreateEntry(const TestEntryInfo& entry) {
236     const base::FilePath target_path =
237         root_path().AppendASCII(entry.target_path);
238
239     entries_.insert(std::make_pair(target_path, entry));
240     switch (entry.type) {
241       case FILE: {
242         const base::FilePath source_path =
243             google_apis::test_util::GetTestFilePath("chromeos/file_manager").
244             AppendASCII(entry.source_file_name);
245         ASSERT_TRUE(base::CopyFile(source_path, target_path))
246             << "Copy from " << source_path.value()
247             << " to " << target_path.value() << " failed.";
248         break;
249       }
250       case DIRECTORY:
251         ASSERT_TRUE(base::CreateDirectory(target_path)) <<
252             "Failed to create a directory: " << target_path.value();
253         break;
254     }
255     ASSERT_TRUE(UpdateModifiedTime(entry));
256   }
257
258  private:
259   // Updates ModifiedTime of the entry and its parents by referring
260   // TestEntryInfo. Returns true on success.
261   bool UpdateModifiedTime(const TestEntryInfo& entry) {
262     const base::FilePath path = root_path().AppendASCII(entry.target_path);
263     if (!base::TouchFile(path, entry.last_modified_time,
264                          entry.last_modified_time))
265       return false;
266
267     // Update the modified time of parent directories because it may be also
268     // affected by the update of child items.
269     if (path.DirName() != root_path()) {
270       const std::map<base::FilePath, const TestEntryInfo>::iterator it =
271           entries_.find(path.DirName());
272       if (it == entries_.end())
273         return false;
274       return UpdateModifiedTime(it->second);
275     }
276     return true;
277   }
278
279   std::map<base::FilePath, const TestEntryInfo> entries_;
280 };
281
282 class DownloadsTestVolume : public LocalTestVolume {
283  public:
284   DownloadsTestVolume() : LocalTestVolume("Downloads") {}
285   virtual ~DownloadsTestVolume() {}
286
287   virtual bool Mount(Profile* profile) OVERRIDE {
288     return CreateRootDirectory(profile) &&
289            VolumeManager::Get(profile)
290                ->RegisterDownloadsDirectoryForTesting(root_path());
291   }
292 };
293
294 class FakeUsbTestVolume : public LocalTestVolume {
295  public:
296   FakeUsbTestVolume() : LocalTestVolume("fake-usb") {}
297   virtual ~FakeUsbTestVolume() {}
298
299   virtual bool Mount(Profile* profile) OVERRIDE {
300     if (!CreateRootDirectory(profile))
301       return false;
302     fileapi::ExternalMountPoints* const mount_points =
303         fileapi::ExternalMountPoints::GetSystemInstance();
304
305     // First revoke the existing mount point (if any).
306     mount_points->RevokeFileSystem(name());
307     const bool result =
308         mount_points->RegisterFileSystem(name(),
309                                          fileapi::kFileSystemTypeNativeLocal,
310                                          fileapi::FileSystemMountOption(),
311                                          root_path());
312     if (!result)
313       return false;
314
315     VolumeManager::Get(profile)
316         ->AddVolumeInfoForTesting(root_path(),
317                                   VOLUME_TYPE_REMOVABLE_DISK_PARTITION,
318                                   chromeos::DEVICE_TYPE_USB);
319     return true;
320   }
321 };
322
323 // The drive volume class for test.
324 // This class provides the operations for a test volume that simulates Google
325 // drive.
326 class DriveTestVolume : public TestVolume {
327  public:
328   DriveTestVolume() : TestVolume("drive"), integration_service_(NULL) {}
329   virtual ~DriveTestVolume() {}
330
331   void CreateEntry(const TestEntryInfo& entry) {
332     const base::FilePath path =
333         base::FilePath::FromUTF8Unsafe(entry.target_path);
334     const std::string target_name = path.BaseName().AsUTF8Unsafe();
335
336     // Obtain the parent entry.
337     drive::FileError error = drive::FILE_ERROR_OK;
338     scoped_ptr<drive::ResourceEntry> parent_entry(new drive::ResourceEntry);
339     integration_service_->file_system()->GetResourceEntry(
340         drive::util::GetDriveMyDriveRootPath().Append(path).DirName(),
341         google_apis::test_util::CreateCopyResultCallback(
342             &error, &parent_entry));
343     drive::test_util::RunBlockingPoolTask();
344     ASSERT_EQ(drive::FILE_ERROR_OK, error);
345     ASSERT_TRUE(parent_entry);
346
347     switch (entry.type) {
348       case FILE:
349         CreateFile(entry.source_file_name,
350                    parent_entry->resource_id(),
351                    target_name,
352                    entry.mime_type,
353                    entry.shared_option == SHARED,
354                    entry.last_modified_time);
355         break;
356       case DIRECTORY:
357         CreateDirectory(
358             parent_entry->resource_id(), target_name, entry.last_modified_time);
359         break;
360     }
361   }
362
363   // Creates an empty directory with the given |name| and |modification_time|.
364   void CreateDirectory(const std::string& parent_id,
365                        const std::string& target_name,
366                        const base::Time& modification_time) {
367     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
368     scoped_ptr<google_apis::ResourceEntry> resource_entry;
369     fake_drive_service_->AddNewDirectory(
370         parent_id,
371         target_name,
372         drive::DriveServiceInterface::AddNewDirectoryOptions(),
373         google_apis::test_util::CreateCopyResultCallback(&error,
374                                                          &resource_entry));
375     base::MessageLoop::current()->RunUntilIdle();
376     ASSERT_EQ(google_apis::HTTP_CREATED, error);
377     ASSERT_TRUE(resource_entry);
378
379     fake_drive_service_->SetLastModifiedTime(
380         resource_entry->resource_id(),
381         modification_time,
382         google_apis::test_util::CreateCopyResultCallback(&error,
383                                                          &resource_entry));
384     base::MessageLoop::current()->RunUntilIdle();
385     ASSERT_TRUE(error == google_apis::HTTP_SUCCESS);
386     ASSERT_TRUE(resource_entry);
387     CheckForUpdates();
388   }
389
390   // Creates a test file with the given spec.
391   // Serves |test_file_name| file. Pass an empty string for an empty file.
392   void CreateFile(const std::string& source_file_name,
393                   const std::string& parent_id,
394                   const std::string& target_name,
395                   const std::string& mime_type,
396                   bool shared_with_me,
397                   const base::Time& modification_time) {
398     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
399
400     std::string content_data;
401     if (!source_file_name.empty()) {
402       base::FilePath source_file_path =
403           google_apis::test_util::GetTestFilePath("chromeos/file_manager").
404               AppendASCII(source_file_name);
405       ASSERT_TRUE(base::ReadFileToString(source_file_path, &content_data));
406     }
407
408     scoped_ptr<google_apis::ResourceEntry> resource_entry;
409     fake_drive_service_->AddNewFile(
410         mime_type,
411         content_data,
412         parent_id,
413         target_name,
414         shared_with_me,
415         google_apis::test_util::CreateCopyResultCallback(&error,
416                                                          &resource_entry));
417     base::MessageLoop::current()->RunUntilIdle();
418     ASSERT_EQ(google_apis::HTTP_CREATED, error);
419     ASSERT_TRUE(resource_entry);
420
421     fake_drive_service_->SetLastModifiedTime(
422         resource_entry->resource_id(),
423         modification_time,
424         google_apis::test_util::CreateCopyResultCallback(&error,
425                                                          &resource_entry));
426     base::MessageLoop::current()->RunUntilIdle();
427     ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
428     ASSERT_TRUE(resource_entry);
429
430     CheckForUpdates();
431   }
432
433   // Notifies FileSystem that the contents in FakeDriveService are
434   // changed, hence the new contents should be fetched.
435   void CheckForUpdates() {
436     if (integration_service_ && integration_service_->file_system()) {
437       integration_service_->file_system()->CheckForUpdates();
438     }
439   }
440
441   // Sets the url base for the test server to be used to generate share urls
442   // on the files and directories.
443   void ConfigureShareUrlBase(const GURL& share_url_base) {
444     fake_drive_service_->set_share_url_base(share_url_base);
445   }
446
447   drive::DriveIntegrationService* CreateDriveIntegrationService(
448       Profile* profile) {
449     profile_ = profile;
450     fake_drive_service_ = new drive::FakeDriveService;
451     fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
452
453     if (!CreateRootDirectory(profile))
454       return NULL;
455     integration_service_ = new drive::DriveIntegrationService(
456         profile, NULL, fake_drive_service_, std::string(), root_path(), NULL);
457     return integration_service_;
458   }
459
460  private:
461   Profile* profile_;
462   drive::FakeDriveService* fake_drive_service_;
463   drive::DriveIntegrationService* integration_service_;
464 };
465
466 // Listener to obtain the test relative messages synchronously.
467 class FileManagerTestListener : public content::NotificationObserver {
468  public:
469   struct Message {
470     int type;
471     std::string message;
472     scoped_refptr<extensions::TestSendMessageFunction> function;
473   };
474
475   FileManagerTestListener() {
476     registrar_.Add(this,
477                    chrome::NOTIFICATION_EXTENSION_TEST_PASSED,
478                    content::NotificationService::AllSources());
479     registrar_.Add(this,
480                    chrome::NOTIFICATION_EXTENSION_TEST_FAILED,
481                    content::NotificationService::AllSources());
482     registrar_.Add(this,
483                    chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE,
484                    content::NotificationService::AllSources());
485   }
486
487   Message GetNextMessage() {
488     if (messages_.empty())
489       content::RunMessageLoop();
490     const Message entry = messages_.front();
491     messages_.pop_front();
492     return entry;
493   }
494
495   virtual void Observe(int type,
496                        const content::NotificationSource& source,
497                        const content::NotificationDetails& details) OVERRIDE {
498     Message entry;
499     entry.type = type;
500     entry.message = type != chrome::NOTIFICATION_EXTENSION_TEST_PASSED ?
501         *content::Details<std::string>(details).ptr() :
502         std::string();
503     entry.function = type == chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE ?
504         content::Source<extensions::TestSendMessageFunction>(source).ptr() :
505         NULL;
506     messages_.push_back(entry);
507     base::MessageLoopForUI::current()->Quit();
508   }
509
510  private:
511   std::deque<Message> messages_;
512   content::NotificationRegistrar registrar_;
513 };
514
515 // The base test class.
516 class FileManagerBrowserTestBase : public ExtensionApiTest {
517  protected:
518   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
519
520   virtual void SetUpOnMainThread() OVERRIDE;
521
522   // Adds an incognito and guest-mode flags for tests in the guest mode.
523   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
524
525   // Loads our testing extension and sends it a string identifying the current
526   // test.
527   void StartTest();
528
529   // Overriding point for test configurations.
530   virtual GuestMode GetGuestModeParam() const = 0;
531   virtual const char* GetTestCaseNameParam() const = 0;
532   virtual std::string OnMessage(const std::string& name,
533                                 const base::Value* value);
534
535   scoped_ptr<LocalTestVolume> local_volume_;
536   linked_ptr<DriveTestVolume> drive_volume_;
537   std::map<Profile*, linked_ptr<DriveTestVolume> > drive_volumes_;
538   scoped_ptr<LocalTestVolume> usb_volume_;
539
540  private:
541   drive::DriveIntegrationService* CreateDriveIntegrationService(
542       Profile* profile);
543   DriveIntegrationServiceFactory::FactoryCallback
544       create_drive_integration_service_;
545   scoped_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest>
546       service_factory_for_test_;
547 };
548
549 void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() {
550   ExtensionApiTest::SetUpInProcessBrowserTestFixture();
551   extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
552
553   local_volume_.reset(new DownloadsTestVolume);
554   if (GetGuestModeParam() != IN_GUEST_MODE) {
555     create_drive_integration_service_ =
556         base::Bind(&FileManagerBrowserTestBase::CreateDriveIntegrationService,
557                    base::Unretained(this));
558     service_factory_for_test_.reset(
559         new DriveIntegrationServiceFactory::ScopedFactoryForTest(
560             &create_drive_integration_service_));
561   }
562 }
563
564 void FileManagerBrowserTestBase::SetUpOnMainThread() {
565   ExtensionApiTest::SetUpOnMainThread();
566   ASSERT_TRUE(local_volume_->Mount(profile()));
567
568   if (GetGuestModeParam() != IN_GUEST_MODE) {
569     // Install the web server to serve the mocked share dialog.
570     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
571     const GURL share_url_base(embedded_test_server()->GetURL(
572         "/chromeos/file_manager/share_dialog_mock/index.html"));
573     drive_volume_ = drive_volumes_[profile()];
574     drive_volume_->ConfigureShareUrlBase(share_url_base);
575     test_util::WaitUntilDriveMountPointIsAdded(profile());
576   }
577 }
578
579 void FileManagerBrowserTestBase::SetUpCommandLine(CommandLine* command_line) {
580   if (GetGuestModeParam() == IN_GUEST_MODE) {
581     command_line->AppendSwitch(chromeos::switches::kGuestSession);
582     command_line->AppendSwitchNative(chromeos::switches::kLoginUser, "");
583     command_line->AppendSwitch(switches::kIncognito);
584   }
585   ExtensionApiTest::SetUpCommandLine(command_line);
586 }
587
588 void FileManagerBrowserTestBase::StartTest() {
589   // Launch the extension.
590   base::FilePath path = test_data_dir_.AppendASCII("file_manager_browsertest");
591   const extensions::Extension* extension = LoadExtensionAsComponent(path);
592   ASSERT_TRUE(extension);
593
594   // Handle the messages from JavaScript.
595   // The while loop is break when the test is passed or failed.
596   FileManagerTestListener listener;
597   while (true) {
598     FileManagerTestListener::Message entry = listener.GetNextMessage();
599     if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_PASSED) {
600       // Test succeed.
601       break;
602     } else if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_FAILED) {
603       // Test failed.
604       ADD_FAILURE() << entry.message;
605       break;
606     }
607
608     // Parse the message value as JSON.
609     const scoped_ptr<const base::Value> value(
610         base::JSONReader::Read(entry.message));
611
612     // If the message is not the expected format, just ignore it.
613     const base::DictionaryValue* message_dictionary = NULL;
614     std::string name;
615     if (!value || !value->GetAsDictionary(&message_dictionary) ||
616         !message_dictionary->GetString("name", &name))
617       continue;
618
619     entry.function->Reply(OnMessage(name, value.get()));
620   }
621 }
622
623 std::string FileManagerBrowserTestBase::OnMessage(const std::string& name,
624                                                   const base::Value* value) {
625   if (name == "getTestName") {
626     // Pass the test case name.
627     return GetTestCaseNameParam();
628   } else if (name == "getRootPaths") {
629     // Pass the root paths.
630     const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
631     res->SetString("downloads",
632         "/" + util::GetDownloadsMountPointName(profile()));
633     res->SetString("drive",
634         "/" + drive::util::GetDriveMountPointPath(profile()
635             ).BaseName().AsUTF8Unsafe() + "/root");
636     std::string jsonString;
637     base::JSONWriter::Write(res.get(), &jsonString);
638     return jsonString;
639   } else if (name == "isInGuestMode") {
640     // Obtain whether the test is in guest mode or not.
641     return GetGuestModeParam() ? "true" : "false";
642   } else if (name == "getCwsWidgetContainerMockUrl") {
643     // Obtain whether the test is in guest mode or not.
644     const GURL url = embedded_test_server()->GetURL(
645           "/chromeos/file_manager/cws_container_mock/index.html");
646     std::string origin = url.GetOrigin().spec();
647
648     // Removes trailing a slash.
649     if (*origin.rbegin() == '/')
650       origin.resize(origin.length() - 1);
651
652     const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
653     res->SetString("url", url.spec());
654     res->SetString("origin", origin);
655     std::string jsonString;
656     base::JSONWriter::Write(res.get(), &jsonString);
657     return jsonString;
658   } else if (name == "addEntries") {
659     // Add entries to the specified volume.
660     base::JSONValueConverter<AddEntriesMessage> add_entries_message_converter;
661     AddEntriesMessage message;
662     if (!add_entries_message_converter.Convert(*value, &message))
663       return "onError";
664     for (size_t i = 0; i < message.entries.size(); ++i) {
665       switch (message.volume) {
666         case LOCAL_VOLUME:
667           local_volume_->CreateEntry(*message.entries[i]);
668           break;
669         case DRIVE_VOLUME:
670           if (drive_volume_.get())
671             drive_volume_->CreateEntry(*message.entries[i]);
672           break;
673         case USB_VOLUME:
674           if (usb_volume_)
675             usb_volume_->CreateEntry(*message.entries[i]);
676           break;
677         default:
678           NOTREACHED();
679           break;
680       }
681     }
682     return "onEntryAdded";
683   } else if (name == "mountFakeUsb") {
684     usb_volume_.reset(new FakeUsbTestVolume());
685     usb_volume_->Mount(profile());
686     return "true";
687   }
688   return "unknownMessage";
689 }
690
691 drive::DriveIntegrationService*
692 FileManagerBrowserTestBase::CreateDriveIntegrationService(Profile* profile) {
693   drive_volumes_[profile].reset(new DriveTestVolume());
694   return drive_volumes_[profile]->CreateDriveIntegrationService(profile);
695 }
696
697 // Parameter of FileManagerBrowserTest.
698 // The second value is the case name of JavaScript.
699 typedef std::tr1::tuple<GuestMode, const char*> TestParameter;
700
701 // Test fixture class for normal (not multi-profile related) tests.
702 class FileManagerBrowserTest :
703       public FileManagerBrowserTestBase,
704       public ::testing::WithParamInterface<TestParameter> {
705   virtual GuestMode GetGuestModeParam() const OVERRIDE {
706     return std::tr1::get<0>(GetParam());
707   }
708   virtual const char* GetTestCaseNameParam() const OVERRIDE {
709     return std::tr1::get<1>(GetParam());
710   }
711 };
712
713 IN_PROC_BROWSER_TEST_P(FileManagerBrowserTest, Test) {
714   StartTest();
715 }
716
717 INSTANTIATE_TEST_CASE_P(
718     FileDisplay,
719     FileManagerBrowserTest,
720     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDownloads"),
721                       TestParameter(IN_GUEST_MODE, "fileDisplayDownloads"),
722                       TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDrive")));
723
724 INSTANTIATE_TEST_CASE_P(
725     OpenSpecialTypes,
726     FileManagerBrowserTest,
727     ::testing::Values(TestParameter(IN_GUEST_MODE, "galleryOpenDownloads"),
728                       TestParameter(NOT_IN_GUEST_MODE, "galleryOpenDownloads"),
729                       TestParameter(NOT_IN_GUEST_MODE, "galleryOpenDrive"),
730                       TestParameter(IN_GUEST_MODE, "zipOpenDownloads"),
731                       TestParameter(NOT_IN_GUEST_MODE, "zipOpenDownloads")));
732 // http://crbug.com/348008
733 // DISABLED           TestParameter(NOT_IN_GUEST_MODE, "zipOpenDrive")));
734
735 INSTANTIATE_TEST_CASE_P(
736     OpenVideoFiles,
737     FileManagerBrowserTest,
738     ::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"),
739                       TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"),
740                       TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive")));
741
742 INSTANTIATE_TEST_CASE_P(
743     OpenAudioFiles,
744     FileManagerBrowserTest,
745     ::testing::Values(
746         TestParameter(IN_GUEST_MODE, "audioOpenDownloads"),
747         TestParameter(NOT_IN_GUEST_MODE, "audioOpenDownloads"),
748         TestParameter(NOT_IN_GUEST_MODE, "audioOpenDrive"),
749         TestParameter(NOT_IN_GUEST_MODE, "audioAutoAdvanceDrive"),
750         TestParameter(NOT_IN_GUEST_MODE, "audioRepeatSingleFileDrive"),
751         TestParameter(NOT_IN_GUEST_MODE, "audioNoRepeatSingleFileDrive"),
752         TestParameter(NOT_IN_GUEST_MODE, "audioRepeatMultipleFileDrive"),
753         TestParameter(NOT_IN_GUEST_MODE, "audioNoRepeatMultipleFileDrive")));
754
755 INSTANTIATE_TEST_CASE_P(
756     CreateNewFolder,
757     FileManagerBrowserTest,
758     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE,
759                                     "createNewFolderAfterSelectFile"),
760                       TestParameter(IN_GUEST_MODE,
761                                     "createNewFolderDownloads"),
762                       TestParameter(NOT_IN_GUEST_MODE,
763                                     "createNewFolderDownloads"),
764                       TestParameter(NOT_IN_GUEST_MODE,
765                                     "createNewFolderDrive")));
766
767 INSTANTIATE_TEST_CASE_P(
768     KeyboardOperations,
769     FileManagerBrowserTest,
770     ::testing::Values(TestParameter(IN_GUEST_MODE, "keyboardDeleteDownloads"),
771                       TestParameter(NOT_IN_GUEST_MODE,
772                                     "keyboardDeleteDownloads"),
773                       TestParameter(NOT_IN_GUEST_MODE, "keyboardDeleteDrive"),
774                       TestParameter(IN_GUEST_MODE, "keyboardCopyDownloads"),
775                       TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDownloads"),
776                       TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDrive"),
777                       TestParameter(IN_GUEST_MODE,
778                                     "renameFileDownloads"),
779                       TestParameter(NOT_IN_GUEST_MODE,
780                                     "renameFileDownloads"),
781                       TestParameter(NOT_IN_GUEST_MODE,
782                                     "renameFileDrive")));
783
784 // Disabled due to frequent timeouts; http://crbug.com/370980.
785 INSTANTIATE_TEST_CASE_P(
786     DISABLED_DriveSpecific,
787     FileManagerBrowserTest,
788     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "openSidebarRecent"),
789                       TestParameter(NOT_IN_GUEST_MODE, "openSidebarOffline"),
790                       TestParameter(NOT_IN_GUEST_MODE,
791                                     "openSidebarSharedWithMe"),
792                       TestParameter(NOT_IN_GUEST_MODE, "autocomplete")));
793
794 INSTANTIATE_TEST_CASE_P(
795     Transfer,
796     FileManagerBrowserTest,
797     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE,
798                                     "transferFromDriveToDownloads"),
799                       TestParameter(NOT_IN_GUEST_MODE,
800                                     "transferFromDownloadsToDrive"),
801                       TestParameter(NOT_IN_GUEST_MODE,
802                                     "transferFromSharedToDownloads"),
803                       TestParameter(NOT_IN_GUEST_MODE,
804                                     "transferFromSharedToDrive"),
805                       TestParameter(NOT_IN_GUEST_MODE,
806                                     "transferFromRecentToDownloads"),
807                       TestParameter(NOT_IN_GUEST_MODE,
808                                     "transferFromRecentToDrive"),
809                       TestParameter(NOT_IN_GUEST_MODE,
810                                     "transferFromOfflineToDownloads"),
811                       TestParameter(NOT_IN_GUEST_MODE,
812                                     "transferFromOfflineToDrive")));
813
814 INSTANTIATE_TEST_CASE_P(
815     RestorePrefs,
816     FileManagerBrowserTest,
817     ::testing::Values(TestParameter(IN_GUEST_MODE, "restoreSortColumn"),
818                       TestParameter(NOT_IN_GUEST_MODE, "restoreSortColumn"),
819                       TestParameter(IN_GUEST_MODE, "restoreCurrentView"),
820                       TestParameter(NOT_IN_GUEST_MODE, "restoreCurrentView")));
821
822 INSTANTIATE_TEST_CASE_P(
823     ShareDialog,
824     FileManagerBrowserTest,
825     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "shareFile"),
826                       TestParameter(NOT_IN_GUEST_MODE, "shareDirectory")));
827
828 INSTANTIATE_TEST_CASE_P(
829     RestoreGeometry,
830     FileManagerBrowserTest,
831     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "restoreGeometry"),
832                       TestParameter(IN_GUEST_MODE, "restoreGeometry")));
833
834 INSTANTIATE_TEST_CASE_P(
835     Traverse,
836     FileManagerBrowserTest,
837     ::testing::Values(TestParameter(IN_GUEST_MODE, "traverseDownloads"),
838                       TestParameter(NOT_IN_GUEST_MODE, "traverseDownloads"),
839                       TestParameter(NOT_IN_GUEST_MODE, "traverseDrive")));
840
841 INSTANTIATE_TEST_CASE_P(
842     SuggestAppDialog,
843     FileManagerBrowserTest,
844     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "suggestAppDialog")));
845
846 INSTANTIATE_TEST_CASE_P(
847     ExecuteDefaultTaskOnDownloads,
848     FileManagerBrowserTest,
849     ::testing::Values(
850         TestParameter(NOT_IN_GUEST_MODE, "executeDefaultTaskOnDownloads"),
851         TestParameter(IN_GUEST_MODE, "executeDefaultTaskOnDownloads")));
852
853 INSTANTIATE_TEST_CASE_P(
854     ExecuteDefaultTaskOnDrive,
855     FileManagerBrowserTest,
856     ::testing::Values(
857         TestParameter(NOT_IN_GUEST_MODE, "executeDefaultTaskOnDrive")));
858
859 INSTANTIATE_TEST_CASE_P(
860     NavigationList,
861     FileManagerBrowserTest,
862     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE,
863                                     "traverseNavigationList")));
864
865 INSTANTIATE_TEST_CASE_P(
866     TabIndex,
867     FileManagerBrowserTest,
868     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "searchBoxFocus")));
869
870 INSTANTIATE_TEST_CASE_P(
871     Thumbnails,
872     FileManagerBrowserTest,
873     ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "thumbnailsDownloads"),
874                       TestParameter(IN_GUEST_MODE, "thumbnailsDownloads")));
875
876 INSTANTIATE_TEST_CASE_P(
877     CopyBetweenWindows,
878     FileManagerBrowserTest,
879     ::testing::Values(
880         TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsLocalToDrive"),
881         TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsLocalToUsb"),
882         TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsUsbToDrive")));
883
884 // Structure to describe an account info.
885 struct TestAccountInfo {
886   const char* const email;
887   const char* const hash;
888   const char* const display_name;
889 };
890
891 enum {
892   DUMMY_ACCOUNT_INDEX = 0,
893   PRIMARY_ACCOUNT_INDEX = 1,
894   SECONDARY_ACCOUNT_INDEX_START = 2,
895 };
896
897 static const TestAccountInfo kTestAccounts[] = {
898   {"__dummy__@invalid.domain", "hashdummy", "Dummy Account"},
899   {"alice@invalid.domain", "hashalice", "Alice"},
900   {"bob@invalid.domain", "hashbob", "Bob"},
901   {"charlie@invalid.domain", "hashcharlie", "Charlie"},
902 };
903
904 // Test fixture class for testing multi-profile features.
905 class MultiProfileFileManagerBrowserTest : public FileManagerBrowserTestBase {
906  protected:
907   // Enables multi-profiles.
908   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
909     FileManagerBrowserTestBase::SetUpCommandLine(command_line);
910     command_line->AppendSwitch(switches::kMultiProfiles);
911     // Logs in to a dummy profile (For making MultiProfileWindowManager happy;
912     // browser test creates a default window and the manager tries to assign a
913     // user for it, and we need a profile connected to a user.)
914     command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
915                                     kTestAccounts[DUMMY_ACCOUNT_INDEX].email);
916     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
917                                     kTestAccounts[DUMMY_ACCOUNT_INDEX].hash);
918   }
919
920   // Logs in to the primary profile of this test.
921   virtual void SetUpOnMainThread() OVERRIDE {
922     const TestAccountInfo& info = kTestAccounts[PRIMARY_ACCOUNT_INDEX];
923
924     AddUser(info, true);
925     FileManagerBrowserTestBase::SetUpOnMainThread();
926   }
927
928   // Loads all users to the current session and sets up necessary fields.
929   // This is used for preparing all accounts in PRE_ test setup, and for testing
930   // actual login behavior.
931   void AddAllUsers() {
932     for (size_t i = 0; i < arraysize(kTestAccounts); ++i)
933       AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START);
934   }
935
936   // Add as many as users
937   void AddExtraUsersForStressTesting() {
938     ash::Shell* const shell = ash::Shell::GetInstance();
939     const size_t maxLogin =
940         shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers();
941
942     for (int i = 0; i + arraysize(kTestAccounts) < maxLogin; ++i) {
943       const std::string email = base::StringPrintf("user%d@invalid.domain", i);
944       const std::string hash = base::StringPrintf("hashuser%d", i);
945       const std::string name = base::StringPrintf("Additional User %d", i);
946       const TestAccountInfo info = {email.c_str(), hash.c_str(), name.c_str()};
947       AddUser(info, true);
948     }
949   }
950
951   // Returns primary profile (if it is already created.)
952   virtual Profile* profile() OVERRIDE {
953     Profile* const profile = chromeos::ProfileHelper::GetProfileByUserIdHash(
954         kTestAccounts[PRIMARY_ACCOUNT_INDEX].hash);
955     return profile ? profile : FileManagerBrowserTestBase::profile();
956   }
957
958   // Sets the test case name (used as a function name in test_cases.js to call.)
959   void set_test_case_name(const std::string& name) { test_case_name_ = name; }
960
961   // Adds a new user for testing to the current session.
962   void AddUser(const TestAccountInfo& info, bool log_in) {
963     chromeos::UserManager* const user_manager = chromeos::UserManager::Get();
964     if (log_in)
965       user_manager->UserLoggedIn(info.email, info.hash, false);
966     user_manager->SaveUserDisplayName(info.email,
967                                       base::UTF8ToUTF16(info.display_name));
968     chromeos::ProfileHelper::GetProfileByUserIdHash(info.hash)->GetPrefs()->
969         SetString(prefs::kGoogleServicesUsername, info.email);
970   }
971
972  private:
973   virtual GuestMode GetGuestModeParam() const OVERRIDE {
974     return NOT_IN_GUEST_MODE;
975   }
976
977   virtual const char* GetTestCaseNameParam() const OVERRIDE {
978     return test_case_name_.c_str();
979   }
980
981   virtual std::string OnMessage(const std::string& name,
982                                 const base::Value* value) OVERRIDE {
983     if (name == "addAllUsers") {
984       AddAllUsers();
985       return "true";
986     } else if (name == "getWindowOwnerId") {
987       chrome::MultiUserWindowManager* const window_manager =
988           chrome::MultiUserWindowManager::GetInstance();
989       apps::AppWindowRegistry* const app_window_registry =
990           apps::AppWindowRegistry::Get(profile());
991       DCHECK(window_manager);
992       DCHECK(app_window_registry);
993
994       const apps::AppWindowRegistry::AppWindowList& list =
995           app_window_registry->GetAppWindowsForApp(
996               file_manager::kFileManagerAppId);
997       return list.size() == 1u ?
998           window_manager->GetUserPresentingWindow(
999               list.front()->GetNativeWindow()) : "";
1000     }
1001     return FileManagerBrowserTestBase::OnMessage(name, value);
1002   }
1003
1004   std::string test_case_name_;
1005 };
1006
1007 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, PRE_BasicDownloads) {
1008   AddAllUsers();
1009 }
1010
1011 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, BasicDownloads) {
1012   AddAllUsers();
1013
1014   // Sanity check that normal operations work in multi-profile setting as well.
1015   set_test_case_name("keyboardCopyDownloads");
1016   StartTest();
1017 }
1018
1019 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, PRE_BasicDrive) {
1020   AddAllUsers();
1021 }
1022
1023 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, BasicDrive) {
1024   AddAllUsers();
1025
1026   // Sanity check that normal operations work in multi-profile setting as well.
1027   set_test_case_name("keyboardCopyDrive");
1028   StartTest();
1029 }
1030
1031 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, PRE_Badge) {
1032   AddAllUsers();
1033 }
1034
1035 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, Badge) {
1036   // Test the profile badge to be correctly shown and hidden.
1037   set_test_case_name("multiProfileBadge");
1038   StartTest();
1039 }
1040
1041 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest,
1042                        PRE_VisitDesktopMenu) {
1043   AddAllUsers();
1044 }
1045
1046 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, VisitDesktopMenu) {
1047   // Test for the menu item for visiting other profile's desktop.
1048   set_test_case_name("multiProfileVisitDesktopMenu");
1049   StartTest();
1050 }
1051
1052 // TODO(kinaba): investigate the flakiness.
1053 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest,
1054                        DISABLED_PRE_MaxUser) {
1055   AddAllUsers();
1056   AddExtraUsersForStressTesting();
1057 }
1058
1059 IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest,
1060                        DISABLED_MaxUser) {
1061   // Run the same test as VisitDesktopMenu with maximum number of users logged
1062   // in and checks that nothing goes wrong. Here, the primary user (alice) logs
1063   // in first, then the "extra" users follow, and then lastly the other users
1064   // (bob and charlie) are added in the test. Thus the existing test verifies
1065   // that the feature is effectively working with lastly logged in users.
1066   AddExtraUsersForStressTesting();
1067
1068   set_test_case_name("multiProfileVisitDesktopMenu");
1069   StartTest();
1070 }
1071
1072 }  // namespace
1073 }  // namespace file_manager