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/files/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 "storage/browser/fileapi/external_mount_points.h" 51 #include "ui/base/l10n/l10n_util.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 storage::ExternalMountPoints* const mount_points = 358 storage::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 storage::ExternalMountPoints* const mount_points = 438 storage::ExternalMountPoints::GetSystemInstance(); 439 DCHECK(mount_points); 440 441 bool success = 442 mount_points->RegisterFileSystem(mount_point_name_, 443 storage::kFileSystemTypeDrive, 444 storage::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 storage::ExternalMountPoints* const mount_points = 464 storage::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 656