Home | History | Annotate | Download | only in drive
      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 #include "chrome/browser/chromeos/drive/file_system_util.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/files/file_path.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "chrome/common/chrome_constants.h"
     13 #include "chrome/test/base/testing_browser_process.h"
     14 #include "chrome/test/base/testing_profile.h"
     15 #include "chrome/test/base/testing_profile_manager.h"
     16 #include "content/public/test/test_browser_thread_bundle.h"
     17 #include "content/public/test/test_file_system_options.h"
     18 #include "google_apis/drive/test_util.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "webkit/browser/fileapi/external_mount_points.h"
     21 #include "webkit/browser/fileapi/file_system_backend.h"
     22 #include "webkit/browser/fileapi/file_system_context.h"
     23 #include "webkit/browser/fileapi/file_system_url.h"
     24 #include "webkit/browser/fileapi/isolated_context.h"
     25 
     26 namespace drive {
     27 namespace util {
     28 
     29 namespace {
     30 
     31 // Sets up ProfileManager for testing and marks the current thread as UI by
     32 // TestBrowserThreadBundle. We need the thread since Profile objects must be
     33 // touched from UI and hence has CHECK/DCHECKs for it.
     34 class ProfileRelatedFileSystemUtilTest : public testing::Test {
     35  protected:
     36   ProfileRelatedFileSystemUtilTest()
     37       : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {
     38   }
     39 
     40   virtual void SetUp() OVERRIDE {
     41     ASSERT_TRUE(testing_profile_manager_.SetUp());
     42   }
     43 
     44   Profile* CreateProfileWithName(const std::string& name) {
     45     return testing_profile_manager_.CreateTestingProfile(
     46         chrome::kProfileDirPrefix + name);
     47   }
     48 
     49  private:
     50   content::TestBrowserThreadBundle thread_bundle_;
     51   TestingProfileManager testing_profile_manager_;
     52 };
     53 
     54 }  // namespace
     55 
     56 TEST(FileSystemUtilTest, FilePathToDriveURL) {
     57   base::FilePath path;
     58 
     59   // Path with alphabets and numbers.
     60   path = GetDriveMyDriveRootPath().AppendASCII("foo/bar012.txt");
     61   EXPECT_EQ(path, DriveURLToFilePath(FilePathToDriveURL(path)));
     62 
     63   // Path with symbols.
     64   path = GetDriveMyDriveRootPath().AppendASCII(
     65       " !\"#$%&'()*+,-.:;<=>?@[\\]^_`{|}~");
     66   EXPECT_EQ(path, DriveURLToFilePath(FilePathToDriveURL(path)));
     67 
     68   // Path with '%'.
     69   path = GetDriveMyDriveRootPath().AppendASCII("%19%20%21.txt");
     70   EXPECT_EQ(path, DriveURLToFilePath(FilePathToDriveURL(path)));
     71 
     72   // Path with multi byte characters.
     73   base::string16 utf16_string;
     74   utf16_string.push_back(0x307b);  // HIRAGANA_LETTER_HO
     75   utf16_string.push_back(0x3052);  // HIRAGANA_LETTER_GE
     76   path = GetDriveMyDriveRootPath().Append(
     77       base::FilePath::FromUTF8Unsafe(base::UTF16ToUTF8(utf16_string) + ".txt"));
     78   EXPECT_EQ(path, DriveURLToFilePath(FilePathToDriveURL(path)));
     79 }
     80 
     81 TEST_F(ProfileRelatedFileSystemUtilTest, GetDriveMountPointPath) {
     82   Profile* profile = CreateProfileWithName("hash1");
     83   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("/special/drive-hash1"),
     84             GetDriveMountPointPath(profile));
     85 }
     86 
     87 TEST_F(ProfileRelatedFileSystemUtilTest, ExtractProfileFromPath) {
     88   Profile* profile1 = CreateProfileWithName("hash1");
     89   Profile* profile2 = CreateProfileWithName("hash2");
     90   EXPECT_EQ(profile1, ExtractProfileFromPath(
     91       base::FilePath::FromUTF8Unsafe("/special/drive-hash1")));
     92   EXPECT_EQ(profile2, ExtractProfileFromPath(
     93       base::FilePath::FromUTF8Unsafe("/special/drive-hash2/root/xxx")));
     94   EXPECT_EQ(NULL, ExtractProfileFromPath(
     95       base::FilePath::FromUTF8Unsafe("/special/non-drive-path")));
     96 }
     97 
     98 TEST(FileSystemUtilTest, IsUnderDriveMountPoint) {
     99   EXPECT_FALSE(IsUnderDriveMountPoint(
    100       base::FilePath::FromUTF8Unsafe("/wherever/foo.txt")));
    101   EXPECT_FALSE(IsUnderDriveMountPoint(
    102       base::FilePath::FromUTF8Unsafe("/special/foo.txt")));
    103   EXPECT_FALSE(IsUnderDriveMountPoint(
    104       base::FilePath::FromUTF8Unsafe("special/drive/foo.txt")));
    105 
    106   EXPECT_TRUE(IsUnderDriveMountPoint(
    107       base::FilePath::FromUTF8Unsafe("/special/drive")));
    108   EXPECT_TRUE(IsUnderDriveMountPoint(
    109       base::FilePath::FromUTF8Unsafe("/special/drive/foo.txt")));
    110   EXPECT_TRUE(IsUnderDriveMountPoint(
    111       base::FilePath::FromUTF8Unsafe("/special/drive/subdir/foo.txt")));
    112   EXPECT_TRUE(IsUnderDriveMountPoint(
    113       base::FilePath::FromUTF8Unsafe("/special/drive-xxx/foo.txt")));
    114 }
    115 
    116 TEST(FileSystemUtilTest, ExtractDrivePath) {
    117   EXPECT_EQ(base::FilePath(),
    118             ExtractDrivePath(
    119                 base::FilePath::FromUTF8Unsafe("/wherever/foo.txt")));
    120   EXPECT_EQ(base::FilePath(),
    121             ExtractDrivePath(
    122                 base::FilePath::FromUTF8Unsafe("/special/foo.txt")));
    123 
    124   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive"),
    125             ExtractDrivePath(
    126                 base::FilePath::FromUTF8Unsafe("/special/drive")));
    127   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/foo.txt"),
    128             ExtractDrivePath(
    129                 base::FilePath::FromUTF8Unsafe("/special/drive/foo.txt")));
    130   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/subdir/foo.txt"),
    131             ExtractDrivePath(base::FilePath::FromUTF8Unsafe(
    132                 "/special/drive/subdir/foo.txt")));
    133   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/foo.txt"),
    134             ExtractDrivePath(
    135                 base::FilePath::FromUTF8Unsafe("/special/drive-xxx/foo.txt")));
    136 }
    137 
    138 TEST(FileSystemUtilTest, ExtractDrivePathFromFileSystemUrl) {
    139   TestingProfile profile;
    140 
    141   // Set up file system context for testing.
    142   base::ScopedTempDir temp_dir_;
    143   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    144 
    145   base::MessageLoop message_loop;
    146   scoped_refptr<fileapi::ExternalMountPoints> mount_points =
    147       fileapi::ExternalMountPoints::CreateRefCounted();
    148   scoped_refptr<fileapi::FileSystemContext> context(
    149       new fileapi::FileSystemContext(
    150           base::MessageLoopProxy::current().get(),
    151           base::MessageLoopProxy::current().get(),
    152           mount_points.get(),
    153           NULL,  // special_storage_policy
    154           NULL,  // quota_manager_proxy,
    155           ScopedVector<fileapi::FileSystemBackend>(),
    156           std::vector<fileapi::URLRequestAutoMountHandler>(),
    157           temp_dir_.path(),  // partition_path
    158           content::CreateAllowFileAccessOptions()));
    159 
    160   // Type:"external" + virtual_path:"drive/foo/bar" resolves to "drive/foo/bar".
    161   const std::string& drive_mount_name =
    162       GetDriveMountPointPath(&profile).BaseName().AsUTF8Unsafe();
    163   mount_points->RegisterFileSystem(
    164       drive_mount_name,
    165       fileapi::kFileSystemTypeDrive,
    166       fileapi::FileSystemMountOption(),
    167       GetDriveMountPointPath(&profile));
    168   EXPECT_EQ(
    169       base::FilePath::FromUTF8Unsafe("drive/foo/bar"),
    170       ExtractDrivePathFromFileSystemUrl(context->CrackURL(GURL(
    171           "filesystem:chrome-extension://dummy-id/external/" +
    172           drive_mount_name + "/foo/bar"))));
    173 
    174   // Virtual mount name should not affect the extracted path.
    175   mount_points->RevokeFileSystem(drive_mount_name);
    176   mount_points->RegisterFileSystem(
    177       "drive2",
    178       fileapi::kFileSystemTypeDrive,
    179       fileapi::FileSystemMountOption(),
    180       GetDriveMountPointPath(&profile));
    181   EXPECT_EQ(
    182       base::FilePath::FromUTF8Unsafe("drive/foo/bar"),
    183       ExtractDrivePathFromFileSystemUrl(context->CrackURL(GURL(
    184           "filesystem:chrome-extension://dummy-id/external/drive2/foo/bar"))));
    185 
    186   // Type:"external" + virtual_path:"Downloads/foo" is not a Drive path.
    187   mount_points->RegisterFileSystem(
    188       "Downloads",
    189       fileapi::kFileSystemTypeNativeLocal,
    190       fileapi::FileSystemMountOption(),
    191       temp_dir_.path());
    192   EXPECT_EQ(
    193       base::FilePath(),
    194       ExtractDrivePathFromFileSystemUrl(context->CrackURL(GURL(
    195           "filesystem:chrome-extension://dummy-id/external/Downloads/foo"))));
    196 
    197   // Type:"isolated" + virtual_path:"isolated_id/name" mapped on a Drive path.
    198   std::string isolated_name;
    199   std::string isolated_id =
    200       fileapi::IsolatedContext::GetInstance()->RegisterFileSystemForPath(
    201           fileapi::kFileSystemTypeNativeForPlatformApp,
    202           std::string(),
    203           GetDriveMountPointPath(&profile).AppendASCII("bar/buz"),
    204           &isolated_name);
    205   EXPECT_EQ(
    206       base::FilePath::FromUTF8Unsafe("drive/bar/buz"),
    207       ExtractDrivePathFromFileSystemUrl(context->CrackURL(GURL(
    208           "filesystem:chrome-extension://dummy-id/isolated/" +
    209           isolated_id + "/" + isolated_name))));
    210 }
    211 
    212 TEST(FileSystemUtilTest, EscapeUnescapeCacheFileName) {
    213   const std::string kUnescapedFileName(
    214       "tmp:`~!@#$%^&*()-_=+[{|]}\\\\;\',<.>/?");
    215   const std::string kEscapedFileName(
    216       "tmp:`~!@#$%25^&*()-_=+[{|]}\\\\;\',<%2E>%2F?");
    217   EXPECT_EQ(kEscapedFileName, EscapeCacheFileName(kUnescapedFileName));
    218   EXPECT_EQ(kUnescapedFileName, UnescapeCacheFileName(kEscapedFileName));
    219 }
    220 
    221 TEST(FileSystemUtilTest, NormalizeFileName) {
    222   EXPECT_EQ("", NormalizeFileName(""));
    223   EXPECT_EQ("foo", NormalizeFileName("foo"));
    224   // Slash
    225   EXPECT_EQ("foo_zzz", NormalizeFileName("foo/zzz"));
    226   EXPECT_EQ("___", NormalizeFileName("///"));
    227   // Japanese hiragana "hi" + semi-voiced-mark is normalized to "pi".
    228   EXPECT_EQ("\xE3\x81\xB4", NormalizeFileName("\xE3\x81\xB2\xE3\x82\x9A"));
    229   // Dot
    230   EXPECT_EQ("_", NormalizeFileName("."));
    231   EXPECT_EQ("_", NormalizeFileName(".."));
    232   EXPECT_EQ("_", NormalizeFileName("..."));
    233   EXPECT_EQ(".bashrc", NormalizeFileName(".bashrc"));
    234   EXPECT_EQ("._", NormalizeFileName("./"));
    235 }
    236 
    237 TEST(FileSystemUtilTest, GetCacheRootPath) {
    238   TestingProfile profile;
    239   base::FilePath profile_path = profile.GetPath();
    240   EXPECT_EQ(profile_path.AppendASCII("GCache/v1"),
    241             util::GetCacheRootPath(&profile));
    242 }
    243 
    244 TEST(FileSystemUtilTest, GDocFile) {
    245   base::ScopedTempDir temp_dir;
    246   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    247 
    248   GURL url("https://docs.google.com/document/d/"
    249            "1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug/edit");
    250   std::string resource_id("1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug");
    251 
    252   // Read and write gdoc.
    253   base::FilePath file = temp_dir.path().AppendASCII("test.gdoc");
    254   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    255   EXPECT_TRUE(HasGDocFileExtension(file));
    256   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    257   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    258 
    259   // Read and write gsheet.
    260   file = temp_dir.path().AppendASCII("test.gsheet");
    261   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    262   EXPECT_TRUE(HasGDocFileExtension(file));
    263   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    264   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    265 
    266   // Read and write gslides.
    267   file = temp_dir.path().AppendASCII("test.gslides");
    268   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    269   EXPECT_TRUE(HasGDocFileExtension(file));
    270   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    271   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    272 
    273   // Read and write gdraw.
    274   file = temp_dir.path().AppendASCII("test.gdraw");
    275   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    276   EXPECT_TRUE(HasGDocFileExtension(file));
    277   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    278   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    279 
    280   // Read and write gtable.
    281   file = temp_dir.path().AppendASCII("test.gtable");
    282   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    283   EXPECT_TRUE(HasGDocFileExtension(file));
    284   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    285   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    286 
    287   // Read and write glink.
    288   file = temp_dir.path().AppendASCII("test.glink");
    289   EXPECT_TRUE(CreateGDocFile(file, url, resource_id));
    290   EXPECT_TRUE(HasGDocFileExtension(file));
    291   EXPECT_EQ(url, ReadUrlFromGDocFile(file));
    292   EXPECT_EQ(resource_id, ReadResourceIdFromGDocFile(file));
    293 
    294   // Non GDoc file.
    295   file = temp_dir.path().AppendASCII("test.txt");
    296   std::string data = "Hello world!";
    297   EXPECT_TRUE(google_apis::test_util::WriteStringToFile(file, data));
    298   EXPECT_FALSE(HasGDocFileExtension(file));
    299   EXPECT_TRUE(ReadUrlFromGDocFile(file).is_empty());
    300   EXPECT_TRUE(ReadResourceIdFromGDocFile(file).empty());
    301 }
    302 
    303 }  // namespace util
    304 }  // namespace drive
    305