root/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CreateFileSystemURL
  2. TEST
  3. TEST
  4. TEST
  5. TEST

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/fileapi/file_system_backend.h"

#include <set>

#include "base/files/file_path.h"
#include "base/path_service.h"
#include "chromeos/dbus/cros_disks_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_util.h"
#include "webkit/browser/fileapi/external_mount_points.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/browser/quota/mock_special_storage_policy.h"

#define FPL(x) FILE_PATH_LITERAL(x)

using fileapi::ExternalMountPoints;
using fileapi::FileSystemURL;

namespace {

FileSystemURL CreateFileSystemURL(const std::string& extension,
                                  const char* path,
                                  ExternalMountPoints* mount_points) {
  return mount_points->CreateCrackedFileSystemURL(
      GURL("chrome-extension://" + extension + "/"),
      fileapi::kFileSystemTypeExternal,
      base::FilePath::FromUTF8Unsafe(path));
}

TEST(ChromeOSFileSystemBackendTest, DefaultMountPoints) {
  // Make sure no system-level mount points are registered before testing
  // to avoid flakiness.
  fileapi::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();

  scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
      new quota::MockSpecialStoragePolicy();
  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());
  chromeos::FileSystemBackend backend(
      NULL,  // drive_delegate
      storage_policy,
      mount_points.get(),
      fileapi::ExternalMountPoints::GetSystemInstance());
  backend.AddSystemMountPoints();
  std::vector<base::FilePath> root_dirs = backend.GetRootDirectories();
  std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());

  // By default there should be 3 mount points (in system mount points):
  EXPECT_EQ(3u, root_dirs.size());

  EXPECT_TRUE(root_dirs_set.count(
      chromeos::CrosDisksClient::GetRemovableDiskMountPoint()));
  EXPECT_TRUE(root_dirs_set.count(
      chromeos::CrosDisksClient::GetArchiveMountPoint()));
  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem"))));
}

TEST(ChromeOSFileSystemBackendTest, GetRootDirectories) {
  scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
      new quota::MockSpecialStoragePolicy();
  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());

  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());

  chromeos::FileSystemBackend backend(
      NULL,  // drive_delegate
      storage_policy,
      mount_points.get(),
      system_mount_points.get());

  const size_t initial_root_dirs_size = backend.GetRootDirectories().size();

  // Register 'local' test mount points.
  mount_points->RegisterFileSystem("c",
                                   fileapi::kFileSystemTypeNativeLocal,
                                   fileapi::FileSystemMountOption(),
                                   base::FilePath(FPL("/a/b/c")));
  mount_points->RegisterFileSystem("d",
                                   fileapi::kFileSystemTypeNativeLocal,
                                   fileapi::FileSystemMountOption(),
                                   base::FilePath(FPL("/b/c/d")));

  // Register system test mount points.
  system_mount_points->RegisterFileSystem("d",
                                          fileapi::kFileSystemTypeNativeLocal,
                                          fileapi::FileSystemMountOption(),
                                          base::FilePath(FPL("/g/c/d")));
  system_mount_points->RegisterFileSystem("e",
                                          fileapi::kFileSystemTypeNativeLocal,
                                          fileapi::FileSystemMountOption(),
                                          base::FilePath(FPL("/g/d/e")));

  std::vector<base::FilePath> root_dirs = backend.GetRootDirectories();
  std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
  EXPECT_EQ(initial_root_dirs_size + 4, root_dirs.size());
  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/a/b/c"))));
  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/b/c/d"))));
  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/c/d"))));
  EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/d/e"))));
}

