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