1// Copyright 2013 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/sync_file_system/drive_backend/folder_creator.h"
6
7#include "chrome/browser/drive/drive_api_util.h"
8#include "chrome/browser/drive/drive_service_interface.h"
9#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
10#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
11#include "google_apis/drive/drive_api_parser.h"
12#include "google_apis/drive/gdata_wapi_parser.h"
13
14namespace drive {
15class DriveServiceInterface;
16class DriveUploaderInterface;
17}
18
19namespace google_apis {
20class ResourceEntry;
21class ResourceList;
22}
23
24namespace sync_file_system {
25namespace drive_backend {
26
27FolderCreator::FolderCreator(drive::DriveServiceInterface* drive_service,
28                             MetadataDatabase* metadata_database,
29                             const std::string& parent_folder_id,
30                             const std::string& title)
31    : drive_service_(drive_service),
32      metadata_database_(metadata_database),
33      parent_folder_id_(parent_folder_id),
34      title_(title),
35      weak_ptr_factory_(this) {
36}
37
38FolderCreator::~FolderCreator() {
39}
40
41void FolderCreator::Run(const FileIDCallback& callback) {
42  drive_service_->AddNewDirectory(
43      parent_folder_id_,
44      title_,
45      drive::DriveServiceInterface::AddNewDirectoryOptions(),
46      base::Bind(&FolderCreator::DidCreateFolder,
47                 weak_ptr_factory_.GetWeakPtr(), callback));
48}
49
50void FolderCreator::DidCreateFolder(
51    const FileIDCallback& callback,
52    google_apis::GDataErrorCode error,
53    scoped_ptr<google_apis::FileResource> entry) {
54  SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
55  if (status != SYNC_STATUS_OK) {
56    callback.Run(std::string(), status);
57    return;
58  }
59
60  drive_service_->SearchByTitle(
61      title_, parent_folder_id_,
62      base::Bind(&FolderCreator::DidListFolders,
63                 weak_ptr_factory_.GetWeakPtr(), callback,
64                 base::Passed(ScopedVector<google_apis::FileResource>())));
65}
66
67void FolderCreator::DidListFolders(
68    const FileIDCallback& callback,
69    ScopedVector<google_apis::FileResource> candidates,
70    google_apis::GDataErrorCode error,
71    scoped_ptr<google_apis::FileList> file_list) {
72  SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
73  if (status != SYNC_STATUS_OK) {
74    callback.Run(std::string(), status);
75    return;
76  }
77
78  if (!file_list) {
79    NOTREACHED();
80    callback.Run(std::string(), SYNC_STATUS_FAILED);
81    return;
82  }
83
84  candidates.reserve(candidates.size() + file_list->items().size());
85  candidates.insert(candidates.end(),
86                    file_list->items().begin(),
87                    file_list->items().end());
88  file_list->mutable_items()->weak_clear();
89
90  if (!file_list->next_link().is_empty()) {
91    drive_service_->GetRemainingFileList(
92        file_list->next_link(),
93        base::Bind(&FolderCreator::DidListFolders,
94                   weak_ptr_factory_.GetWeakPtr(), callback,
95                   base::Passed(&candidates)));
96    return;
97  }
98
99  const google_apis::FileResource* oldest = NULL;
100  for (size_t i = 0; i < candidates.size(); ++i) {
101    const google_apis::FileResource& entry = *candidates[i];
102    if (!entry.IsDirectory() || entry.labels().is_trashed())
103      continue;
104
105    if (!oldest || oldest->created_date() > entry.created_date())
106      oldest = &entry;
107  }
108
109  if (!oldest) {
110    callback.Run(std::string(), SYNC_FILE_ERROR_NOT_FOUND);
111    return;
112  }
113
114  std::string file_id = oldest->file_id();
115
116  status = metadata_database_->UpdateByFileResourceList(candidates.Pass());
117  if (status != SYNC_STATUS_OK) {
118    callback.Run(std::string(), status);
119    return;
120  }
121
122  DCHECK(!file_id.empty());
123  if (!metadata_database_->FindFileByFileID(file_id, NULL)) {
124    callback.Run(std::string(), SYNC_FILE_ERROR_NOT_FOUND);
125    return;
126  }
127
128  callback.Run(file_id, status);
129}
130
131}  // namespace drive_backend
132}  // namespace sync_file_system
133