change_list_processor.h revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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/callback.h"
13#include "base/files/file_path.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/scoped_vector.h"
16#include "base/memory/weak_ptr.h"
17#include "chrome/browser/chromeos/drive/file_errors.h"
18#include "googleurl/src/gurl.h"
19
20namespace google_apis {
21class AboutResource;
22class ResourceList;
23}  // google_apis
24
25namespace drive {
26
27class ResourceEntry;
28
29namespace internal {
30class ResourceMetadata;
31}  // namespace internal
32
33// Class to represent a change list.
34class ChangeList {
35 public:
36  explicit ChangeList(const google_apis::ResourceList& resource_list);
37  ~ChangeList();
38
39  const std::vector<ResourceEntry>& entries() const { return entries_; }
40  std::vector<ResourceEntry>* mutable_entries() { return &entries_; }
41  const GURL& next_url() const { return next_url_; }
42  int64 largest_changestamp() const { return largest_changestamp_; }
43
44 private:
45  std::vector<ResourceEntry> entries_;
46  GURL next_url_;
47  int64 largest_changestamp_;
48
49  DISALLOW_COPY_AND_ASSIGN(ChangeList);
50};
51
52// ChangeListProcessor is used to process feeds from WAPI (codename for
53// Documents List API) or Google Drive API.
54class ChangeListProcessor {
55 public:
56  typedef std::map<std::string /* resource_id */, ResourceEntry>
57      ResourceEntryMap;
58
59  // Class used to record UMA stats with FeedToEntryProtoMap().
60  class ChangeListToEntryProtoMapUMAStats;
61
62  explicit ChangeListProcessor(internal::ResourceMetadata* resource_metadata);
63  ~ChangeListProcessor();
64
65  // Applies the documents feeds to the file system using |resource_metadata_|.
66  //
67  // |is_delta_feed| determines the type of feed to process, whether it is a
68  // root feed (false) or a delta feed (true).
69  //
70  // In the case of processing the root feeds |root_feed_changestamp| is used
71  // as its initial changestamp value. The value comes from
72  // google_apis::AccountMetadata.
73  // |on_complete_callback| is run after the feed is applied.
74  // |on_complete_callback| must not be null.
75  // TODO(achuith): Change the type of on_complete_callback to
76  // FileOperationCallback instead.
77  void ApplyFeeds(scoped_ptr<google_apis::AboutResource> about_resource,
78                  ScopedVector<ChangeList> change_lists,
79                  bool is_delta_feed,
80                  const base::Closure& on_complete_callback);
81
82  // Converts list of document feeds from collected feeds into a
83  // ResourceEntryMap. |feed_changestamp| and/or |uma_stats| may be NULL.
84  // entry_map_ is updated as side effects.
85  void FeedToEntryProtoMap(ScopedVector<ChangeList> change_lists,
86                           int64* feed_changestamp,
87                           ChangeListToEntryProtoMapUMAStats* uma_stats);
88
89  // A map of ResourceEntry's representing a feed.
90  const ResourceEntryMap& entry_map() const { return entry_map_; }
91
92  // The set of changed directories as a result of feed processing.
93  const std::set<base::FilePath>& changed_dirs() const { return changed_dirs_; }
94
95 private:
96  // Applies the pre-processed feed from entry_map_ onto the filesystem.
97  // If this is not delta feed update (i.e. |is_delta_feed| is false),
98  // |about_resource| must not be null.
99  void ApplyEntryProtoMap(
100      bool is_delta_feed,
101      scoped_ptr<google_apis::AboutResource> about_resource);
102  void ApplyEntryProtoMapAfterReset(
103      scoped_ptr<google_apis::AboutResource> about_resource,
104      FileError error);
105
106  // Apply the next item from entry_map_ to the file system. The async
107  // version posts to the message loop to avoid recursive stack-overflow.
108  void ApplyNextEntryProto();
109  void ApplyNextEntryProtoAsync();
110
111  // Apply |entry| to resource_metadata_.
112  void ApplyEntryProto(const ResourceEntry& entry);
113
114  // Continue ApplyEntryProto. This is a callback for
115  // ResourceMetadata::GetEntryInfoByResourceId.
116  void ContinueApplyEntryProto(
117      const ResourceEntry& entry,
118      FileError error,
119      const base::FilePath& file_path,
120      scoped_ptr<ResourceEntry> old_entry);
121
122  // Apply the ResourceEntry pointed to by |it| to resource_metadata_.
123  void ApplyNextByIterator(ResourceEntryMap::iterator it);
124
125  // Helper function to add |entry| to its parent. Updates changed_dirs_
126  // as a side effect.
127  void AddEntry(const ResourceEntry& entry);
128
129  // Callback for ResourceMetadata::AddEntry.
130  void NotifyForAddEntry(bool is_directory,
131                         FileError error,
132                         const base::FilePath& file_path);
133
134  // Removes entry pointed to by |resource_id| from its parent. Updates
135  // changed_dirs_ as a side effect.
136  void RemoveEntryFromParent(
137      const ResourceEntry& entry,
138      const base::FilePath& file_path);
139
140  // Continues RemoveEntryFromParent after
141  // ResourceMetadata::GetChildDirectories.
142  void OnGetChildrenForRemove(
143      const ResourceEntry& entry,
144      const base::FilePath& file_path,
145      const std::set<base::FilePath>& child_directories);
146
147  // Callback for ResourceMetadata::RemoveEntryFromParent.
148  void NotifyForRemoveEntryFromParent(
149      bool is_directory,
150      const base::FilePath& file_path,
151      const std::set<base::FilePath>& child_directories,
152      FileError error,
153      const base::FilePath& parent_path);
154
155  // Refreshes ResourceMetadata entry that has the same resource_id as
156  // |entry| with |entry|. Updates changed_dirs_ as a side effect.
157  void RefreshEntry(const ResourceEntry& entry,
158                    const base::FilePath& file_path);
159
160  // Callback for ResourceMetadata::RefreshEntry.
161  void NotifyForRefreshEntry(
162      const base::FilePath& old_file_path,
163      FileError error,
164      const base::FilePath& file_path,
165      scoped_ptr<ResourceEntry> entry);
166
167  // Updates the root directory entry. changestamp will be updated. Calls
168  // |closure| upon completion regardless of whether the update was successful
169  // or not.  |closure| must not be null.
170  void UpdateRootEntry(const base::Closure& closure);
171
172  // Part of UpdateRootEntry(). Called after
173  // ResourceMetadata::GetEntryInfoByPath is complete. Updates the root
174  // proto, and refreshes the root entry with the proto.
175  void UpdateRootEntryAfterGetEntry(const base::Closure& closure,
176                                    FileError error,
177                                    scoped_ptr<ResourceEntry> root_proto);
178
179  // Part of UpdateRootEntry(). Called after
180  // ResourceMetadata::RefreshEntry() is complete. Calls OnComplete() to
181  // finish the change list processing.
182  void UpdateRootEntryAfterRefreshEntry(const base::Closure& closure,
183                                        FileError error,
184                                        const base::FilePath& root_path,
185                                        scoped_ptr<ResourceEntry> root_proto);
186
187  // Runs after all entries have been processed.
188  void OnComplete();
189
190  // Reset the state of this object.
191  void Clear();
192
193  internal::ResourceMetadata* resource_metadata_;  // Not owned.
194
195  ResourceEntryMap entry_map_;
196  std::set<base::FilePath> changed_dirs_;
197  int64 largest_changestamp_;
198  base::Closure on_complete_callback_;
199
200  // Note: This should remain the last member so it'll be destroyed and
201  // invalidate its weak pointers before any other members are destroyed.
202  base::WeakPtrFactory<ChangeListProcessor> weak_ptr_factory_;
203  DISALLOW_COPY_AND_ASSIGN(ChangeListProcessor);
204};
205
206}  // namespace drive
207
208#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_PROCESSOR_H_
209