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