Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / create_directory_operation.cc
index af7805e..39f5742 100644 (file)
@@ -7,10 +7,7 @@
 #include "chrome/browser/chromeos/drive/drive.pb.h"
 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
-#include "chrome/browser/chromeos/drive/job_scheduler.h"
-#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
-#include "chrome/browser/google_apis/gdata_errorcode.h"
-#include "chrome/browser/google_apis/gdata_wapi_parser.h"
+#include "chrome/browser/chromeos/drive/resource_metadata.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
@@ -20,238 +17,150 @@ namespace file_system {
 
 namespace {
 
-// Part of CreateDirectoryRecursively(). Adds an |entry| for new directory
-// to |metadata|, and return the status. If succeeded, |file_path| will store
-// the path to the result file.
-FileError UpdateLocalStateForCreateDirectoryRecursively(
+FileError CreateDirectoryRecursively(
     internal::ResourceMetadata* metadata,
-    scoped_ptr<google_apis::ResourceEntry> resource_entry,
-    base::FilePath* file_path) {
-  DCHECK(metadata);
-  DCHECK(file_path);
+    const std::string& parent_local_id,
+    const base::FilePath& relative_file_path,
+    std::set<std::string>* updated_local_ids,
+    std::set<base::FilePath>* changed_directories) {
+  // Split the first component and remaining ones of |relative_file_path|.
+  std::vector<base::FilePath::StringType> components;
+  relative_file_path.GetComponents(&components);
+  DCHECK(!components.empty());
+  base::FilePath title(components[0]);
+  base::FilePath remaining_path;
+  title.AppendRelativePath(relative_file_path, &remaining_path);
 
   ResourceEntry entry;
-  std::string parent_resource_id;
-  if (!ConvertToResourceEntry(*resource_entry, &entry, &parent_resource_id))
-    return FILE_ERROR_NOT_A_FILE;
-
-  std::string parent_local_id;
-  FileError result = metadata->GetIdByResourceId(parent_resource_id,
-                                                 &parent_local_id);
-  if (result != FILE_ERROR_OK)
-    return result;
+  const base::Time now = base::Time::Now();
+  entry.set_title(title.AsUTF8Unsafe());
+  entry.mutable_file_info()->set_is_directory(true);
+  entry.mutable_file_info()->set_last_modified(now.ToInternalValue());
+  entry.mutable_file_info()->set_last_accessed(now.ToInternalValue());
   entry.set_parent_local_id(parent_local_id);
+  entry.set_metadata_edit_state(ResourceEntry::DIRTY);
+  entry.set_modification_date(base::Time::Now().ToInternalValue());
 
   std::string local_id;
-  result = metadata->AddEntry(entry, &local_id);
-  // Depending on timing, a metadata may be updated by change list already.
-  // So, FILE_ERROR_EXISTS is not an error.
-  if (result == FILE_ERROR_EXISTS)
-    result = metadata->GetIdByResourceId(entry.resource_id(), &local_id);
-
-  if (result == FILE_ERROR_OK)
-    *file_path = metadata->GetFilePath(local_id);
-
-  return result;
-}
+  FileError error = metadata->AddEntry(entry, &local_id);
+  if (error != FILE_ERROR_OK)
+    return error;
 
-}  // namespace
+  updated_local_ids->insert(local_id);
+  changed_directories->insert(metadata->GetFilePath(local_id).DirName());
 
-CreateDirectoryOperation::CreateDirectoryOperation(
-    base::SequencedTaskRunner* blocking_task_runner,
-    OperationObserver* observer,
-    JobScheduler* scheduler,
-    internal::ResourceMetadata* metadata)
-    : blocking_task_runner_(blocking_task_runner),
-      observer_(observer),
-      scheduler_(scheduler),
-      metadata_(metadata),
-      weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
+  if (remaining_path.empty())  // All directories are created successfully.
+    return FILE_ERROR_OK;
 
-CreateDirectoryOperation::~CreateDirectoryOperation() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void CreateDirectoryOperation::CreateDirectory(
-    const base::FilePath& directory_path,
-    bool is_exclusive,
-    bool is_recursive,
-    const FileOperationCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
-
-  ResourceEntry* entry = new ResourceEntry;
-  base::PostTaskAndReplyWithResult(
-      blocking_task_runner_.get(),
-      FROM_HERE,
-      base::Bind(&CreateDirectoryOperation::GetExistingDeepestDirectory,
-                 metadata_,
-                 directory_path,
-                 entry),
-      base::Bind(&CreateDirectoryOperation::
-                     CreateDirectoryAfterGetExistingDeepestDirectory,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 directory_path,
-                 is_exclusive,
-                 is_recursive,
-                 callback,
-                 base::Owned(entry)));
+  // Create descendant directories.
+  return CreateDirectoryRecursively(metadata, local_id, remaining_path,
+                                    updated_local_ids, changed_directories);
 }
 
-// static
-base::FilePath CreateDirectoryOperation::GetExistingDeepestDirectory(
-    internal::ResourceMetadata* metadata,
-    const base::FilePath& directory_path,
-    ResourceEntry* entry) {
-  DCHECK(metadata);
-  DCHECK(entry);
-
+FileError UpdateLocalState(internal::ResourceMetadata* metadata,
+                           const base::FilePath& directory_path,
+                           bool is_exclusive,
+                           bool is_recursive,
+                           std::set<std::string>* updated_local_ids,
+                           std::set<base::FilePath>* changed_directories) {
+  // Get the existing deepest entry.
   std::vector<base::FilePath::StringType> components;
   directory_path.GetComponents(&components);
 
   if (components.empty() || components[0] != util::kDriveGrandRootDirName)
-    return base::FilePath();
+    return FILE_ERROR_NOT_FOUND;
 
-  std::string local_id = util::kDriveGrandRootSpecialResourceId;
+  base::FilePath existing_deepest_path(components[0]);
+  std::string local_id = util::kDriveGrandRootLocalId;
   for (size_t i = 1; i < components.size(); ++i) {
     std::string child_local_id = metadata->GetChildId(local_id, components[i]);
     if (child_local_id.empty())
       break;
+    existing_deepest_path = existing_deepest_path.Append(components[i]);
     local_id = child_local_id;
   }
 
-  FileError error = metadata->GetResourceEntryById(local_id, entry);
-  DCHECK_EQ(FILE_ERROR_OK, error);
-
-  if (!entry->file_info().is_directory())
-    return base::FilePath();
-
-  return metadata->GetFilePath(local_id);
-}
-
-void CreateDirectoryOperation::CreateDirectoryAfterGetExistingDeepestDirectory(
-    const base::FilePath& directory_path,
-    bool is_exclusive,
-    bool is_recursive,
-    const FileOperationCallback& callback,
-    ResourceEntry* existing_deepest_directory_entry,
-    const base::FilePath& existing_deepest_directory_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
-  DCHECK(existing_deepest_directory_entry);
+  ResourceEntry entry;
+  FileError error = metadata->GetResourceEntryById(local_id, &entry);
+  if (error != FILE_ERROR_OK)
+    return error;
 
-  if (existing_deepest_directory_path.empty()) {
-    callback.Run(FILE_ERROR_NOT_FOUND);
-    return;
-  }
+  if (!entry.file_info().is_directory())
+    return FILE_ERROR_NOT_A_DIRECTORY;
 
-  if (directory_path == existing_deepest_directory_path) {
-    callback.Run(is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK);
-    return;
-  }
+  if (directory_path == existing_deepest_path)
+    return is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK;
 
   // If it is not recursive creation, the found directory must be the direct
   // parent of |directory_path| to ensure creating exact one directory.
-  if (!is_recursive &&
-      existing_deepest_directory_path != directory_path.DirName()) {
-    callback.Run(FILE_ERROR_NOT_FOUND);
-    return;
-  }
+  if (!is_recursive && existing_deepest_path != directory_path.DirName())
+    return FILE_ERROR_NOT_FOUND;
 
   // Create directories under the found directory.
   base::FilePath remaining_path;
-  existing_deepest_directory_path.AppendRelativePath(
-      directory_path, &remaining_path);
-  CreateDirectoryRecursively(existing_deepest_directory_entry->resource_id(),
-                             remaining_path, callback);
+  existing_deepest_path.AppendRelativePath(directory_path, &remaining_path);
+  return CreateDirectoryRecursively(metadata, entry.local_id(), remaining_path,
+                                    updated_local_ids, changed_directories);
 }
 
-void CreateDirectoryOperation::CreateDirectoryRecursively(
-    const std::string& parent_resource_id,
-    const base::FilePath& relative_file_path,
-    const FileOperationCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!callback.is_null());
+}  // namespace
 
-  // Split the first component and remaining ones of |relative_file_path|.
-  std::vector<base::FilePath::StringType> components;
-  relative_file_path.GetComponents(&components);
-  DCHECK(!components.empty());
-  base::FilePath title(components[0]);
-  base::FilePath remaining_path;
-  title.AppendRelativePath(relative_file_path, &remaining_path);
+CreateDirectoryOperation::CreateDirectoryOperation(
+    base::SequencedTaskRunner* blocking_task_runner,
+    OperationObserver* observer,
+    internal::ResourceMetadata* metadata)
+    : blocking_task_runner_(blocking_task_runner),
+      observer_(observer),
+      metadata_(metadata),
+      weak_ptr_factory_(this) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
 
-  scheduler_->AddNewDirectory(
-      parent_resource_id,
-      title.AsUTF8Unsafe(),
-      base::Bind(&CreateDirectoryOperation
-                     ::CreateDirectoryRecursivelyAfterAddNewDirectory,
-                 weak_ptr_factory_.GetWeakPtr(), remaining_path, callback));
+CreateDirectoryOperation::~CreateDirectoryOperation() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
-void CreateDirectoryOperation::CreateDirectoryRecursivelyAfterAddNewDirectory(
-    const base::FilePath& remaining_path,
-    const FileOperationCallback& callback,
-    google_apis::GDataErrorCode gdata_error,
-    scoped_ptr<google_apis::ResourceEntry> resource_entry) {
+void CreateDirectoryOperation::CreateDirectory(
+    const base::FilePath& directory_path,
+    bool is_exclusive,
+    bool is_recursive,
+    const FileOperationCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  FileError error = GDataToFileError(gdata_error);
-  if (error != FILE_ERROR_OK) {
-    callback.Run(error);
-    return;
-  }
-  DCHECK(resource_entry);
-  const std::string& resource_id = resource_entry->resource_id();
-
-  // Note that the created directory may be renamed inside
-  // ResourceMetadata::AddEntry due to name confliction.
-  // What we actually need here is the new created path (not the path we try
-  // to create).
-  base::FilePath* file_path = new base::FilePath;
+  std::set<std::string>* updated_local_ids = new std::set<std::string>;
+  std::set<base::FilePath>* changed_directories = new std::set<base::FilePath>;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
-      base::Bind(&UpdateLocalStateForCreateDirectoryRecursively,
-                 metadata_,
-                 base::Passed(&resource_entry),
-                 file_path),
+      base::Bind(&UpdateLocalState,
+                 metadata_, directory_path, is_exclusive, is_recursive,
+                 updated_local_ids, changed_directories),
       base::Bind(&CreateDirectoryOperation::
-                     CreateDirectoryRecursivelyAfterUpdateLocalState,
+                     CreateDirectoryAfterUpdateLocalState,
                  weak_ptr_factory_.GetWeakPtr(),
-                 resource_id,
-                 remaining_path,
                  callback,
-                 base::Owned(file_path)));
+                 base::Owned(updated_local_ids),
+                 base::Owned(changed_directories)));
 }
 
