Home | History | Annotate | Download | only in drive
      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
     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|.
     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:
    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 
    184   void set_integration_service(DriveIntegrationService* integration_service) {
    185     integration_service_ = integration_service;
    186   }
    187 
    188  private:
    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 
    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 
    283 DriveIntegrationService::~DriveIntegrationService() {
    284   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    285 }
    286 
    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 
    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 
    345 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 
    354 void DriveIntegrationService::AddObserver(
    355     DriveIntegrationServiceObserver* observer) {
    356   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    357   observers_.AddObserver(observer);
    358 }
    359 
    360 void DriveIntegrationService::RemoveObserver(
    361     DriveIntegrationServiceObserver* observer) {
    362   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    363   observers_.RemoveObserver(observer);
    364 }
    365 
    366 void DriveIntegrationService::OnNotificationReceived() {
    367   file_system_->CheckForUpdates();
    368   drive_app_registry_->Update();
    369 }
    370 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    544 DriveIntegrationService* DriveIntegrationServiceFactory::GetForProfile(
    545     Profile* profile) {
    546   return GetForProfileRegardlessOfStates(profile);
    547 }
    548 
    549 // static
    550 DriveIntegrationService*
    551 DriveIntegrationServiceFactory::GetForProfileRegardlessOfStates(
    552     Profile* profile) {
    553   return static_cast<DriveIntegrationService*>(
    554       GetInstance()->GetServiceForBrowserContext(profile, true));
    555 }
    556 
    557 // static
    558 DriveIntegrationService* DriveIntegrationServiceFactory::FindForProfile(
    559     Profile* profile) {
    560   return FindForProfileRegardlessOfStates(profile);
    561 }
    562 
    563 // static
    564 DriveIntegrationService*
    565 DriveIntegrationServiceFactory::FindForProfileRegardlessOfStates(
    566     Profile* profile) {
    567   return static_cast<DriveIntegrationService*>(
    568       GetInstance()->GetServiceForBrowserContext(profile, false));
    569 }
    570 
    571 // static
    572 DriveIntegrationServiceFactory* DriveIntegrationServiceFactory::GetInstance() {
    573   return Singleton<DriveIntegrationServiceFactory>::get();
    574 }
    575 
    576 // static
    577 void DriveIntegrationServiceFactory::SetFactoryForTest(
    578     const FactoryCallback& factory_for_test) {
    579   GetInstance()->factory_for_test_ = factory_for_test;
    580 }
    581 
    582 DriveIntegrationServiceFactory::DriveIntegrationServiceFactory()
    583     : BrowserContextKeyedServiceFactory(
    584         "DriveIntegrationService",
    585         BrowserContextDependencyManager::GetInstance()) {
    586   DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
    587   DependsOn(DriveNotificationManagerFactory::GetInstance());
    588   DependsOn(DownloadServiceFactory::GetInstance());
    589 }
    590 
    591 DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() {
    592 }
    593 
    594 BrowserContextKeyedService*
    595 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