1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/drive/file_system/move_operation.h" 6 7#include "base/sequenced_task_runner.h" 8#include "chrome/browser/chromeos/drive/drive.pb.h" 9#include "chrome/browser/chromeos/drive/file_change.h" 10#include "chrome/browser/chromeos/drive/file_system/operation_delegate.h" 11#include "chrome/browser/chromeos/drive/resource_metadata.h" 12#include "content/public/browser/browser_thread.h" 13 14using content::BrowserThread; 15 16namespace drive { 17namespace file_system { 18namespace { 19 20// Looks up ResourceEntry for source entry and the destination directory. 21FileError UpdateLocalState(internal::ResourceMetadata* metadata, 22 const base::FilePath& src_path, 23 const base::FilePath& dest_path, 24 FileChange* changed_files, 25 std::string* local_id) { 26 ResourceEntry entry; 27 FileError error = metadata->GetResourceEntryByPath(src_path, &entry); 28 if (error != FILE_ERROR_OK) 29 return error; 30 *local_id = entry.local_id(); 31 32 ResourceEntry parent_entry; 33 error = metadata->GetResourceEntryByPath(dest_path.DirName(), &parent_entry); 34 if (error != FILE_ERROR_OK) 35 return error; 36 37 // The parent must be a directory. 38 if (!parent_entry.file_info().is_directory()) 39 return FILE_ERROR_NOT_A_DIRECTORY; 40 41 changed_files->Update(src_path, entry, FileChange::DELETE); 42 43 // Strip the extension for a hosted document if necessary. 44 const std::string new_extension = 45 base::FilePath(dest_path.Extension()).AsUTF8Unsafe(); 46 const bool has_hosted_document_extension = 47 entry.has_file_specific_info() && 48 entry.file_specific_info().is_hosted_document() && 49 new_extension == entry.file_specific_info().document_extension(); 50 const std::string new_title = 51 has_hosted_document_extension ? 52 dest_path.BaseName().RemoveExtension().AsUTF8Unsafe() : 53 dest_path.BaseName().AsUTF8Unsafe(); 54 55 entry.set_title(new_title); 56 entry.set_parent_local_id(parent_entry.local_id()); 57 entry.set_metadata_edit_state(ResourceEntry::DIRTY); 58 entry.set_modification_date(base::Time::Now().ToInternalValue()); 59 error = metadata->RefreshEntry(entry); 60 if (error != FILE_ERROR_OK) 61 return error; 62 63 changed_files->Update(dest_path, entry, FileChange::ADD_OR_UPDATE); 64 return FILE_ERROR_OK; 65} 66 67} // namespace 68 69MoveOperation::MoveOperation(base::SequencedTaskRunner* blocking_task_runner, 70 OperationDelegate* delegate, 71 internal::ResourceMetadata* metadata) 72 : blocking_task_runner_(blocking_task_runner), 73 delegate_(delegate), 74 metadata_(metadata), 75 weak_ptr_factory_(this) { 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 77} 78 79MoveOperation::~MoveOperation() { 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81} 82 83void MoveOperation::Move(const base::FilePath& src_file_path, 84 const base::FilePath& dest_file_path, 85 const FileOperationCallback& callback) { 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 87 DCHECK(!callback.is_null()); 88 89 FileChange* changed_files = new FileChange; 90 std::string* local_id = new std::string; 91 base::PostTaskAndReplyWithResult( 92 blocking_task_runner_.get(), 93 FROM_HERE, 94 base::Bind(&UpdateLocalState, 95 metadata_, 96 src_file_path, 97 dest_file_path, 98 changed_files, 99 local_id), 100 base::Bind(&MoveOperation::MoveAfterUpdateLocalState, 101 weak_ptr_factory_.GetWeakPtr(), 102 callback, 103 base::Owned(changed_files), 104 base::Owned(local_id))); 105} 106 107void MoveOperation::MoveAfterUpdateLocalState( 108 const FileOperationCallback& callback, 109 const FileChange* changed_files, 110 const std::string* local_id, 111 FileError error) { 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 113 if (error == FILE_ERROR_OK) { 114 // Notify the change of directory. 115 delegate_->OnFileChangedByOperation(*changed_files); 116 delegate_->OnEntryUpdatedByOperation(*local_id); 117 } 118 callback.Run(error); 119} 120 121} // namespace file_system 122} // namespace drive 123