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_DRIVE_INTEGRATION_SERVICE_H_
6#define CHROME_BROWSER_CHROMEOS_DRIVE_DRIVE_INTEGRATION_SERVICE_H_
7
8#include "base/callback.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/memory/singleton.h"
11#include "base/memory/weak_ptr.h"
12#include "base/observer_list.h"
13#include "chrome/browser/chromeos/drive/file_errors.h"
14#include "chrome/browser/chromeos/drive/file_system_util.h"
15#include "chrome/browser/chromeos/drive/job_scheduler.h"
16#include "chrome/browser/drive/drive_notification_observer.h"
17#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
18#include "components/keyed_service/core/keyed_service.h"
19#include "content/public/browser/notification_observer.h"
20#include "content/public/browser/notification_registrar.h"
21
22namespace base {
23class FilePath;
24class SequencedTaskRunner;
25}
26
27namespace drive {
28
29class DebugInfoCollector;
30class DownloadHandler;
31class DriveAppRegistry;
32class DriveServiceInterface;
33class EventLogger;
34class FileSystemInterface;
35class JobListInterface;
36
37namespace internal {
38class FileCache;
39class ResourceMetadata;
40class ResourceMetadataStorage;
41}  // namespace internal
42
43// Interface for classes that need to observe events from
44// DriveIntegrationService.  All events are notified on UI thread.
45class DriveIntegrationServiceObserver {
46 public:
47  // Triggered when the file system is mounted.
48  virtual void OnFileSystemMounted() {
49  }
50
51  // Triggered when the file system is being unmounted.
52  virtual void OnFileSystemBeingUnmounted() {
53  }
54
55 protected:
56  virtual ~DriveIntegrationServiceObserver() {}
57};
58
59// DriveIntegrationService is used to integrate Drive to Chrome. This class
60// exposes the file system representation built on top of Drive and some
61// other Drive related objects to the file manager, and some other sub
62// systems.
63//
64// The class is essentially a container that manages lifetime of the objects
65// that are used to integrate Drive to Chrome. The object of this class is
66// created per-profile.
67class DriveIntegrationService : public KeyedService,
68                                public DriveNotificationObserver,
69                                public content::NotificationObserver {
70 public:
71  class PreferenceWatcher;
72
73  // test_drive_service, test_mount_point_name, test_cache_root and
74  // test_file_system are used by tests to inject customized instances.
75  // Pass NULL or the empty value when not interested.
76  // |preference_watcher| observes the drive enable preference, and sets the
77  // enable state when changed. It can be NULL. The ownership is taken by
78  // the DriveIntegrationService.
79  DriveIntegrationService(
80      Profile* profile,
81      PreferenceWatcher* preference_watcher,
82      DriveServiceInterface* test_drive_service,
83      const std::string& test_mount_point_name,
84      const base::FilePath& test_cache_root,
85      FileSystemInterface* test_file_system);
86  virtual ~DriveIntegrationService();
87
88  // KeyedService override:
89  virtual void Shutdown() OVERRIDE;
90
91  void SetEnabled(bool enabled);
92  bool is_enabled() const { return enabled_; }
93
94  bool IsMounted() const;
95
96  // Adds and removes the observer.
97  void AddObserver(DriveIntegrationServiceObserver* observer);
98  void RemoveObserver(DriveIntegrationServiceObserver* observer);
99
100  // DriveNotificationObserver implementation.
101  virtual void OnNotificationReceived() OVERRIDE;
102  virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE;
103
104  EventLogger* event_logger() { return logger_.get(); }
105  DriveServiceInterface* drive_service() { return drive_service_.get(); }
106  DebugInfoCollector* debug_info_collector() {
107    return debug_info_collector_.get();
108  }
109  FileSystemInterface* file_system() { return file_system_.get(); }
110  DownloadHandler* download_handler() { return download_handler_.get(); }
111  DriveAppRegistry* drive_app_registry() { return drive_app_registry_.get(); }
112  JobListInterface* job_list() { return scheduler_.get(); }
113
114  // Clears all the local cache file, the local resource metadata, and
115  // in-memory Drive app registry, and remounts the file system. |callback|
116  // is called with true when this operation is done successfully. Otherwise,
117  // |callback| is called with false. |callback| must not be null.
118  void ClearCacheAndRemountFileSystem(
119      const base::Callback<void(bool)>& callback);
120
121 private:
122  enum State {
123    NOT_INITIALIZED,
124    INITIALIZING,
125    INITIALIZED,
126    REMOUNTING,
127  };
128
129  // Returns true if Drive is enabled.
130  // Must be called on UI thread.
131  bool IsDriveEnabled();
132
133  // Registers remote file system for drive mount point.
134  void AddDriveMountPoint();
135  // Unregisters drive mount point from File API.
136  void RemoveDriveMountPoint();
137
138  // Adds back the drive mount point.
139  // Used to implement ClearCacheAndRemountFileSystem().
140  void AddBackDriveMountPoint(const base::Callback<void(bool)>& callback,
141                              FileError error);
142
143  // Initializes the object. This function should be called before any
144  // other functions.
145  void Initialize();
146
147  // Called when metadata initialization is done. Continues initialization if
148  // the metadata initialization is successful.
149  void InitializeAfterMetadataInitialized(FileError error);
150
151  // Change the download directory to the local "Downloads" if the download
152  // destination is set under Drive. This must be called when disabling Drive.
153  void AvoidDriveAsDownloadDirecotryPreference();
154
155  // content::NotificationObserver overrides.
156  virtual void Observe(int type,
157                       const content::NotificationSource& source,
158                       const content::NotificationDetails& details) OVERRIDE;
159
160  friend class DriveIntegrationServiceFactory;
161
162  Profile* profile_;
163  State state_;
164  bool enabled_;
165  // Custom mount point name that can be injected for testing in constructor.
166  std::string mount_point_name_;
167
168  base::FilePath cache_root_directory_;
169  scoped_ptr<EventLogger> logger_;
170  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
171  scoped_ptr<internal::ResourceMetadataStorage,
172             util::DestroyHelper> metadata_storage_;
173  scoped_ptr<internal::FileCache, util::DestroyHelper> cache_;
174  scoped_ptr<DriveServiceInterface> drive_service_;
175  scoped_ptr<JobScheduler> scheduler_;
176  scoped_ptr<DriveAppRegistry> drive_app_registry_;
177  scoped_ptr<internal::ResourceMetadata,
178             util::DestroyHelper> resource_metadata_;
179  scoped_ptr<FileSystemInterface> file_system_;
180  scoped_ptr<DownloadHandler> download_handler_;
181  scoped_ptr<DebugInfoCollector> debug_info_collector_;
182
183  ObserverList<DriveIntegrationServiceObserver> observers_;
184  scoped_ptr<PreferenceWatcher> preference_watcher_;
185  scoped_ptr<content::NotificationRegistrar> profile_notification_registrar_;
186
187  // Note: This should remain the last member so it'll be destroyed and
188  // invalidate its weak pointers before any other members are destroyed.
189  base::WeakPtrFactory<DriveIntegrationService> weak_ptr_factory_;
190  DISALLOW_COPY_AND_ASSIGN(DriveIntegrationService);
191};
192
193// Singleton that owns all instances of DriveIntegrationService and
194// associates them with Profiles.
195class DriveIntegrationServiceFactory
196    : public BrowserContextKeyedServiceFactory {
197 public:
198  // Factory function used by tests.
199  typedef base::Callback<DriveIntegrationService*(Profile* profile)>
200      FactoryCallback;
201
202  // Sets and resets a factory function for tests. See below for why we can't
203  // use BrowserContextKeyedServiceFactory::SetTestingFactory().
204  class ScopedFactoryForTest {
205   public:
206    explicit ScopedFactoryForTest(FactoryCallback* factory_for_test);
207    ~ScopedFactoryForTest();
208  };
209
210  // Returns the DriveIntegrationService for |profile|, creating it if it is
211  // not yet created.
212  static DriveIntegrationService* GetForProfile(Profile* profile);
213
214  // Returns the DriveIntegrationService that is already associated with
215  // |profile|, if it is not yet created it will return NULL.
216  static DriveIntegrationService* FindForProfile(Profile* profile);
217
218  // Returns the DriveIntegrationServiceFactory instance.
219  static DriveIntegrationServiceFactory* GetInstance();
220
221 private:
222  friend struct DefaultSingletonTraits<DriveIntegrationServiceFactory>;
223
224  DriveIntegrationServiceFactory();
225  virtual ~DriveIntegrationServiceFactory();
226
227  // BrowserContextKeyedServiceFactory overrides.
228  virtual content::BrowserContext* GetBrowserContextToUse(
229      content::BrowserContext* context) const OVERRIDE;
230  virtual KeyedService* BuildServiceInstanceFor(
231      content::BrowserContext* context) const OVERRIDE;
232
233  // This is static so it can be set without instantiating the factory. This
234  // allows factory creation to be delayed until it normally happens (on profile
235  // creation) rather than when tests are set up. DriveIntegrationServiceFactory
236  // transitively depends on ExtensionSystemFactory which crashes if created too
237  // soon (i.e. before the BrowserProcess exists).
238  static FactoryCallback* factory_for_test_;
239};
240
241}  // namespace drive
242
243#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_DRIVE_INTEGRATION_SERVICE_H_
244