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