-void CreateDirectoryOperation::CreateDirectoryRecursivelyAfterUpdateLocalState(
-    const std::string& resource_id,
-    const base::FilePath& remaining_path,
-    const FileOperationCallback& callback,
-    base::FilePath* file_path,
-    FileError error) {
+void CreateDirectoryOperation::CreateDirectoryAfterUpdateLocalState(
+      const FileOperationCallback& callback,
+      const std::set<std::string>* updated_local_ids,
+      const std::set<base::FilePath>* changed_directories,
+      FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
-  if (error != FILE_ERROR_OK) {
-    callback.Run(error);
-    return;
-  }
+  for (std::set<std::string>::const_iterator it = updated_local_ids->begin();
+       it != updated_local_ids->end(); ++it)
+    observer_->OnEntryUpdatedByOperation(*it);
 
-  observer_->OnDirectoryChangedByOperation(file_path->DirName());
+  for (std::set<base::FilePath>::const_iterator it =
+           changed_directories->begin(); it != changed_directories->end(); ++it)
+    observer_->OnDirectoryChangedByOperation(*it);
 
-  if (remaining_path.empty()) {
-    // All directories are created successfully.
-    callback.Run(FILE_ERROR_OK);
-    return;
-  }
-
-  // Create descendant directories.
-  CreateDirectoryRecursively(resource_id, remaining_path, callback);
+  callback.Run(error);
 }
 
 }  // namespace file_system