TEST(ChromeOSFileSystemBackendTest, AccessPermissions) {
  url_util::AddStandardScheme("chrome-extension");

  scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
      new quota::MockSpecialStoragePolicy();
  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());
  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());
  chromeos::FileSystemBackend backend(
      NULL,  // drive_delegate
      storage_policy,
      mount_points.get(),
      system_mount_points.get());

  std::string extension("ddammdhioacbehjngdmkjcjbnfginlla");

  storage_policy->AddFileHandler(extension);

  // Initialize mount points.
  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
      "system",
      fileapi::kFileSystemTypeNativeLocal,
      fileapi::FileSystemMountOption(),
      base::FilePath(FPL("/g/system"))));
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "removable",
      fileapi::kFileSystemTypeNativeLocal,
      fileapi::FileSystemMountOption(),
      base::FilePath(FPL("/media/removable"))));
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "oem",
      fileapi::kFileSystemTypeRestrictedNativeLocal,
      fileapi::FileSystemMountOption(),
      base::FilePath(FPL("/usr/share/oem"))));

  // Backend specific mount point access.
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));

  backend.GrantFileAccessToExtension(extension,
                                      base::FilePath(FPL("removable/foo")));
  EXPECT_TRUE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));

  // System mount point access.
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));

  backend.GrantFileAccessToExtension(extension,
                                      base::FilePath(FPL("system/foo")));
  EXPECT_TRUE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "system/foo1",
                          system_mount_points.get())));

  // oem is restricted file system.
  backend.GrantFileAccessToExtension(
      extension, base::FilePath(FPL("oem/foo")));
  // The extension should not be able to access the file even if
  // GrantFileAccessToExtension was called.
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "oem/foo", mount_points.get())));

  backend.GrantFullAccessToExtension(extension);
  // The extension should be able to access restricted file system after it was
  // granted full access.
  EXPECT_TRUE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "oem/foo", mount_points.get())));
  // The extension which was granted full access should be able to access any
  // path on current file systems.
  EXPECT_TRUE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));
  EXPECT_TRUE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "system/foo1",
                          system_mount_points.get())));

  // The extension cannot access new mount points.
  // TODO(tbarzic): This should probably be changed.
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "test",
      fileapi::kFileSystemTypeNativeLocal,
      fileapi::FileSystemMountOption(),
      base::FilePath(FPL("/foo/test"))));
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "test_/foo", mount_points.get())));

  backend.RevokeAccessForExtension(extension);
  EXPECT_FALSE(backend.IsAccessAllowed(
      CreateFileSystemURL(extension, "removable/foo", mount_points.get())));

  fileapi::FileSystemURL internal_url = FileSystemURL::CreateForTest(
      GURL("chrome://foo"),
      fileapi::kFileSystemTypeExternal,
      base::FilePath(FPL("removable/")));
  // Internal WebUI should have full access.
  EXPECT_TRUE(backend.IsAccessAllowed(internal_url));
}

TEST(ChromeOSFileSystemBackendTest, GetVirtualPathConflictWithSystemPoints) {
  scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
      new quota::MockSpecialStoragePolicy();
  scoped_refptr<fileapi::ExternalMountPoints> mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());
  scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
      fileapi::ExternalMountPoints::CreateRefCounted());
  chromeos::FileSystemBackend backend(
      NULL,  // drive_delegate
      storage_policy,
      mount_points.get(),
      system_mount_points.get());

  const fileapi::FileSystemType type = fileapi::kFileSystemTypeNativeLocal;
  const fileapi::FileSystemMountOption option =
      fileapi::FileSystemMountOption();

  // Backend specific mount points.
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "b", type, option, base::FilePath(FPL("/a/b"))));
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "y", type, option, base::FilePath(FPL("/z/y"))));
  ASSERT_TRUE(mount_points->RegisterFileSystem(
      "n", type, option, base::FilePath(FPL("/m/n"))));

  // System mount points
  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
      "gb", type, option, base::FilePath(FPL("/a/b"))));
  ASSERT_TRUE(
      system_mount_points->RegisterFileSystem(
          "gz", type, option, base::FilePath(FPL("/z"))));
  ASSERT_TRUE(system_mount_points->RegisterFileSystem(
       "gp", type, option, base::FilePath(FPL("/m/n/o/p"))));

  struct TestCase {
    const base::FilePath::CharType* const local_path;
    bool success;
    const base::FilePath::CharType* const virtual_path;
  };

  const TestCase kTestCases[] = {
    // Same paths in both mount points.
    { FPL("/a/b/c/d"), true, FPL("b/c/d") },
    // System mount points path more specific.
    { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") },
    // System mount points path less specific.
    { FPL("/z/y/x"), true, FPL("y/x") },
    // Only system mount points path matches.
    { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") },
    // No match.
    { FPL("/foo/xxx"), false, FPL("") },
  };

  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
    // Initialize virtual path with a value.
    base::FilePath virtual_path(FPL("/mount"));
    base::FilePath local_path(kTestCases[i].local_path);
    EXPECT_EQ(kTestCases[i].success,
              backend.GetVirtualPath(local_path, &virtual_path))
        << "Resolving " << kTestCases[i].local_path;

    // There are no guarantees for |virtual_path| value if |GetVirtualPath|
    // fails.
    if (!kTestCases[i].success)
      continue;

    base::FilePath expected_virtual_path(kTestCases[i].virtual_path);
    EXPECT_EQ(expected_virtual_path, virtual_path)
        << "Resolving " << kTestCases[i].local_path;
  }
}

}  // namespace

/* [<][>][^][v][top][bottom][index][help] */