blob: ed27c013e5f145b8f012193b1f783d35110777fe [file] [log] [blame]
// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef POSIX_TRANSLATION_EXTERNAL_FILE_H_
#define POSIX_TRANSLATION_EXTERNAL_FILE_H_
#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
#include "common/export.h"
#include "native_client/src/untrusted/irt/irt.h"
#include "posix_translation/pepper_file.h"
namespace posix_translation {
// A class which provides the directory handling which holding external files.
// The mounted path is constructed from three parts: RootDirectory, Slot,
// Filename. The RootDirectory is stored in |root_directory_|, and the slot and
// filename pair is stored in |slot_file_map_|.
// Example:
// The mount point of this handler is /data/data/org.chromium.arc/external.
// Then chosen file is "/foo.txt"
//
// In this case, the mounted path will be like:
// /data/data/org.chromium.arc/external/361F9A2BF6CDFD23EEE2C3D618C170/foo.txt
// Here, RootDirectory is "/data/data/org.chromium.arc/external",
// Slot is "/361F9A2BF6CDFD23EEE2C3D618C170", and Filename is "/foo.txt"
//
// RootDirectory:
// The RootDirectory is the same as mount point of this file handler. In this
// handler, RootDirectory must NOT end with slash.
// Slot:
// The Slot is used for identifying the mounted file. One slot is
// corresponding to one mounted entry. The slot must start with slash and the
// rest must only contain alphanumeric characters.
// Filename:
// The Filename is corresponding to absolute path in chosen Pepper file
// system. In this case, the path must start with slash and the rest must NOT
// contain slash. There is only one Filename per slot.
class ARC_EXPORT ExternalFileWrapperHandler : public FileSystemHandler {
public:
// An delegate class for external file handler. This delegate can be
// used for resolving unmounted file requests.
class Delegate {
public:
virtual ~Delegate() {}
// Called when found request to unmounted resource
virtual bool ResolveExternalFile(const std::string& path,
pp::FileSystem** file_system,
std::string* path_in_external_fs,
bool* is_writable) = 0;
};
explicit ExternalFileWrapperHandler(Delegate* delegate);
virtual ~ExternalFileWrapperHandler();
// Overridden from FileSystemHandler
virtual scoped_refptr<FileStream> open(int unused_fd,
const std::string& pathname,
int oflag, mode_t cmode) OVERRIDE;
virtual int mkdir(const std::string& pathname, mode_t mode) OVERRIDE;
virtual int stat(const std::string& pathname, struct stat* out) OVERRIDE;
virtual int statfs(const std::string& pathname, struct statfs* out) OVERRIDE;
virtual void OnMounted(const std::string& path) OVERRIDE;
virtual void OnUnmounted(const std::string& path) OVERRIDE;
virtual Dir* OnDirectoryContentsNeeded(const std::string& name) OVERRIDE;
virtual std::string SetPepperFileSystem(
scoped_ptr<pp::FileSystem> pepper_file_system,
const std::string& mount_source_in_pepper_file_system,
const std::string& mount_dest_in_vfs) OVERRIDE;
private:
friend class TestableExternalFileWrapperHandler;
// Returns slot from |file_path|. The slot is starting slash.
// This function returns empty string if |file_path| is invalid.
std::string GetSlot(const std::string& file_path) const;
// Returns true if given string defines resource path
// which consists from root/slot/resource_name
bool IsResourcePath(const std::string& file_path) const;
// Generates unique slot name.
std::string GenerateUniqueSlotLocked() const;
// This function takes the ownership of |file_system|.
// virtual for testing purpose.
virtual scoped_ptr<FileSystemHandler> MountExternalFile(
scoped_ptr<pp::FileSystem> file_system,
const std::string& path_in_external_fs,
const std::string& path_in_vfs);
// Tries to resolve external file what was not mounted in this session
FileSystemHandler* ResolveExternalFile(const std::string& pathname);
std::string SetPepperFileSystemLocked(
scoped_ptr<pp::FileSystem> pepper_file_system,
const std::string& mount_source_in_pepper_file_system,
const std::string& mount_dest_in_vfs,
FileSystemHandler** file_handler);
// The mounted directory in VFS. This must NOT end with slash.
std::string root_directory_;
// A map from slot to filename the external file handler having.
typedef base::hash_map<std::string, std::string> SlotFileMap; // NOLINT
SlotFileMap slot_file_map_;
// Mounted handlers.
typedef base::hash_map<std::string, FileSystemHandler*> HandlerMap; // NOLINT
HandlerMap file_handlers_;
// For generating unique slot.
nacl_irt_random random_;
// Keep delegate pointer
scoped_ptr<Delegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(ExternalFileWrapperHandler);
};
class ExternalFileHandlerBase : public PepperFileHandler {
public:
explicit ExternalFileHandlerBase(const char* classname);
// |ppapi_file_path| and |virtual_file_path| can be both file and directory.
virtual ~ExternalFileHandlerBase();
virtual std::string SetPepperFileSystem(
scoped_ptr<pp::FileSystem> file_system,
const std::string& path_in_pepperfs,
const std::string& path_in_vfs) OVERRIDE;
// Overridden from PepperFileHandler.
virtual int mkdir(const std::string& pathname, mode_t mode) OVERRIDE;
virtual scoped_refptr<FileStream> open(int unused_fd,
const std::string& pathname,
int oflag, mode_t cmode) OVERRIDE;
virtual int remove(const std::string& pathname) OVERRIDE;
virtual int rename(const std::string& oldpath,
const std::string& newpath) OVERRIDE;
virtual int rmdir(const std::string& pathname) OVERRIDE;
virtual int stat(const std::string& pathname, struct stat* out) OVERRIDE;
virtual int statfs(const std::string& pathname, struct statfs* out) OVERRIDE;
virtual int truncate(const std::string& pathname, off64_t length) OVERRIDE;
virtual int unlink(const std::string& pathname) OVERRIDE;
virtual int utimes(const std::string& pathname,
const struct timeval times[2]) OVERRIDE;
virtual void OnMounted(const std::string& path) OVERRIDE;
virtual void OnUnmounted(const std::string& path) OVERRIDE;
protected:
void SetMountPointInVFS(const std::string& path);
private:
friend class TestableExternalFileHandler;
// Returns external PPAPI file path correponding to |file_path|.
std::string GetExternalPPAPIPath(const std::string& file_path) const;
// The file path in PPAPI file path.
std::string ppapi_file_path_;
// The file path in VFS.
std::string virtual_file_path_;
DISALLOW_COPY_AND_ASSIGN(ExternalFileHandlerBase);
};
// This class provides external file handling.
// The given external file will be shown in |virtual_file_path| on virtual file
// system.
class ExternalFileHandler : public ExternalFileHandlerBase {
public:
ExternalFileHandler(scoped_ptr<pp::FileSystem> file_system,
const std::string& ppapi_file_path,
const std::string& virtual_file_path);
virtual ~ExternalFileHandler();
virtual scoped_refptr<FileStream> open(int unused_fd,
const std::string& pathname,
int oflag, mode_t cmode) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(ExternalFileHandler);
};
// This class provides external directory handling.
// The given external directory will be shown in |virtual_file_path| on virtual
// file system. External directory handler can be "pending". The pending state
// means that any specific pepper filesystem is not attached. Once the pending
// external directory handler is initialized, call Observer::OnInitializing and
// block until the filesystem is attached with SetExternalDirectory.
class ARC_EXPORT ExternalDirectoryHandler : public ExternalFileHandlerBase {
public:
// An observer class for external directory handler. By passing this instance
// to ExternalDirectoryHandler ctor, OnInitializing is called just
// before PepperFileHandler::Initialize function call. This observer can be
// used on-demand initialization of ExternalDirectoryHandler.
class Observer {
public:
virtual ~Observer() {}
// Calles just before the PepperFileHandler::Initialize call.
virtual void OnInitializing() = 0;
};
// Creates pending external directory handler. If this handler is initialized,
// |observer| will be called and block until filesystem will be ready. This
// class takes the ownership of |observer|.
ExternalDirectoryHandler(const std::string& virtual_file_path,
Observer* observer);
virtual ~ExternalDirectoryHandler();
virtual void Initialize() OVERRIDE;
private:
scoped_ptr<Observer> observer_;
DISALLOW_COPY_AND_ASSIGN(ExternalDirectoryHandler);
};
} // namespace posix_translation
#endif // POSIX_TRANSLATION_EXTERNAL_FILE_H_