12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/drive/file_change.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_metadata.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace drive {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace file_system {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21116680a4aac90f2aa7413d9095a592090648e557Ben MurdochFileError CreateDirectoryRecursively(internal::ResourceMetadata* metadata,
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     const std::string& parent_local_id,
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     const base::FilePath& relative_file_path,
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     std::set<std::string>* updated_local_ids,
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     FileChange* changed_files) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Split the first component and remaining ones of |relative_file_path|.
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<base::FilePath::StringType> components;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  relative_file_path.GetComponents(&components);
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!components.empty());
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath title(components[0]);
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath remaining_path;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  title.AppendRelativePath(relative_file_path, &remaining_path);
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ResourceEntry entry;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Time now = base::Time::Now();
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.set_title(title.AsUTF8Unsafe());
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_info()->set_is_directory(true);
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_info()->set_last_modified(now.ToInternalValue());
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_info()->set_last_accessed(now.ToInternalValue());
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  entry.set_parent_local_id(parent_local_id);
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.set_metadata_edit_state(ResourceEntry::DIRTY);
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  entry.set_modification_date(base::Time::Now().ToInternalValue());
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string local_id;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError error = metadata->AddEntry(entry, &local_id);
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != FILE_ERROR_OK)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return error;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath path;
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  error = metadata->GetFilePath(local_id, &path);
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error != FILE_ERROR_OK)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  updated_local_ids->insert(local_id);
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(changed_files);
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  changed_files->Update(
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      path, FileChange::FILE_TYPE_DIRECTORY, FileChange::ADD_OR_UPDATE);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (remaining_path.empty())  // All directories are created successfully.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_OK;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create descendant directories.
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return CreateDirectoryRecursively(
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      metadata, local_id, remaining_path, updated_local_ids, changed_files);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileError UpdateLocalState(internal::ResourceMetadata* metadata,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const base::FilePath& directory_path,
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool is_exclusive,
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool is_recursive,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           std::set<std::string>* updated_local_ids,
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           FileChange* changed_files) {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Get the existing deepest entry.
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<base::FilePath::StringType> components;
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  directory_path.GetComponents(&components);
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (components.empty() || components[0] != util::kDriveGrandRootDirName)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath existing_deepest_path(components[0]);
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string local_id = util::kDriveGrandRootLocalId;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 1; i < components.size(); ++i) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::string child_local_id;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FileError error =
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        metadata->GetChildId(local_id, components[i], &child_local_id);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (error == FILE_ERROR_NOT_FOUND)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (error != FILE_ERROR_OK)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return error;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    existing_deepest_path = existing_deepest_path.Append(components[i]);
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    local_id = child_local_id;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceEntry entry;
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError error = metadata->GetResourceEntryById(local_id, &entry);
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != FILE_ERROR_OK)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return error;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!entry.file_info().is_directory())
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (directory_path == existing_deepest_path)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If it is not recursive creation, the found directory must be the direct
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // parent of |directory_path| to ensure creating exact one directory.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_recursive && existing_deepest_path != directory_path.DirName())
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create directories under the found directory.
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath remaining_path;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  existing_deepest_path.AppendRelativePath(directory_path, &remaining_path);
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return CreateDirectoryRecursively(metadata,
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    entry.local_id(),
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    remaining_path,
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    updated_local_ids,
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    changed_files);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CreateDirectoryOperation::CreateDirectoryOperation(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::SequencedTaskRunner* blocking_task_runner,
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OperationDelegate* delegate,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    internal::ResourceMetadata* metadata)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : blocking_task_runner_(blocking_task_runner),
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delegate_(delegate),
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      metadata_(metadata),
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      weak_ptr_factory_(this) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CreateDirectoryOperation::~CreateDirectoryOperation() {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CreateDirectoryOperation::CreateDirectory(
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::FilePath& directory_path,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_exclusive,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_recursive,
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const FileOperationCallback& callback) {
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<std::string>* updated_local_ids = new std::set<std::string>;
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileChange* changed_files(new FileChange);
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      blocking_task_runner_.get(),
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&UpdateLocalState,
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 metadata_,
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 directory_path,
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 is_exclusive,
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 is_recursive,
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 updated_local_ids,
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 changed_files),
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          &CreateDirectoryOperation::CreateDirectoryAfterUpdateLocalState,
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          weak_ptr_factory_.GetWeakPtr(),
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          callback,
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::Owned(updated_local_ids),
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::Owned(changed_files)));
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CreateDirectoryOperation::CreateDirectoryAfterUpdateLocalState(
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const FileOperationCallback& callback,
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::set<std::string>* updated_local_ids,
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const FileChange* changed_files,
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FileError error) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<std::string>::const_iterator it = updated_local_ids->begin();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != updated_local_ids->end(); ++it)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnEntryUpdatedByOperation(*it);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnFileChangedByOperation(*changed_files);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(error);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace file_system
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace drive
184