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