15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/copy_operation.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/task_runner_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_cache.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/drive/file_change.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/job_scheduler.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_metadata.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/drive/drive_api_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/drive_api_parser.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace file_system {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct CopyOperation::CopyParams {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath src_file_path;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath dest_file_path;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool preserve_last_modified;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileOperationCallback callback;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceEntry src_entry;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceEntry parent_entry;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Enum for categorizing where a gdoc represented by a JSON file exists.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum JsonGdocLocationType {
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NOT_IN_METADATA,
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IS_ORPHAN,
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  HAS_PARENT,
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct CopyOperation::TransferJsonGdocParams {
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TransferJsonGdocParams(const FileOperationCallback& callback,
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const std::string& resource_id,
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const ResourceEntry& parent_entry,
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const std::string& new_title)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : callback(callback),
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        resource_id(resource_id),
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        parent_resource_id(parent_entry.resource_id()),
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        parent_local_id(parent_entry.local_id()),
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new_title(new_title),
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        location_type(NOT_IN_METADATA) {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Parameters supplied or calculated from operation arguments.
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const FileOperationCallback callback;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string resource_id;
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string parent_resource_id;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string parent_local_id;
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string new_title;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Values computed during operation.
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  JsonGdocLocationType location_type;  // types where the gdoc file is located.
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string local_id;  // the local_id of the file (if exists in metadata.)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::FilePath changed_path;
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileError TryToCopyLocally(internal::ResourceMetadata* metadata,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           internal::FileCache* cache,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           CopyOperation::CopyParams* params,
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           std::vector<std::string>* updated_local_ids,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool* directory_changed,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool* should_copy_on_server) {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError error = metadata->GetResourceEntryByPath(params->src_file_path,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                     &params->src_entry);
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != FILE_ERROR_OK)
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return error;
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = metadata->GetResourceEntryByPath(params->dest_file_path.DirName(),
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           &params->parent_entry);
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != FILE_ERROR_OK)
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return error;
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!params->parent_entry.file_info().is_directory())
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Drive File System doesn't support recursive copy.
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (params->src_entry.file_info().is_directory())
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return FILE_ERROR_NOT_A_FILE;
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check destination.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceEntry dest_entry;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = metadata->GetResourceEntryByPath(params->dest_file_path, &dest_entry);
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (error) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case FILE_ERROR_OK:
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // File API spec says it is an error to try to "copy a file to a path
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // occupied by a directory".
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (dest_entry.file_info().is_directory())
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return FILE_ERROR_INVALID_OPERATION;
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Move the existing entry to the trash.
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dest_entry.set_parent_local_id(util::kDriveTrashDirLocalId);
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = metadata->RefreshEntry(dest_entry);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (error != FILE_ERROR_OK)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return error;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      updated_local_ids->push_back(dest_entry.local_id());
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *directory_changed = true;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case FILE_ERROR_NOT_FOUND:
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return error;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the cache file is not present and the entry exists on the server,
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // server side copy should be used.
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!params->src_entry.file_specific_info().cache_state().is_present() &&
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      !params->src_entry.resource_id().empty()) {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *should_copy_on_server = true;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_OK;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Copy locally.
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceEntry entry;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int64 now = base::Time::Now().ToInternalValue();
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.set_title(params->dest_file_path.BaseName().AsUTF8Unsafe());
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.set_parent_local_id(params->parent_entry.local_id());
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_specific_info()->set_content_mime_type(
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      params->src_entry.file_specific_info().content_mime_type());
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.set_metadata_edit_state(ResourceEntry::DIRTY);
1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  entry.set_modification_date(base::Time::Now().ToInternalValue());
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_info()->set_last_modified(
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      params->preserve_last_modified ?
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      params->src_entry.file_info().last_modified() : now);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  entry.mutable_file_info()->set_last_accessed(now);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string local_id;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = metadata->AddEntry(entry, &local_id);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != FILE_ERROR_OK)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return error;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  updated_local_ids->push_back(local_id);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *directory_changed = true;
146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!params->src_entry.file_specific_info().cache_state().is_present()) {
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(params->src_entry.resource_id().empty());
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Locally created empty file may have no cache file.
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return FILE_ERROR_OK;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath cache_file_path;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = cache->GetFile(params->src_entry.local_id(), &cache_file_path);
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != FILE_ERROR_OK)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return error;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return cache->Store(local_id, std::string(), cache_file_path,
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      internal::FileCache::FILE_OPERATION_COPY);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Stores the entry returned from the server and returns its path.
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)FileError UpdateLocalStateForServerSideOperation(
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    internal::ResourceMetadata* metadata,
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<google_apis::FileResource> file_resource,
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ResourceEntry* entry,
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::FilePath* file_path) {
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(file_resource);
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string parent_resource_id;
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!ConvertFileResourceToResourceEntry(
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          *file_resource, entry, &parent_resource_id) ||
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      parent_resource_id.empty())
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return FILE_ERROR_NOT_A_FILE;
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string parent_local_id;
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileError error = metadata->GetIdByResourceId(parent_resource_id,
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                &parent_local_id);
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (error != FILE_ERROR_OK)
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return error;
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  entry->set_parent_local_id(parent_local_id);
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string local_id;
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  error = metadata->AddEntry(*entry, &local_id);
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Depending on timing, the metadata may have inserted via change list
186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // already. So, FILE_ERROR_EXISTS is not an error.
187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error == FILE_ERROR_EXISTS)
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error = metadata->GetIdByResourceId(entry->resource_id(), &local_id);
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error != FILE_ERROR_OK)
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return metadata->GetFilePath(local_id, file_path);
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Stores the file at |local_file_path| to the cache as a content of entry at
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |remote_dest_path|, and marks it dirty.
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FileError UpdateLocalStateForScheduleTransfer(
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    internal::ResourceMetadata* metadata,
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    internal::FileCache* cache,
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& local_src_path,
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& remote_dest_path,
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ResourceEntry* entry,
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string* local_id) {
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileError error = metadata->GetIdByPath(remote_dest_path, local_id);
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (error != FILE_ERROR_OK)
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return error;
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  error = metadata->GetResourceEntryById(*local_id, entry);
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (error != FILE_ERROR_OK)
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return error;
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return cache->Store(*local_id, std::string(), local_src_path,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      internal::FileCache::FILE_OPERATION_COPY);
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Gets the file size of the |local_path|, and the ResourceEntry for the parent
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// of |remote_path| to prepare the necessary information for transfer.
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileError PrepareTransferFileFromLocalToRemote(
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    internal::ResourceMetadata* metadata,
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& local_src_path,
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& remote_dest_path,
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string* gdoc_resource_id,
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ResourceEntry* parent_entry) {
225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError error = metadata->GetResourceEntryByPath(
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      remote_dest_path.DirName(), parent_entry);
227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != FILE_ERROR_OK)
228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return error;
229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
230424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // The destination's parent must be a directory.
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!parent_entry->file_info().is_directory())
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Try to parse GDoc File and extract the resource id, if necessary.
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Failing isn't problem. It'd be handled as a regular file, then.
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (util::HasHostedDocumentExtension(local_src_path))
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    *gdoc_resource_id = util::ReadResourceIdFromGDocFile(local_src_path);
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return FILE_ERROR_OK;
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Performs local work before server-side work for transferring JSON-represented
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// gdoc files.
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)FileError LocalWorkForTransferJsonGdocFile(
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    internal::ResourceMetadata* metadata,
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CopyOperation::TransferJsonGdocParams* params) {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string local_id;
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FileError error = metadata->GetIdByResourceId(params->resource_id, &local_id);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error != FILE_ERROR_OK) {
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params->location_type = NOT_IN_METADATA;
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return error == FILE_ERROR_NOT_FOUND ? FILE_ERROR_OK : error;
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ResourceEntry entry;
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  error = metadata->GetResourceEntryById(local_id, &entry);
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error != FILE_ERROR_OK)
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return error;
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  params->local_id = entry.local_id();
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (entry.parent_local_id() == util::kDriveOtherDirLocalId) {
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params->location_type = IS_ORPHAN;
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    entry.set_title(params->new_title);
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    entry.set_parent_local_id(params->parent_local_id);
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    entry.set_metadata_edit_state(ResourceEntry::DIRTY);
2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    entry.set_modification_date(base::Time::Now().ToInternalValue());
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error = metadata->RefreshEntry(entry);
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (error != FILE_ERROR_OK)
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return error;
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return metadata->GetFilePath(local_id, &params->changed_path);
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  params->location_type = HAS_PARENT;
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return FILE_ERROR_OK;
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             OperationDelegate* delegate,
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             JobScheduler* scheduler,
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             internal::ResourceMetadata* metadata,
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             internal::FileCache* cache)
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  : blocking_task_runner_(blocking_task_runner),
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_(delegate),
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scheduler_(scheduler),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metadata_(metadata),
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cache_(cache),
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    create_file_operation_(new CreateFileOperation(blocking_task_runner,
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                   delegate,
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                   metadata)),
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    weak_ptr_factory_(this) {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CopyOperation::~CopyOperation() {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CopyOperation::Copy(const base::FilePath& src_file_path,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const base::FilePath& dest_file_path,
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                         bool preserve_last_modified,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const FileOperationCallback& callback) {
302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CopyParams* params = new CopyParams;
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params->src_file_path = src_file_path;
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params->dest_file_path = dest_file_path;
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params->preserve_last_modified = preserve_last_modified;
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params->callback = callback;
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string>* updated_local_ids = new std::vector<std::string>;
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool* directory_changed = new bool(false);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool* should_copy_on_server = new bool(false);
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      blocking_task_runner_.get(),
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      FROM_HERE,
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&TryToCopyLocally, metadata_, cache_, params,
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 updated_local_ids, directory_changed, should_copy_on_server),
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&CopyOperation::CopyAfterTryToCopyLocally,
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), base::Owned(params),
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Owned(updated_local_ids), base::Owned(directory_changed),
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Owned(should_copy_on_server)));
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CopyOperation::CopyAfterTryToCopyLocally(
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CopyParams* params,
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<std::string>* updated_local_ids,
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bool* directory_changed,
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bool* should_copy_on_server,
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FileError error) {
331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!params->callback.is_null());
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < updated_local_ids->size(); ++i)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnEntryUpdatedByOperation((*updated_local_ids)[i]);
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (*directory_changed) {
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FileChange changed_file;
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(!params->src_entry.file_info().is_directory());
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    changed_file.Update(params->dest_file_path,
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        FileChange::FILE_TYPE_FILE,
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        FileChange::ADD_OR_UPDATE);
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnFileChangedByOperation(changed_file);
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != FILE_ERROR_OK || !*should_copy_on_server) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    params->callback.Run(error);
348424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
349424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (params->parent_entry.resource_id().empty()) {
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Parent entry may be being synced.
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const bool waiting = delegate_->WaitForSyncComplete(
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        params->parent_entry.local_id(),
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&CopyOperation::CopyAfterParentSync,
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), *params));
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!waiting)
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      params->callback.Run(FILE_ERROR_NOT_FOUND);
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CopyAfterGetParentResourceId(*params, &params->parent_entry, FILE_ERROR_OK);
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void CopyOperation::CopyAfterParentSync(const CopyParams& params,
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        FileError error) {
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!params.callback.is_null());
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (error != FILE_ERROR_OK) {
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    params.callback.Run(error);
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResourceEntry* parent = new ResourceEntry;
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      blocking_task_runner_.get(),
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&internal::ResourceMetadata::GetResourceEntryById,
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 base::Unretained(metadata_),
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 params.parent_entry.local_id(),
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 parent),
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&CopyOperation::CopyAfterGetParentResourceId,
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr(),
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 params,
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Owned(parent)));
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void CopyOperation::CopyAfterGetParentResourceId(const CopyParams& params,
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 const ResourceEntry* parent,
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                 FileError error) {
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!params.callback.is_null());
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (error != FILE_ERROR_OK) {
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    params.callback.Run(error);
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath new_title = params.dest_file_path.BaseName();
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (params.src_entry.file_specific_info().is_hosted_document()) {
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Drop the document extension, which should not be in the title.
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // TODO(yoshiki): Remove this code with crbug.com/223304.
403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    new_title = new_title.RemoveExtension();
404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Time last_modified =
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      params.preserve_last_modified ?
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Time::FromInternalValue(
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          params.src_entry.file_info().last_modified()) : base::Time();
410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CopyResourceOnServer(
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      params.src_entry.resource_id(), parent->resource_id(),
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new_title.AsUTF8Unsafe(), last_modified, params.callback);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyOperation::TransferFileFromLocalToRemote(
417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& local_src_path,
418424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& remote_dest_path,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileOperationCallback& callback) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string* gdoc_resource_id = new std::string;
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ResourceEntry* parent_entry = new ResourceEntry;
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::PostTaskAndReplyWithResult(
426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      blocking_task_runner_.get(),
427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(
429424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          &PrepareTransferFileFromLocalToRemote,
43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          metadata_, local_src_path, remote_dest_path,
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          gdoc_resource_id, parent_entry),
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          &CopyOperation::TransferFileFromLocalToRemoteAfterPrepare,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          weak_ptr_factory_.GetWeakPtr(),
435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          local_src_path, remote_dest_path, callback,
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Owned(gdoc_resource_id), base::Owned(parent_entry)));
437424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
438424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void CopyOperation::TransferFileFromLocalToRemoteAfterPrepare(
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& local_src_path,
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::FilePath& remote_dest_path,
442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const FileOperationCallback& callback,
44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string* gdoc_resource_id,
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ResourceEntry* parent_entry,
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FileError error) {
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!callback.is_null());
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != FILE_ERROR_OK) {
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    callback.Run(error);
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // For regular files, schedule the transfer.
45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (gdoc_resource_id->empty()) {
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ScheduleTransferRegularFile(local_src_path, remote_dest_path, callback);
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // GDoc file may contain a resource ID in the old format.
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const std::string canonicalized_resource_id =
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      util::CanonicalizeResourceId(*gdoc_resource_id);
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Drop the document extension, which should not be in the title.
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(yoshiki): Remove this code with crbug.com/223304.
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string new_title =
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      remote_dest_path.BaseName().RemoveExtension().AsUTF8Unsafe();
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This is uploading a JSON file representing a hosted document.
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TransferJsonGdocParams* params = new TransferJsonGdocParams(
471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      callback, canonicalized_resource_id, *parent_entry, new_title);
472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      blocking_task_runner_.get(),
474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&LocalWorkForTransferJsonGdocFile, metadata_, params),
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&CopyOperation::TransferJsonGdocFileAfterLocalWork,
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), base::Owned(params)));
478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CopyOperation::TransferJsonGdocFileAfterLocalWork(
481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TransferJsonGdocParams* params,
482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FileError error) {
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error != FILE_ERROR_OK) {
486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params->callback.Run(error);
487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (params->location_type) {
491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // When |resource_id| is found in the local metadata and it has a specific
492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // parent folder, we assume the user's intention is to copy the document and
493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // thus perform the server-side copy operation.
494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case HAS_PARENT:
495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CopyResourceOnServer(params->resource_id,
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           params->parent_resource_id,
497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           params->new_title,
498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           base::Time(),
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           params->callback);
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // When |resource_id| has no parent, we just set the new destination folder
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // as the parent, for sharing the document between the original source.
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // This reparenting is already done in LocalWorkForTransferJsonGdocFile().
504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case IS_ORPHAN: {
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK(!params->changed_path.empty());
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delegate_->OnEntryUpdatedByOperation(params->local_id);
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FileChange changed_file;
509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      changed_file.Update(
510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          params->changed_path,
511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          FileChange::FILE_TYPE_FILE,  // This must be a hosted document.
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          FileChange::ADD_OR_UPDATE);
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delegate_->OnFileChangedByOperation(changed_file);
514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      params->callback.Run(error);
515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // When the |resource_id| is not in the local metadata, assume it to be a
518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // document just now shared on the server but not synced locally.
519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Same as the IS_ORPHAN case, we want to deal the case by setting parent,
520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // but this time we need to resort to server side operation.
521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case NOT_IN_METADATA:
522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      scheduler_->UpdateResource(
523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          params->resource_id,
524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          params->parent_resource_id,
525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          params->new_title,
526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Time(),
527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Time(),
528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          ClientContext(USER_INITIATED),
529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Bind(&CopyOperation::UpdateAfterServerSideOperation,
530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     params->callback));
532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
534424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
536424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void CopyOperation::CopyResourceOnServer(
537424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& resource_id,
538424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& parent_resource_id,
539424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& new_title,
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const base::Time& last_modified,
541424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const FileOperationCallback& callback) {
542424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
543424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!callback.is_null());
544424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
545424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scheduler_->CopyResource(
54668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      resource_id, parent_resource_id, new_title, last_modified,
547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&CopyOperation::UpdateAfterServerSideOperation,
548424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
549424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 callback));
550424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
551424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CopyOperation::UpdateAfterServerSideOperation(
553424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const FileOperationCallback& callback,
554424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    google_apis::GDataErrorCode status,
555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<google_apis::FileResource> entry) {
556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
557424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!callback.is_null());
558424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError error = GDataToFileError(status);
560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != FILE_ERROR_OK) {
561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    callback.Run(error);
562424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResourceEntry* resource_entry = new ResourceEntry;
566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // The copy on the server side is completed successfully. Update the local
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // metadata.
569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::FilePath* file_path = new base::FilePath;
570424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      blocking_task_runner_.get(),
572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      FROM_HERE,
573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&UpdateLocalStateForServerSideOperation,
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 metadata_,
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 base::Passed(&entry),
576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 resource_entry,
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 file_path),
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&CopyOperation::UpdateAfterLocalStateUpdate,
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 callback,
581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 base::Owned(file_path),
582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 base::Owned(resource_entry)));
583424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CopyOperation::UpdateAfterLocalStateUpdate(
586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const FileOperationCallback& callback,
587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::FilePath* file_path,
588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ResourceEntry* entry,
589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FileError error) {
590424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
591424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!callback.is_null());
592424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (error == FILE_ERROR_OK) {
594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FileChange changed_file;
595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    changed_file.Update(*file_path, *entry, FileChange::ADD_OR_UPDATE);
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnFileChangedByOperation(changed_file);
597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
598424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  callback.Run(error);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CopyOperation::ScheduleTransferRegularFile(
6023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& local_src_path,
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& remote_dest_path,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileOperationCallback& callback) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  create_file_operation_->CreateFile(
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      remote_dest_path,
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      false,  // Not exclusive (OK even if a file already exists).
6113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      std::string(),  // no specific mime type; CreateFile should guess it.
6123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&CopyOperation::ScheduleTransferRegularFileAfterCreate,
6133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
6143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 local_src_path, remote_dest_path, callback));
6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void CopyOperation::ScheduleTransferRegularFileAfterCreate(
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& local_src_path,
6193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::FilePath& remote_dest_path,
6203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const FileOperationCallback& callback,
6213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    FileError error) {
6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!callback.is_null());
6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (error != FILE_ERROR_OK) {
6263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    callback.Run(error);
6273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
63058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string* local_id = new std::string;
631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResourceEntry* entry = new ResourceEntry;
6327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
6337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      blocking_task_runner_.get(),
6347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      FROM_HERE,
635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&UpdateLocalStateForScheduleTransfer,
636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 metadata_,
637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 cache_,
638116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 local_src_path,
639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 remote_dest_path,
640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 entry,
641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 local_id),
6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(
6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          &CopyOperation::ScheduleTransferRegularFileAfterUpdateLocalState,
644116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          weak_ptr_factory_.GetWeakPtr(),
645116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          callback,
646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          remote_dest_path,
647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::Owned(entry),
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Owned(local_id)));
6497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
6507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void CopyOperation::ScheduleTransferRegularFileAfterUpdateLocalState(
6527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const FileOperationCallback& callback,
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::FilePath& remote_dest_path,
654116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ResourceEntry* entry,
65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string* local_id,
6567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    FileError error) {
6573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!callback.is_null());
6593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error == FILE_ERROR_OK) {
661116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FileChange changed_file;
662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    changed_file.Update(remote_dest_path, *entry, FileChange::ADD_OR_UPDATE);
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnFileChangedByOperation(changed_file);
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnEntryUpdatedByOperation(*local_id);
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.Run(error);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace file_system
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace drive
671