• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
6 
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/prefs/pref_change_registrar.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chromeos/drive/debug_info_collector.h"
15 #include "chrome/browser/chromeos/drive/download_handler.h"
16 #include "chrome/browser/chromeos/drive/drive_app_registry.h"
17 #include "chrome/browser/chromeos/drive/file_cache.h"
18 #include "chrome/browser/chromeos/drive/file_system.h"
19 #include "chrome/browser/chromeos/drive/file_system_util.h"
20 #include "chrome/browser/chromeos/drive/job_scheduler.h"
21 #include "chrome/browser/chromeos/drive/logging.h"
22 #include "chrome/browser/chromeos/drive/resource_metadata.h"
23 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
24 #include "chrome/browser/chromeos/file_manager/path_util.h"
25 #include "chrome/browser/chromeos/profiles/profile_util.h"
26 #include "chrome/browser/download/download_prefs.h"
27 #include "chrome/browser/download/download_service.h"
28 #include "chrome/browser/download/download_service_factory.h"
29 #include "chrome/browser/drive/drive_api_service.h"
30 #include "chrome/browser/drive/drive_api_util.h"
31 #include "chrome/browser/drive/drive_notification_manager.h"
32 #include "chrome/browser/drive/drive_notification_manager_factory.h"
33 #include "chrome/browser/drive/gdata_wapi_service.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/signin/profile_oauth2_token_service.h"
36 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
37 #include "chrome/common/chrome_version_info.h"
38 #include "chrome/common/pref_names.h"
39 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
40 #include "content/public/browser/browser_context.h"
41 #include "content/public/browser/browser_thread.h"
42 #include "google_apis/drive/auth_service.h"
43 #include "google_apis/drive/gdata_wapi_url_generator.h"
44 #include "grit/generated_resources.h"
45 #include "ui/base/l10n/l10n_util.h"
46 #include "webkit/browser/fileapi/external_mount_points.h"
47 #include "webkit/common/user_agent/user_agent_util.h"
48 
49 using content::BrowserContext;
50 using content::BrowserThread;
51 
52 namespace drive {
53 namespace {
54 
55 // Name of the directory used to store metadata.
56 const base::FilePath::CharType kMetadataDirectory[] = FILE_PATH_LITERAL("meta");
57 
58 // Name of the directory used to store cached files.
59 const base::FilePath::CharType kCacheFileDirectory[] =
60     FILE_PATH_LITERAL("files");
61 
62 // Name of the directory used to store temporary files.
63 const base::FilePath::CharType kTemporaryFileDirectory[] =
64     FILE_PATH_LITERAL("tmp");
65 
66 // Returns a user agent string used for communicating with the Drive backend,
67 // both WAPI and Drive API.  The user agent looks like:
68 //
69 // chromedrive-<VERSION> chrome-cc/none (<OS_CPU_INFO>)
70 // chromedrive-24.0.1274.0 chrome-cc/none (CrOS x86_64 0.4.0)
71 //
72 // TODO(satorux): Move this function to somewhere else: crbug.com/151605
GetDriveUserAgent()73 std::string GetDriveUserAgent() {
74   const char kDriveClientName[] = "chromedrive";
75 
76   chrome::VersionInfo version_info;
77   const std::string version = (version_info.is_valid() ?
78                                version_info.Version() :
79                                std::string("unknown"));
80 
81   // This part is <client_name>/<version>.
82   const char kLibraryInfo[] = "chrome-cc/none";
83 
84   const std::string os_cpu_info = webkit_glue::BuildOSCpuInfo();
85 
86   // Add "gzip" to receive compressed data from the server.
87   // (see https://developers.google.com/drive/performance)
88   return base::StringPrintf("%s-%s %s (%s) (gzip)",
89                             kDriveClientName,
90                             version.c_str(),
91                             kLibraryInfo,
92                             os_cpu_info.c_str());
93 }
94 
95 // Initializes FileCache and ResourceMetadata.
96 // Must be run on the same task runner used by |cache| and |resource_metadata|.
InitializeMetadata(const base::FilePath & cache_root_directory,internal::ResourceMetadataStorage * metadata_storage,internal::FileCache * cache,internal::ResourceMetadata * resource_metadata,const ResourceIdCanonicalizer & id_canonicalizer,const base::FilePath & downloads_directory)97 FileError InitializeMetadata(
98     const base::FilePath& cache_root_directory,
99     internal::ResourceMetadataStorage* metadata_storage,
100     internal::FileCache* cache,
101     internal::ResourceMetadata* resource_metadata,
102     const ResourceIdCanonicalizer& id_canonicalizer,
103     const base::FilePath& downloads_directory) {
104   if (!base::CreateDirectory(cache_root_directory.Append(
105           kMetadataDirectory)) ||
106       !base::CreateDirectory(cache_root_directory.Append(
107           kCacheFileDirectory)) ||
108       !base::CreateDirectory(cache_root_directory.Append(
109           kTemporaryFileDirectory))) {
110     LOG(WARNING) << "Failed to create directories.";
111     return FILE_ERROR_FAILED;
112   }
113 
114   // Change permissions of cache file directory to u+rwx,og+x (711) in order to
115   // allow archive files in that directory to be mounted by cros-disks.
116   base::SetPosixFilePermissions(
117       cache_root_directory.Append(kCacheFileDirectory),
118       base::FILE_PERMISSION_USER_MASK |
119       base::FILE_PERMISSION_EXECUTE_BY_GROUP |
120       base::FILE_PERMISSION_EXECUTE_BY_OTHERS);
121 
122   internal::ResourceMetadataStorage::UpgradeOldDB(
123       metadata_storage->directory_path(), id_canonicalizer);
124 
125   if (!metadata_storage->Initialize()) {
126     LOG(WARNING) << "Failed to initialize the metadata storage.";
127     return FILE_ERROR_FAILED;
128   }
129 
130   if (!cache->Initialize()) {
131     LOG(WARNING) << "Failed to initialize the cache.";
132     return FILE_ERROR_FAILED;
133   }
134 
135   if (metadata_storage->cache_file_scan_is_needed()) {
136     // Generate unique directory name.
137     const std::string& dest_directory_name = l10n_util::GetStringUTF8(
138         IDS_FILE_BROWSER_RECOVERED_FILES_FROM_GOOGLE_DRIVE_DIRECTORY_NAME);
139     base::FilePath dest_directory = downloads_directory.Append(
140         base::FilePath::FromUTF8Unsafe(dest_directory_name));
141     for (int uniquifier = 1; base::PathExists(dest_directory); ++uniquifier) {
142       dest_directory = downloads_directory.Append(
143           base::FilePath::FromUTF8Unsafe(dest_directory_name))
144           .InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", uniquifier));
145     }
146 
147     internal::ResourceMetadataStorage::RecoveredCacheInfoMap
148         recovered_cache_info;
149     metadata_storage->RecoverCacheInfoFromTrashedResourceMap(
150         &recovered_cache_info);
151 
152     LOG(WARNING) << "DB could not be opened for some reasons. "
153                  << "Recovering cache files to " << dest_directory.value();
154     if (!cache->RecoverFilesFromCacheDirectory(dest_directory,
155                                                recovered_cache_info)) {
156       LOG(WARNING) << "Failed to recover cache files.";
157       return FILE_ERROR_FAILED;
158     }
159   }
160 
161   FileError error = resource_metadata->Initialize();
162   LOG_IF(WARNING, error != FILE_ERROR_OK)
163       << "Failed to initialize resource metadata. " << FileErrorToString(error);
164   return error;
165 }
166 
167 }  // namespace
168 
169 // Observes drive disable Preference's change.
170 class DriveIntegrationService::PreferenceWatcher {
171  public:
PreferenceWatcher(PrefService * pref_service)172   explicit PreferenceWatcher(PrefService* pref_service)
173       : pref_service_(pref_service),
174         integration_service_(NULL),
175         weak_ptr_factory_(this) {
176     DCHECK(pref_service);
177     pref_change_registrar_.Init(pref_service);
178     pref_change_registrar_.Add(
179         prefs::kDisableDrive,
180         base::Bind(&PreferenceWatcher::OnPreferenceChanged,
181                    weak_ptr_factory_.GetWeakPtr()));
182   }
183 
set_integration_service(DriveIntegrationService * integration_service)184   void set_integration_service(DriveIntegrationService* integration_service) {
185     integration_service_ = integration_service;
186   }
187 
188  private:
OnPreferenceChanged()189   void OnPreferenceChanged() {
190     DCHECK(integration_service_);
191     integration_service_->SetEnabled(
192         !pref_service_->GetBoolean(prefs::kDisableDrive));
193   }
194 
195   PrefService* pref_service_;
196   PrefChangeRegistrar pref_change_registrar_;
197   DriveIntegrationService* integration_service_;
198 
199   base::WeakPtrFactory<PreferenceWatcher> weak_ptr_factory_;
200   DISALLOW_COPY_AND_ASSIGN(PreferenceWatcher);
201 };
202 
DriveIntegrationService(Profile * profile,PreferenceWatcher * preference_watcher,DriveServiceInterface * test_drive_service,const base::FilePath & test_cache_root,FileSystemInterface * test_file_system)203 DriveIntegrationService::DriveIntegrationService(
204     Profile* profile,
205     PreferenceWatcher* preference_watcher,
206     DriveServiceInterface* test_drive_service,
207     const base::FilePath& test_cache_root,
208     FileSystemInterface* test_file_system)
209     : profile_(profile),
210       state_(NOT_INITIALIZED),
211       enabled_(false),
212       cache_root_directory_(!test_cache_root.empty() ?
213                             test_cache_root : util::GetCacheRootPath(profile)),
214       weak_ptr_factory_(this) {
215   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216 
217   base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
218   blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
219       blocking_pool->GetSequenceToken());
220 
221   ProfileOAuth2TokenService* oauth_service =
222       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
223 
224   if (test_drive_service) {
225     drive_service_.reset(test_drive_service);
226   } else if (util::IsDriveV2ApiEnabled()) {
227     drive_service_.reset(new DriveAPIService(
228         oauth_service,
229         g_browser_process->system_request_context(),
230         blocking_task_runner_.get(),
231         GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
232         GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction),
233         GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
234         GetDriveUserAgent()));
235   } else {
236     drive_service_.reset(new GDataWapiService(
237         oauth_service,
238         g_browser_process->system_request_context(),
239         blocking_task_runner_.get(),
240         GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
241         GURL(google_apis::GDataWapiUrlGenerator::kBaseDownloadUrlForProduction),
242         GetDriveUserAgent()));
243   }
244   scheduler_.reset(new JobScheduler(
245       profile_->GetPrefs(),
246       drive_service_.get(),
247       blocking_task_runner_.get()));
248   metadata_storage_.reset(new internal::ResourceMetadataStorage(
249       cache_root_directory_.Append(kMetadataDirectory),
250       blocking_task_runner_.get()));
251   cache_.reset(new internal::FileCache(
252       metadata_storage_.get(),
253       cache_root_directory_.Append(kCacheFileDirectory),
254       blocking_task_runner_.get(),
255       NULL /* free_disk_space_getter */));
256   drive_app_registry_.reset(new DriveAppRegistry(scheduler_.get()));
257 
258   resource_metadata_.reset(new internal::ResourceMetadata(
259       metadata_storage_.get(), blocking_task_runner_));
260 
261   file_system_.reset(
262       test_file_system ? test_file_system : new FileSystem(
263           profile_->GetPrefs(),
264           cache_.get(),
265           drive_service_.get(),
266           scheduler_.get(),
267           resource_metadata_.get(),
268           blocking_task_runner_.get(),
269           cache_root_directory_.Append(kTemporaryFileDirectory)));
270   download_handler_.reset(new DownloadHandler(file_system()));
271   debug_info_collector_.reset(
272       new DebugInfoCollector(file_system(), cache_.get(),
273                              blocking_task_runner_.get()));
274 
275   if (preference_watcher) {
276     preference_watcher_.reset(preference_watcher);
277     preference_watcher->set_integration_service(this);
278   }
279 
280   SetEnabled(drive::util::IsDriveEnabledForProfile(profile));
281 }
282 
~DriveIntegrationService()283 DriveIntegrationService::~DriveIntegrationService() {
284   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285 }
286 
Shutdown()287 void DriveIntegrationService::Shutdown() {
288   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289 
290   weak_ptr_factory_.InvalidateWeakPtrs();
291 
292   DriveNotificationManager* drive_notification_manager =
293       DriveNotificationManagerFactory::GetForBrowserContext(profile_);
294   if (drive_notification_manager)
295     drive_notification_manager->RemoveObserver(this);
296 
297   RemoveDriveMountPoint();
298   debug_info_collector_.reset();
299   download_handler_.reset();
300   file_system_.reset();
301   drive_app_registry_.reset();
302   scheduler_.reset();
303   drive_service_.reset();
304 }
305 
SetEnabled(bool enabled)306 void DriveIntegrationService::SetEnabled(bool enabled) {
307   // If Drive is being disabled, ensure the download destination preference to
308   // be out of Drive. Do this before "Do nothing if not changed." because we
309   // want to run the check for the first SetEnabled() called in the constructor,
310   // which may be a change from false to false.
311   if (!enabled)
312     AvoidDriveAsDownloadDirecotryPreference();
313 
314   // Do nothing if not changed.
315   if (enabled_ == enabled)
316     return;
317 
318   if (enabled) {
319     enabled_ = true;
320     switch (state_) {
321       case NOT_INITIALIZED:
322         // If the initialization is not yet done, trigger it.
323         Initialize();
324         return;
325 
326       case INITIALIZING:
327       case REMOUNTING:
328         // If the state is INITIALIZING or REMOUNTING, at the end of the
329         // process, it tries to mounting (with re-checking enabled state).
330         // Do nothing for now.
331         return;
332 
333       case INITIALIZED:
334         // The integration service is already initialized. Add the mount point.
335         AddDriveMountPoint();
336         return;
337     }
338     NOTREACHED();
339   } else {
340     RemoveDriveMountPoint();
341     enabled_ = false;
342   }
343 }
344 
IsMounted() const345 bool DriveIntegrationService::IsMounted() const {
346   // Look up the registered path, and just discard it.
347   // GetRegisteredPath() returns true if the path is available.
348   const base::FilePath& drive_mount_point = util::GetDriveMountPointPath();
349   base::FilePath unused;
350   return BrowserContext::GetMountPoints(profile_)->GetRegisteredPath(
351       drive_mount_point.BaseName().AsUTF8Unsafe(), &unused);
352 }
353 
AddObserver(DriveIntegrationServiceObserver * observer)354 void DriveIntegrationService::AddObserver(
355     DriveIntegrationServiceObserver* observer) {
356   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
357   observers_.AddObserver(observer);
358 }
359 
RemoveObserver(DriveIntegrationServiceObserver * observer)360 void DriveIntegrationService::RemoveObserver(
361     DriveIntegrationServiceObserver* observer) {
362   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
363   observers_.RemoveObserver(observer);
364 }
365 
OnNotificationReceived()366 void DriveIntegrationService::OnNotificationReceived() {
367   file_system_->CheckForUpdates();
368   drive_app_registry_->Update();
369 }
370 
OnPushNotificationEnabled(bool enabled)371 void DriveIntegrationService::OnPushNotificationEnabled(bool enabled) {
372   if (enabled)
373     drive_app_registry_->Update();
374 
375   const char* status = (enabled ? "enabled" : "disabled");
376   util::Log(logging::LOG_INFO, "Push notification is %s", status);
377 }
378 
ClearCacheAndRemountFileSystem(const base::Callback<void (bool)> & callback)379 void DriveIntegrationService::ClearCacheAndRemountFileSystem(
380     const base::Callback<void(bool)>& callback) {
381   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
382   DCHECK(!callback.is_null());
383 
384   if (state_ != INITIALIZED) {
385     callback.Run(false);
386     return;
387   }
388 
389   RemoveDriveMountPoint();
390 
391   state_ = REMOUNTING;
392   // Reloads the Drive app registry.
393   drive_app_registry_->Update();
394   // Reloading the file system clears resource metadata and cache.
395   file_system_->Reload(base::Bind(
396       &DriveIntegrationService::AddBackDriveMountPoint,
397       weak_ptr_factory_.GetWeakPtr(),
398       callback));
399 }
400 
AddBackDriveMountPoint(const base::Callback<void (bool)> & callback,FileError error)401 void DriveIntegrationService::AddBackDriveMountPoint(
402     const base::Callback<void(bool)>& callback,
403     FileError error) {
404   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
405   DCHECK(!callback.is_null());
406 
407   state_ = error == FILE_ERROR_OK ? INITIALIZED : NOT_INITIALIZED;
408 
409   if (error != FILE_ERROR_OK || !enabled_) {
410     // Failed to reload, or Drive was disabled during the reloading.
411     callback.Run(false);
412     return;
413   }
414 
415   AddDriveMountPoint();
416   callback.Run(true);
417 }
418 
AddDriveMountPoint()419 void DriveIntegrationService::AddDriveMountPoint() {
420   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
421   DCHECK_EQ(INITIALIZED, state_);
422   DCHECK(enabled_);
423 
424   const base::FilePath drive_mount_point = util::GetDriveMountPointPath();
425   fileapi::ExternalMountPoints* mount_points =
426       BrowserContext::GetMountPoints(profile_);
427   DCHECK(mount_points);
428 
429   bool success = mount_points->RegisterFileSystem(
430       drive_mount_point.BaseName().AsUTF8Unsafe(),
431       fileapi::kFileSystemTypeDrive,
432       fileapi::FileSystemMountOption(),
433       drive_mount_point);
434 
435   if (success) {
436     util::Log(logging::LOG_INFO, "Drive mount point is added");
437     FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_,
438                       OnFileSystemMounted());
439   }
440 }
441 
RemoveDriveMountPoint()442 void DriveIntegrationService::RemoveDriveMountPoint() {
443   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
444 
445   job_list()->CancelAllJobs();
446 
447   FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_,
448                     OnFileSystemBeingUnmounted());
449 
450   fileapi::ExternalMountPoints* mount_points =
451       BrowserContext::GetMountPoints(profile_);
452   DCHECK(mount_points);
453 
454   mount_points->RevokeFileSystem(
455       util::GetDriveMountPointPath().BaseName().AsUTF8Unsafe());
456   util::Log(logging::LOG_INFO, "Drive mount point is removed");
457 }
458 
Initialize()459 void DriveIntegrationService::Initialize() {
460   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
461   DCHECK_EQ(NOT_INITIALIZED, state_);
462   DCHECK(enabled_);
463 
464   state_ = INITIALIZING;
465 
466   base::PostTaskAndReplyWithResult(
467       blocking_task_runner_.get(),
468       FROM_HERE,
469       base::Bind(&InitializeMetadata,
470                  cache_root_directory_,
471                  metadata_storage_.get(),
472                  cache_.get(),
473                  resource_metadata_.get(),
474                  drive_service_->GetResourceIdCanonicalizer(),
475                  file_manager::util::GetDownloadsFolderForProfile(profile_)),
476       base::Bind(&DriveIntegrationService::InitializeAfterMetadataInitialized,
477                  weak_ptr_factory_.GetWeakPtr()));
478 }
479 
InitializeAfterMetadataInitialized(FileError error)480 void DriveIntegrationService::InitializeAfterMetadataInitialized(
481     FileError error) {
482   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
483   DCHECK_EQ(INITIALIZING, state_);
484 
485   drive_service_->Initialize(
486       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
487           GetPrimaryAccountId());
488 
489   if (error != FILE_ERROR_OK) {
490     LOG(WARNING) << "Failed to initialize: " << FileErrorToString(error);
491 
492     // Cannot used Drive. Set the download destination preference out of Drive.
493     AvoidDriveAsDownloadDirecotryPreference();
494 
495     // Back to NOT_INITIALIZED state. Then, re-running Initialize() should
496     // work if the error is recoverable manually (such as out of disk space).
497     state_ = NOT_INITIALIZED;
498     return;
499   }
500 
501   content::DownloadManager* download_manager =
502       g_browser_process->download_status_updater() ?
503       BrowserContext::GetDownloadManager(profile_) : NULL;
504   download_handler_->Initialize(
505       download_manager,
506       cache_root_directory_.Append(kTemporaryFileDirectory));
507 
508   // Register for Google Drive invalidation notifications.
509   DriveNotificationManager* drive_notification_manager =
510       DriveNotificationManagerFactory::GetForBrowserContext(profile_);
511   if (drive_notification_manager) {
512     drive_notification_manager->AddObserver(this);
513     const bool registered =
514         drive_notification_manager->push_notification_registered();
515     const char* status = (registered ? "registered" : "not registered");
516     util::Log(logging::LOG_INFO, "Push notification is %s", status);
517 
518     if (drive_notification_manager->push_notification_enabled())
519       drive_app_registry_->Update();
520   }
521 
522   state_ = INITIALIZED;
523 
524   // Mount only when the drive is enabled. Initialize is triggered by
525   // SetEnabled(true), but there is a change to disable it again during
526   // the metadata initialization, so we need to look this up again here.
527   if (enabled_)
528     AddDriveMountPoint();
529 }
530 
AvoidDriveAsDownloadDirecotryPreference()531 void DriveIntegrationService::AvoidDriveAsDownloadDirecotryPreference() {
532   PrefService* pref_service = profile_->GetPrefs();
533   if (util::IsUnderDriveMountPoint(
534           pref_service->GetFilePath(prefs::kDownloadDefaultDirectory))) {
535     pref_service->SetFilePath(
536         prefs::kDownloadDefaultDirectory,
537         file_manager::util::GetDownloadsFolderForProfile(profile_));
538   }
539 }
540 
541 //===================== DriveIntegrationServiceFactory =======================
542 
543 // static
GetForProfile(Profile * profile)544 DriveIntegrationService* DriveIntegrationServiceFactory::GetForProfile(
545     Profile* profile) {
546   return GetForProfileRegardlessOfStates(profile);
547 }
548 
549 // static
550 DriveIntegrationService*
GetForProfileRegardlessOfStates(Profile * profile)551 DriveIntegrationServiceFactory::GetForProfileRegardlessOfStates(
552     Profile* profile) {
553   return static_cast<DriveIntegrationService*>(
554       GetInstance()->GetServiceForBrowserContext(profile, true));
555 }
556 
557 // static
FindForProfile(Profile * profile)558 DriveIntegrationService* DriveIntegrationServiceFactory::FindForProfile(
559     Profile* profile) {
560   return FindForProfileRegardlessOfStates(profile);
561 }
562 
563 // static
564 DriveIntegrationService*
FindForProfileRegardlessOfStates(Profile * profile)565 DriveIntegrationServiceFactory::FindForProfileRegardlessOfStates(
566     Profile* profile) {
567   return static_cast<DriveIntegrationService*>(
568       GetInstance()->GetServiceForBrowserContext(profile, false));
569 }
570 
571 // static
GetInstance()572 DriveIntegrationServiceFactory* DriveIntegrationServiceFactory::GetInstance() {
573   return Singleton<DriveIntegrationServiceFactory>::get();
574 }
575 
576 // static
SetFactoryForTest(const FactoryCallback & factory_for_test)577 void DriveIntegrationServiceFactory::SetFactoryForTest(
578     const FactoryCallback& factory_for_test) {
579   GetInstance()->factory_for_test_ = factory_for_test;
580 }
581 
DriveIntegrationServiceFactory()582 DriveIntegrationServiceFactory::DriveIntegrationServiceFactory()
583     : BrowserContextKeyedServiceFactory(
584         "DriveIntegrationService",
585         BrowserContextDependencyManager::GetInstance()) {
586   DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
587   DependsOn(DriveNotificationManagerFactory::GetInstance());
588   DependsOn(DownloadServiceFactory::GetInstance());
589 }
590 
~DriveIntegrationServiceFactory()591 DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() {
592 }
593 
594 BrowserContextKeyedService*
BuildServiceInstanceFor(content::BrowserContext * context) const595 DriveIntegrationServiceFactory::BuildServiceInstanceFor(
596     content::BrowserContext* context) const {
597   Profile* profile = Profile::FromBrowserContext(context);
598 
599   DriveIntegrationService* service = NULL;
600   if (factory_for_test_.is_null()) {
601     DriveIntegrationService::PreferenceWatcher* preference_watcher = NULL;
602     if (chromeos::IsProfileAssociatedWithGaiaAccount(profile)) {
603       // Drive File System can be enabled.
604       preference_watcher =
605           new DriveIntegrationService::PreferenceWatcher(profile->GetPrefs());
606     }
607 
608     service = new DriveIntegrationService(profile, preference_watcher,
609                                           NULL, base::FilePath(), NULL);
610   } else {
611     service = factory_for_test_.Run(profile);
612   }
613 
614   return service;
615 }
616 
617 }  // namespace drive
618