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