move_operation.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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_system/operation_observer.h" 10#include "chrome/browser/chromeos/drive/resource_metadata.h" 11#include "content/public/browser/browser_thread.h" 12 13using content::BrowserThread; 14 15namespace drive { 16namespace file_system { 17namespace { 18 19// Looks up ResourceEntry for source entry and the destination directory. 20FileError UpdateLocalState(internal::ResourceMetadata* metadata, 21 const base::FilePath& src_path, 22 const base::FilePath& dest_path, 23 bool preserve_last_modified, 24 std::set<base::FilePath>* changed_directories, 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 // Strip the extension for a hosted document if necessary. 42 const std::string new_extension = 43 base::FilePath(dest_path.Extension()).AsUTF8Unsafe(); 44 const bool has_hosted_document_extension = 45 entry.has_file_specific_info() && 46 entry.file_specific_info().is_hosted_document() && 47 new_extension == entry.file_specific_info().document_extension(); 48 const std::string new_title = 49 has_hosted_document_extension ? 50 dest_path.BaseName().RemoveExtension().AsUTF8Unsafe() : 51 dest_path.BaseName().AsUTF8Unsafe(); 52 53 // Update last_modified. 54 if (!preserve_last_modified) { 55 entry.mutable_file_info()->set_last_modified( 56 base::Time::Now().ToInternalValue()); 57 } 58 59 entry.set_title(new_title); 60 entry.set_parent_local_id(parent_entry.local_id()); 61 entry.set_metadata_edit_state(ResourceEntry::DIRTY); 62 error = metadata->RefreshEntry(entry); 63 if (error != FILE_ERROR_OK) 64 return error; 65 66 changed_directories->insert(src_path.DirName()); 67 changed_directories->insert(dest_path.DirName()); 68 return FILE_ERROR_OK; 69} 70 71} // namespace 72 73MoveOperation::MoveOperation(base::SequencedTaskRunner* blocking_task_runner, 74 OperationObserver* observer, 75 internal::ResourceMetadata* metadata) 76 : blocking_task_runner_(blocking_task_runner), 77 observer_(observer), 78 metadata_(metadata), 79 weak_ptr_factory_(this) { 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81} 82 83MoveOperation::~MoveOperation() { 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 85} 86 87void MoveOperation::Move(const base::FilePath& src_file_path, 88 const base::FilePath& dest_file_path, 89 bool preserve_last_modified, 90 const FileOperationCallback& callback) { 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 92 DCHECK(!callback.is_null()); 93 94 std::set<base::FilePath>* changed_directories = new std::set<base::FilePath>; 95 std::string* local_id = new std::string; 96 base::PostTaskAndReplyWithResult( 97 blocking_task_runner_.get(), 98 FROM_HERE, 99 base::Bind(&UpdateLocalState, 100 metadata_, 101 src_file_path, 102 dest_file_path, 103 preserve_last_modified, 104 changed_directories, 105 local_id), 106 base::Bind(&MoveOperation::MoveAfterUpdateLocalState, 107 weak_ptr_factory_.GetWeakPtr(), 108 callback, 109 base::Owned(changed_directories), 110 base::Owned(local_id))); 111} 112 113void MoveOperation::MoveAfterUpdateLocalState( 114 const FileOperationCallback& callback, 115 const std::set<base::FilePath>* changed_directories, 116 const std::string* local_id, 117 FileError error) { 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 119 if (error == FILE_ERROR_OK) { 120 // Notify the change of directory. 121 for (std::set<base::FilePath>::const_iterator it = 122 changed_directories->begin(); 123 it != changed_directories->end(); ++it) 124 observer_->OnDirectoryChangedByOperation(*it); 125 126 observer_->OnEntryUpdatedByOperation(*local_id); 127 } 128 callback.Run(error); 129} 130 131} // namespace file_system 132} // namespace drive 133