Commit d4a143f9 authored by kinaba@chromium.org's avatar kinaba@chromium.org

Implement generalized file preparation utility function for apps.

The previous implementation worked only for Google Drive filesystem.
The new implementation in the current CL generally supports all
volumes accessible from Chrome OS file manager, in particular
including MTP devices and file systems provided by fileSystemProvider extensions.

BUG=367028

Review URL: https://codereview.chromium.org/303133008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274222 0039d316-1c4b-4281-b951-d872f2087c98
parent 920b111f
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "google_apis/drive/task_util.h"
#include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_context.h"
namespace file_manager { namespace file_manager {
...@@ -23,6 +24,8 @@ namespace util { ...@@ -23,6 +24,8 @@ namespace util {
namespace { namespace {
// Helper function used to implement GetNonNativeLocalPathMimeType. It extracts
// the mime type from the passed Drive resource entry.
void GetMimeTypeAfterGetResourceEntry( void GetMimeTypeAfterGetResourceEntry(
const base::Callback<void(bool, const std::string&)>& callback, const base::Callback<void(bool, const std::string&)>& callback,
drive::FileError error, drive::FileError error,
...@@ -41,19 +44,46 @@ void GetMimeTypeAfterGetResourceEntry( ...@@ -41,19 +44,46 @@ void GetMimeTypeAfterGetResourceEntry(
void BoolCallbackAsFileErrorCallback( void BoolCallbackAsFileErrorCallback(
const base::Callback<void(bool)>& callback, const base::Callback<void(bool)>& callback,
base::File::Error error) { base::File::Error error) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return callback.Run(error == base::File::FILE_OK); return callback.Run(error == base::File::FILE_OK);
} }
void CheckWritableAfterDriveCheck(const base::Callback<void(bool)>& callback, // Part of PrepareFileOnIOThread. It tries to create a new file if the given
drive::FileError error, // |url| is not already inhabited.
const base::FilePath& local_path) { void PrepareFileAfterCheckExistOnIOThread(
// This is called on the IO-allowed blocking pool. Call back to UI. scoped_refptr<fileapi::FileSystemContext> file_system_context,
content::BrowserThread::PostTask( const fileapi::FileSystemURL& url,
content::BrowserThread::UI, const fileapi::FileSystemOperation::StatusCallback& callback,
FROM_HERE, base::File::Error error) {
base::Bind(callback, error == drive::FILE_ERROR_OK)); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (error != base::File::FILE_ERROR_NOT_FOUND) {
callback.Run(error);
return;
}
// Call with the second argument |exclusive| set to false, meaning that it
// is not an error even if the file already exists (it can happen if the file
// is created after the previous FileExists call and before this CreateFile.)
//
// Note that the preceding call to FileExists is necessary for handling
// read only filesystems that blindly rejects handling CreateFile().
file_system_context->operation_runner()->CreateFile(url, false, callback);
}
// Checks whether a file exists at the given |url|, and try creating it if it
// is not already there.
void PrepareFileOnIOThread(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
const fileapi::FileSystemURL& url,
const base::Callback<void(bool)>& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
file_system_context->operation_runner()->FileExists(
url,
base::Bind(&PrepareFileAfterCheckExistOnIOThread,
file_system_context,
url,
base::Bind(&BoolCallbackAsFileErrorCallback, callback)));
} }
} // namespace } // namespace
...@@ -128,7 +158,7 @@ void IsNonNativeLocalPathDirectory( ...@@ -128,7 +158,7 @@ void IsNonNativeLocalPathDirectory(
if (!util::ConvertAbsoluteFilePathToFileSystemUrl( if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
profile, path, kFileManagerAppId, &url)) { profile, path, kFileManagerAppId, &url)) {
// Posting to the current thread, so that we always call back asynchronously // Posting to the current thread, so that we always call back asynchronously
// independent from whether or not the operation succeeeds. // independent from whether or not the operation succeeds.
content::BrowserThread::PostTask(content::BrowserThread::UI, content::BrowserThread::PostTask(content::BrowserThread::UI,
FROM_HERE, FROM_HERE,
base::Bind(callback, false)); base::Bind(callback, false));
...@@ -146,12 +176,34 @@ void PrepareNonNativeLocalPathWritableFile( ...@@ -146,12 +176,34 @@ void PrepareNonNativeLocalPathWritableFile(
const base::FilePath& path, const base::FilePath& path,
const base::Callback<void(bool)>& callback) { const base::Callback<void(bool)>& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(IsUnderNonNativeLocalPath(profile, path));
GURL url;
if (!util::ConvertAbsoluteFilePathToFileSystemUrl(
profile, path, kFileManagerAppId, &url)) {
// Posting to the current thread, so that we always call back asynchronously
// independent from whether or not the operation succeeds.
content::BrowserThread::PostTask(content::BrowserThread::UI,
FROM_HERE,
base::Bind(callback, false));
return;
}
// TODO(kinaba): support other types of volumes besides Drive. fileapi::FileSystemContext* const context =
drive::util::PrepareWritableFileAndRun( GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
profile, DCHECK(context);
path,
base::Bind(&CheckWritableAfterDriveCheck, callback)); // Check the existence of a file using file system API implementation on
// behalf of the file manager app. We need to grant access beforehand.
context->external_backend()->GrantFullAccessToExtension(kFileManagerAppId);
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
base::Bind(&PrepareFileOnIOThread,
make_scoped_refptr(context),
context->CrackURL(url),
google_apis::CreateRelayCallback(callback)));
} }
} // namespace util } // namespace util
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment