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