1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_PROCESSOR_H_
6#define CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_PROCESSOR_H_
7
8#include <map>
9#include <set>
10#include <string>
11
12#include "base/files/file_path.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/scoped_vector.h"
15#include "chrome/browser/chromeos/drive/file_errors.h"
16#include "chrome/browser/chromeos/drive/file_errors.h"
17#include "url/gurl.h"
18
19namespace google_apis {
20class AboutResource;
21class ChangeList;
22class FileList;
23}  // google_apis
24
25namespace drive {
26
27class FileChange;
28class ResourceEntry;
29
30namespace internal {
31
32class ResourceMetadata;
33
34// Holds information needed to fetch contents of a directory.
35// This object is copyable.
36class DirectoryFetchInfo {
37 public:
38  DirectoryFetchInfo() : changestamp_(0) {}
39  DirectoryFetchInfo(const std::string& local_id,
40                     const std::string& resource_id,
41                     int64 changestamp)
42      : local_id_(local_id),
43        resource_id_(resource_id),
44        changestamp_(changestamp) {
45  }
46
47  // Returns true if the object is empty.
48  bool empty() const { return local_id_.empty(); }
49
50  // Local ID of the directory.
51  const std::string& local_id() const { return local_id_; }
52
53  // Resource ID of the directory.
54  const std::string& resource_id() const { return resource_id_; }
55
56  // Changestamp of the directory. The changestamp is used to determine if
57  // the directory contents should be fetched.
58  int64 changestamp() const { return changestamp_; }
59
60  // Returns a string representation of this object.
61  std::string ToString() const;
62
63 private:
64  const std::string local_id_;
65  const std::string resource_id_;
66  const int64 changestamp_;
67};
68
69// Class to represent a change list.
70class ChangeList {
71 public:
72  ChangeList();  // For tests.
73  explicit ChangeList(const google_apis::ChangeList& change_list);
74  explicit ChangeList(const google_apis::FileList& file_list);
75  ~ChangeList();
76
77  const std::vector<ResourceEntry>& entries() const { return entries_; }
78  std::vector<ResourceEntry>* mutable_entries() { return &entries_; }
79  const std::vector<std::string>& parent_resource_ids() const {
80    return parent_resource_ids_;
81  }
82  std::vector<std::string>* mutable_parent_resource_ids() {
83    return &parent_resource_ids_;
84  }
85  const GURL& next_url() const { return next_url_; }
86  int64 largest_changestamp() const { return largest_changestamp_; }
87
88  void set_largest_changestamp(int64 largest_changestamp) {
89    largest_changestamp_ = largest_changestamp;
90  }
91
92 private:
93  std::vector<ResourceEntry> entries_;
94  std::vector<std::string> parent_resource_ids_;
95  GURL next_url_;
96  int64 largest_changestamp_;
97
98  DISALLOW_COPY_AND_ASSIGN(ChangeList);
99};
100
101// ChangeListProcessor is used to process change lists, or full resource
102// lists from WAPI (codename for Documents List API) or Google Drive API, and
103// updates the resource metadata stored locally.
104class ChangeListProcessor {
105 public:
106  explicit ChangeListProcessor(ResourceMetadata* resource_metadata);
107  ~ChangeListProcessor();
108
109  // Applies change lists or full resource lists to |resource_metadata_|.
110  //
111  // |is_delta_update| determines the type of input data to process, whether
112  // it is full resource lists (false) or change lists (true).
113  //
114  // Must be run on the same task runner as |resource_metadata_| uses.
115  FileError Apply(scoped_ptr<google_apis::AboutResource> about_resource,
116                  ScopedVector<ChangeList> change_lists,
117                  bool is_delta_update);
118
119  // The set of changed files as a result of change list processing.
120  const FileChange& changed_files() const { return *changed_files_; }
121
122  // Adds or refreshes the child entries from |change_list| to the directory.
123  static FileError RefreshDirectory(
124      ResourceMetadata* resource_metadata,
125      const DirectoryFetchInfo& directory_fetch_info,
126      scoped_ptr<ChangeList> change_list,
127      std::vector<ResourceEntry>* out_refreshed_entries);
128
129  // Sets |entry|'s parent_local_id.
130  static FileError SetParentLocalIdOfEntry(
131      ResourceMetadata* resource_metadata,
132      ResourceEntry* entry,
133      const std::string& parent_resource_id);
134
135 private:
136  typedef std::map<std::string /* resource_id */, ResourceEntry>
137      ResourceEntryMap;
138  typedef std::map<std::string /* resource_id */,
139                   std::string /* parent_resource_id*/> ParentResourceIdMap;
140
141  // Applies the pre-processed metadata from entry_map_ onto the resource
142  // metadata. |about_resource| must not be null.
143  FileError ApplyEntryMap(
144      int64 changestamp,
145      scoped_ptr<google_apis::AboutResource> about_resource);
146
147  // Apply |entry| to resource_metadata_.
148  FileError ApplyEntry(const ResourceEntry& entry);
149
150  // Adds the directories changed by the update on |entry| to |changed_dirs_|.
151  void UpdateChangedDirs(const ResourceEntry& entry);
152
153  ResourceMetadata* resource_metadata_;  // Not owned.
154
155  ResourceEntryMap entry_map_;
156  ParentResourceIdMap parent_resource_id_map_;
157  scoped_ptr<FileChange> changed_files_;
158
159  DISALLOW_COPY_AND_ASSIGN(ChangeListProcessor);
160};
161
162}  // namespace internal
163}  // namespace drive
164
165#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_PROCESSOR_H_
166