create_directory_operation.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/job_scheduler.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/google_apis/gdata_errorcode.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/google_apis/gdata_wapi_parser.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace drive {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace file_system {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Part of CreateDirectoryRecursively(). Adds an |entry| for new directory
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// to |metadata|, and return the status. If succeeded, |file_path| will store
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// the path to the result file.
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)FileError UpdateLocalStateForCreateDirectoryRecursively(
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    internal::ResourceMetadata* metadata,
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ResourceEntry& entry,
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath* file_path) {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(metadata);
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(file_path);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FileError result = metadata->AddEntry(entry);
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Depending on timing, a metadata may be updated by delta feed already.
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // So, FILE_ERROR_EXISTS is not an error.
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result == FILE_ERROR_EXISTS)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    result = FILE_ERROR_OK;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result == FILE_ERROR_OK)
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *file_path = metadata->GetFilePath(entry.resource_id());
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return result;
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CreateDirectoryOperation::CreateDirectoryOperation(
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::SequencedTaskRunner* blocking_task_runner,
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    OperationObserver* observer,
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    JobScheduler* scheduler,
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    internal::ResourceMetadata* metadata)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : blocking_task_runner_(blocking_task_runner),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      observer_(observer),
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      scheduler_(scheduler),
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      metadata_(metadata),
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CreateDirectoryOperation::~CreateDirectoryOperation() {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateDirectoryOperation::CreateDirectory(
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& directory_path,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_exclusive,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_recursive,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileOperationCallback& callback) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ResourceEntry* entry = new ResourceEntry;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      blocking_task_runner_,
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE,
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&CreateDirectoryOperation::GetExistingDeepestDirectory,
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 metadata_, directory_path, entry),
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&CreateDirectoryOperation
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     ::CreateDirectoryAfterGetExistingDeepestDirectory,
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 directory_path, is_exclusive, is_recursive,
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 callback, base::Owned(entry)));
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::FilePath CreateDirectoryOperation::GetExistingDeepestDirectory(
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    internal::ResourceMetadata* metadata,
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& directory_path,
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResourceEntry* entry) {
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(metadata);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(entry);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<base::FilePath::StringType> components;
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  directory_path.GetComponents(&components);
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (components.empty() || components[0] != util::kDriveGrandRootDirName)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return base::FilePath();
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string resource_id = util::kDriveGrandRootSpecialResourceId;
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 1; i < components.size(); ++i) {
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string child_resource_id =
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        metadata->GetChildResourceId(resource_id, components[i]);
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (child_resource_id.empty())
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    resource_id = child_resource_id;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FileError error = metadata->GetResourceEntryById(resource_id, NULL, entry);
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(FILE_ERROR_OK, error);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!entry->file_info().is_directory())
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return base::FilePath();
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return metadata->GetFilePath(resource_id);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CreateDirectoryOperation::CreateDirectoryAfterGetExistingDeepestDirectory(
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& directory_path,
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    bool is_exclusive,
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    bool is_recursive,
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const FileOperationCallback& callback,
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ResourceEntry* existing_deepest_directory_entry,
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& existing_deepest_directory_path) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(existing_deepest_directory_entry);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (existing_deepest_directory_path.empty()) {
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(FILE_ERROR_NOT_FOUND);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (directory_path == existing_deepest_directory_path) {
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If it is not recursive creation, the found directory must be the direct
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // parent of |directory_path| to ensure creating exact one directory.
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!is_recursive &&
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      existing_deepest_directory_path != directory_path.DirName()) {
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(FILE_ERROR_NOT_FOUND);
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create directories under the found directory.
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath remaining_path;
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  existing_deepest_directory_path.AppendRelativePath(
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      directory_path, &remaining_path);
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CreateDirectoryRecursively(existing_deepest_directory_entry->resource_id(),
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             remaining_path, callback);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CreateDirectoryOperation::CreateDirectoryRecursively(
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& parent_resource_id,
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& relative_file_path,
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const FileOperationCallback& callback) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Split the first component and remaining ones of |relative_file_path|.
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<base::FilePath::StringType> components;
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  relative_file_path.GetComponents(&components);
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!components.empty());
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(hidehiko): Rename this variable to "title" with other variable names.
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // crbug.com/242794.
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath name(components[0]);
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath remaining_path;
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  name.AppendRelativePath(relative_file_path, &remaining_path);
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scheduler_->AddNewDirectory(
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      parent_resource_id,
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      name.AsUTF8Unsafe(),
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&CreateDirectoryOperation
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     ::CreateDirectoryRecursivelyAfterAddNewDirectory,
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), remaining_path, callback));
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CreateDirectoryOperation::CreateDirectoryRecursivelyAfterAddNewDirectory(
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& remaining_path,
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const FileOperationCallback& callback,
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    google_apis::GDataErrorCode gdata_error,
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<google_apis::ResourceEntry> resource_entry) {
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FileError error = util::GDataToFileError(gdata_error);
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error != FILE_ERROR_OK) {
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(error);
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(resource_entry);
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that the created directory may be renamed inside
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ResourceMetadata::AddEntry due to name confliction.
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // What we actually need here is the new created path (not the path we try
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // to create).
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath* file_path = new base::FilePath;
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      blocking_task_runner_,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&UpdateLocalStateForCreateDirectoryRecursively,
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 metadata_, ConvertToResourceEntry(*resource_entry), file_path),
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&CreateDirectoryOperation
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     ::CreateDirectoryRecursivelyAfterUpdateLocalState,
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 resource_entry->resource_id(),
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 remaining_path, callback, base::Owned(file_path)));
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CreateDirectoryOperation::CreateDirectoryRecursivelyAfterUpdateLocalState(
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& resource_id,
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& remaining_path,
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const FileOperationCallback& callback,
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath* file_path,
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    FileError error) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error != FILE_ERROR_OK) {
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(error);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  observer_->OnDirectoryChangedByOperation(file_path->DirName());
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (remaining_path.empty()) {
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // All directories are created successfully.
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(FILE_ERROR_OK);
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create descendent directories.
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CreateDirectoryRecursively(resource_id, remaining_path, callback);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace file_system
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace drive
239