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_DRIVE_FAKE_DRIVE_SERVICE_H_
6#define CHROME_BROWSER_DRIVE_FAKE_DRIVE_SERVICE_H_
7
8#include "base/files/file_path.h"
9#include "chrome/browser/drive/drive_service_interface.h"
10
11namespace base {
12class DictionaryValue;
13}
14
15namespace google_apis {
16class AboutResource;
17class ChangeResource;
18class FileResource;
19}
20
21namespace drive {
22
23// This class implements a fake DriveService which acts like a real Drive
24// service. The fake service works as follows:
25//
26// 1) Load JSON files and construct the in-memory resource list.
27// 2) Return valid responses based on the the in-memory resource list.
28// 3) Update the in-memory resource list by requests like DeleteResource().
29class FakeDriveService : public DriveServiceInterface {
30 public:
31  class ChangeObserver {
32   public:
33    virtual ~ChangeObserver() {}
34    virtual void OnNewChangeAvailable() = 0;
35  };
36
37  FakeDriveService();
38  virtual ~FakeDriveService();
39
40  // Loads the app list for Drive API. Returns true on success.
41  bool LoadAppListForDriveApi(const std::string& relative_path);
42
43  // Adds an app to app list.
44  void AddApp(const std::string& app_id,
45              const std::string& app_name,
46              const std::string& product_id,
47              const std::string& create_url);
48
49  // Removes an app by product id.
50  void RemoveAppByProductId(const std::string& product_id);
51
52  // Returns true if the service knows the given drive app id.
53  bool HasApp(const std::string& app_id) const;
54
55  // Changes the offline state. All functions fail with GDATA_NO_CONNECTION
56  // when offline. By default the offline state is false.
57  void set_offline(bool offline) { offline_ = offline; }
58
59  // GetAllFileList never returns result when this is set to true.
60  // Used to emulate the real server's slowness.
61  void set_never_return_all_file_list(bool value) {
62    never_return_all_file_list_ = value;
63  }
64
65  // Changes the default max results returned from GetAllFileList().
66  // By default, it's set to 0, which is unlimited.
67  void set_default_max_results(int default_max_results) {
68    default_max_results_ = default_max_results;
69  }
70
71  // Sets the url to the test server to be used as a base for generated share
72  // urls to the share dialog.
73  void set_share_url_base(const GURL& share_url_base) {
74    share_url_base_ = share_url_base;
75  }
76
77  // Changes the quota fields returned from GetAboutResource().
78  void SetQuotaValue(int64 used, int64 total);
79
80  // Returns the AboutResource.
81  const google_apis::AboutResource& about_resource() const {
82    return *about_resource_;
83  }
84
85  // Returns the number of times the file list is successfully loaded by
86  // GetAllFileList().
87  int file_list_load_count() const { return file_list_load_count_; }
88
89  // Returns the number of times the resource list is successfully loaded by
90  // GetChangeList().
91  int change_list_load_count() const { return change_list_load_count_; }
92
93  // Returns the number of times the resource list is successfully loaded by
94  // GetFileListInDirectory().
95  int directory_load_count() const { return directory_load_count_; }
96
97  // Returns the number of times the about resource is successfully loaded
98  // by GetAboutResource().
99  int about_resource_load_count() const {
100    return about_resource_load_count_;
101  }
102
103  // Returns the number of times the app list is successfully loaded by
104  // GetAppList().
105  int app_list_load_count() const { return app_list_load_count_; }
106
107  // Returns the number of times GetAllFileList are blocked due to
108  // set_never_return_all_file_list().
109  int blocked_file_list_load_count() const {
110    return blocked_file_list_load_count_;
111  }
112
113  // Returns the file path whose request is cancelled just before this method
114  // invocation.
115  const base::FilePath& last_cancelled_file() const {
116    return last_cancelled_file_;
117  }
118
119  // Returns the (fake) URL for the link.
120  static GURL GetFakeLinkUrl(const std::string& resource_id);
121
122  // Sets the printf format for constructing the response of AuthorizeApp().
123  // The format string must include two %s that are to be filled with
124  // resource_id and app_id.
125  void set_open_url_format(const std::string& url_format) {
126    open_url_format_ = url_format;
127  }
128
129  // DriveServiceInterface Overrides
130  virtual void Initialize(const std::string& account_id) OVERRIDE;
131  virtual void AddObserver(DriveServiceObserver* observer) OVERRIDE;
132  virtual void RemoveObserver(DriveServiceObserver* observer) OVERRIDE;
133  virtual bool CanSendRequest() const OVERRIDE;
134  virtual std::string GetRootResourceId() const OVERRIDE;
135  virtual bool HasAccessToken() const OVERRIDE;
136  virtual void RequestAccessToken(
137      const google_apis::AuthStatusCallback& callback) OVERRIDE;
138  virtual bool HasRefreshToken() const OVERRIDE;
139  virtual void ClearAccessToken() OVERRIDE;
140  virtual void ClearRefreshToken() OVERRIDE;
141  virtual google_apis::CancelCallback GetAllFileList(
142      const google_apis::FileListCallback& callback) OVERRIDE;
143  virtual google_apis::CancelCallback GetFileListInDirectory(
144      const std::string& directory_resource_id,
145      const google_apis::FileListCallback& callback) OVERRIDE;
146  // See the comment for EntryMatchWidthQuery() in .cc file for details about
147  // the supported search query types.
148  virtual google_apis::CancelCallback Search(
149      const std::string& search_query,
150      const google_apis::FileListCallback& callback) OVERRIDE;
151  virtual google_apis::CancelCallback SearchByTitle(
152      const std::string& title,
153      const std::string& directory_resource_id,
154      const google_apis::FileListCallback& callback) OVERRIDE;
155  virtual google_apis::CancelCallback GetChangeList(
156      int64 start_changestamp,
157      const google_apis::ChangeListCallback& callback) OVERRIDE;
158  virtual google_apis::CancelCallback GetRemainingChangeList(
159      const GURL& next_link,
160      const google_apis::ChangeListCallback& callback) OVERRIDE;
161  virtual google_apis::CancelCallback GetRemainingFileList(
162      const GURL& next_link,
163      const google_apis::FileListCallback& callback) OVERRIDE;
164  virtual google_apis::CancelCallback GetFileResource(
165      const std::string& resource_id,
166      const google_apis::FileResourceCallback& callback) OVERRIDE;
167  virtual google_apis::CancelCallback GetShareUrl(
168      const std::string& resource_id,
169      const GURL& embed_origin,
170      const google_apis::GetShareUrlCallback& callback) OVERRIDE;
171  virtual google_apis::CancelCallback GetAboutResource(
172      const google_apis::AboutResourceCallback& callback) OVERRIDE;
173  virtual google_apis::CancelCallback GetAppList(
174      const google_apis::AppListCallback& callback) OVERRIDE;
175  virtual google_apis::CancelCallback DeleteResource(
176      const std::string& resource_id,
177      const std::string& etag,
178      const google_apis::EntryActionCallback& callback) OVERRIDE;
179  virtual google_apis::CancelCallback TrashResource(
180      const std::string& resource_id,
181      const google_apis::EntryActionCallback& callback) OVERRIDE;
182  virtual google_apis::CancelCallback DownloadFile(
183      const base::FilePath& local_cache_path,
184      const std::string& resource_id,
185      const google_apis::DownloadActionCallback& download_action_callback,
186      const google_apis::GetContentCallback& get_content_callback,
187      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
188  virtual google_apis::CancelCallback CopyResource(
189      const std::string& resource_id,
190      const std::string& parent_resource_id,
191      const std::string& new_title,
192      const base::Time& last_modified,
193      const google_apis::FileResourceCallback& callback) OVERRIDE;
194  virtual google_apis::CancelCallback UpdateResource(
195      const std::string& resource_id,
196      const std::string& parent_resource_id,
197      const std::string& new_title,
198      const base::Time& last_modified,
199      const base::Time& last_viewed_by_me,
200      const google_apis::FileResourceCallback& callback) OVERRIDE;
201  virtual google_apis::CancelCallback AddResourceToDirectory(
202      const std::string& parent_resource_id,
203      const std::string& resource_id,
204      const google_apis::EntryActionCallback& callback) OVERRIDE;
205  virtual google_apis::CancelCallback RemoveResourceFromDirectory(
206      const std::string& parent_resource_id,
207      const std::string& resource_id,
208      const google_apis::EntryActionCallback& callback) OVERRIDE;
209  virtual google_apis::CancelCallback AddNewDirectory(
210      const std::string& parent_resource_id,
211      const std::string& directory_title,
212      const AddNewDirectoryOptions& options,
213      const google_apis::FileResourceCallback& callback) OVERRIDE;
214  virtual google_apis::CancelCallback InitiateUploadNewFile(
215      const std::string& content_type,
216      int64 content_length,
217      const std::string& parent_resource_id,
218      const std::string& title,
219      const InitiateUploadNewFileOptions& options,
220      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
221  virtual google_apis::CancelCallback InitiateUploadExistingFile(
222      const std::string& content_type,
223      int64 content_length,
224      const std::string& resource_id,
225      const InitiateUploadExistingFileOptions& options,
226      const google_apis::InitiateUploadCallback& callback) OVERRIDE;
227  virtual google_apis::CancelCallback ResumeUpload(
228      const GURL& upload_url,
229      int64 start_position,
230      int64 end_position,
231      int64 content_length,
232      const std::string& content_type,
233      const base::FilePath& local_file_path,
234      const google_apis::drive::UploadRangeCallback& callback,
235      const google_apis::ProgressCallback& progress_callback) OVERRIDE;
236  virtual google_apis::CancelCallback GetUploadStatus(
237      const GURL& upload_url,
238      int64 content_length,
239      const google_apis::drive::UploadRangeCallback& callback) OVERRIDE;
240  virtual google_apis::CancelCallback AuthorizeApp(
241      const std::string& resource_id,
242      const std::string& app_id,
243      const google_apis::AuthorizeAppCallback& callback) OVERRIDE;
244  virtual google_apis::CancelCallback UninstallApp(
245      const std::string& app_id,
246      const google_apis::EntryActionCallback& callback) OVERRIDE;
247  virtual google_apis::CancelCallback AddPermission(
248      const std::string& resource_id,
249      const std::string& email,
250      google_apis::drive::PermissionRole role,
251      const google_apis::EntryActionCallback& callback) OVERRIDE;
252
253  // Adds a new file with the given parameters. On success, returns
254  // HTTP_CREATED with the parsed entry.
255  // |callback| must not be null.
256  void AddNewFile(const std::string& content_type,
257                  const std::string& content_data,
258                  const std::string& parent_resource_id,
259                  const std::string& title,
260                  bool shared_with_me,
261                  const google_apis::FileResourceCallback& callback);
262
263  // Adds a new file with the given |resource_id|. If the id already exists,
264  // it's an error. This is used for testing cross profile file sharing that
265  // needs to have matching resource IDs in different fake service instances.
266  // |callback| must not be null.
267  void AddNewFileWithResourceId(
268      const std::string& resource_id,
269      const std::string& content_type,
270      const std::string& content_data,
271      const std::string& parent_resource_id,
272      const std::string& title,
273      bool shared_with_me,
274      const google_apis::FileResourceCallback& callback);
275
276  // Adds a new directory with the given |resource_id|.
277  // |callback| must not be null.
278  google_apis::CancelCallback AddNewDirectoryWithResourceId(
279      const std::string& resource_id,
280      const std::string& parent_resource_id,
281      const std::string& directory_title,
282      const AddNewDirectoryOptions& options,
283      const google_apis::FileResourceCallback& callback);
284
285  // Sets the last modified time for an entry specified by |resource_id|.
286  // On success, returns HTTP_SUCCESS with the parsed entry.
287  // |callback| must not be null.
288  void SetLastModifiedTime(
289      const std::string& resource_id,
290      const base::Time& last_modified_time,
291      const google_apis::FileResourceCallback& callback);
292
293  // Sets the user's permission for an entry specified by |resource_id|.
294  google_apis::GDataErrorCode SetUserPermission(
295      const std::string& resource_id,
296      google_apis::drive::PermissionRole user_permission);
297
298  void AddChangeObserver(ChangeObserver* observer);
299  void RemoveChangeObserver(ChangeObserver* observer);
300
301 private:
302  struct EntryInfo;
303  struct UploadSession;
304
305  // Returns a pointer to the entry that matches |resource_id|, or NULL if
306  // not found.
307  EntryInfo* FindEntryByResourceId(const std::string& resource_id);
308
309  // Returns a new resource ID, which looks like "resource_id_<num>" where
310  // <num> is a monotonically increasing number starting from 1.
311  std::string GetNewResourceId();
312
313  // Increments |largest_changestamp_| and adds the new changestamp.
314  void AddNewChangestamp(google_apis::ChangeResource* change);
315
316  // Update ETag of |file| based on |largest_changestamp_|.
317  void UpdateETag(google_apis::FileResource* file);
318
319  // Adds a new entry based on the given parameters.
320  // |resource_id| can be empty, in the case, the id is automatically generated.
321  // Returns a pointer to the newly added entry, or NULL if failed.
322  const EntryInfo* AddNewEntry(
323      const std::string& resource_id,
324      const std::string& content_type,
325      const std::string& content_data,
326      const std::string& parent_resource_id,
327      const std::string& title,
328      bool shared_with_me);
329
330  // Core implementation of GetChangeList.
331  // This method returns the slice of the all matched entries, and its range
332  // is between |start_offset| (inclusive) and |start_offset| + |max_results|
333  // (exclusive).
334  // Increments *load_counter by 1 before it returns successfully.
335  void GetChangeListInternal(
336      int64 start_changestamp,
337      const std::string& search_query,
338      const std::string& directory_resource_id,
339      int start_offset,
340      int max_results,
341      int* load_counter,
342      const google_apis::ChangeListCallback& callback);
343
344  // Returns new upload session URL.
345  GURL GetNewUploadSessionUrl();
346
347  void NotifyObservers();
348
349  typedef std::map<std::string, EntryInfo*> EntryInfoMap;
350  EntryInfoMap entries_;
351  scoped_ptr<google_apis::AboutResource> about_resource_;
352  scoped_ptr<base::DictionaryValue> app_info_value_;
353  std::map<GURL, UploadSession> upload_sessions_;
354  int64 published_date_seq_;
355  int64 next_upload_sequence_number_;
356  int default_max_results_;
357  int resource_id_count_;
358  int file_list_load_count_;
359  int change_list_load_count_;
360  int directory_load_count_;
361  int about_resource_load_count_;
362  int app_list_load_count_;
363  int blocked_file_list_load_count_;
364  bool offline_;
365  bool never_return_all_file_list_;
366  base::FilePath last_cancelled_file_;
367  GURL share_url_base_;
368  std::string app_json_template_;
369  std::string open_url_format_;
370
371  ObserverList<ChangeObserver> change_observers_;
372
373  base::WeakPtrFactory<FakeDriveService> weak_ptr_factory_;
374
375  DISALLOW_COPY_AND_ASSIGN(FakeDriveService);
376};
377
378}  // namespace drive
379
380#endif  // CHROME_BROWSER_DRIVE_FAKE_DRIVE_SERVICE_H_
381