Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / drive_integration_service.cc
blobeb05e35e180c1d988216ebad395d6917309c55c5
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.
5 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
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 "storage/browser/fileapi/external_mount_points.h"
50 #include "ui/base/l10n/l10n_util.h"
52 using content::BrowserContext;
53 using content::BrowserThread;
55 namespace drive {
56 namespace {
58 // Name of the directory used to store metadata.
59 const base::FilePath::CharType kMetadataDirectory[] = FILE_PATH_LITERAL("meta");
61 // Name of the directory used to store cached files.
62 const base::FilePath::CharType kCacheFileDirectory[] =
63 FILE_PATH_LITERAL("files");
65 // Name of the directory used to store temporary files.
66 const base::FilePath::CharType kTemporaryFileDirectory[] =
67 FILE_PATH_LITERAL("tmp");
69 // Returns a user agent string used for communicating with the Drive backend,
70 // both WAPI and Drive API. The user agent looks like:
72 // chromedrive-<VERSION> chrome-cc/none (<OS_CPU_INFO>)
73 // chromedrive-24.0.1274.0 chrome-cc/none (CrOS x86_64 0.4.0)
75 // TODO(satorux): Move this function to somewhere else: crbug.com/151605
76 std::string GetDriveUserAgent() {
77 const char kDriveClientName[] = "chromedrive";
79 chrome::VersionInfo version_info;
80 const std::string version = version_info.Version();
82 // This part is <client_name>/<version>.
83 const char kLibraryInfo[] = "chrome-cc/none";
85 const std::string os_cpu_info = content::BuildOSCpuInfo();
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());
96 // Initializes FileCache and ResourceMetadata.
97 // Must be run on the same task runner used by |cache| and |resource_metadata|.
98 FileError InitializeMetadata(
99 const base::FilePath& cache_root_directory,
100 internal::ResourceMetadataStorage* metadata_storage,
101 internal::FileCache* cache,
102 internal::ResourceMetadata* resource_metadata,
103 const base::FilePath& downloads_directory) {
104 // Files in temporary directory need not persist across sessions. Clean up
105 // the directory content while initialization.
106 base::DeleteFile(cache_root_directory.Append(kTemporaryFileDirectory),
107 true); // recursive
108 if (!base::CreateDirectory(cache_root_directory.Append(
109 kMetadataDirectory)) ||
110 !base::CreateDirectory(cache_root_directory.Append(
111 kCacheFileDirectory)) ||
112 !base::CreateDirectory(cache_root_directory.Append(
113 kTemporaryFileDirectory))) {
114 LOG(WARNING) << "Failed to create directories.";
115 return FILE_ERROR_FAILED;
118 // Change permissions of cache file directory to u+rwx,og+x (711) in order to
119 // allow archive files in that directory to be mounted by cros-disks.
120 base::SetPosixFilePermissions(
121 cache_root_directory.Append(kCacheFileDirectory),
122 base::FILE_PERMISSION_USER_MASK |
123 base::FILE_PERMISSION_EXECUTE_BY_GROUP |
124 base::FILE_PERMISSION_EXECUTE_BY_OTHERS);
126 internal::ResourceMetadataStorage::UpgradeOldDB(
127 metadata_storage->directory_path());
129 if (!metadata_storage->Initialize()) {
130 LOG(WARNING) << "Failed to initialize the metadata storage.";
131 return FILE_ERROR_FAILED;
134 if (!cache->Initialize()) {
135 LOG(WARNING) << "Failed to initialize the cache.";
136 return FILE_ERROR_FAILED;
139 if (metadata_storage->cache_file_scan_is_needed()) {
140 // Generate unique directory name.
141 const std::string& dest_directory_name = l10n_util::GetStringUTF8(
142 IDS_FILE_BROWSER_RECOVERED_FILES_FROM_GOOGLE_DRIVE_DIRECTORY_NAME);
143 base::FilePath dest_directory = downloads_directory.Append(
144 base::FilePath::FromUTF8Unsafe(dest_directory_name));
145 for (int uniquifier = 1; base::PathExists(dest_directory); ++uniquifier) {
146 dest_directory = downloads_directory.Append(
147 base::FilePath::FromUTF8Unsafe(dest_directory_name))
148 .InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", uniquifier));
151 internal::ResourceMetadataStorage::RecoveredCacheInfoMap
152 recovered_cache_info;
153 metadata_storage->RecoverCacheInfoFromTrashedResourceMap(
154 &recovered_cache_info);
156 LOG_IF(WARNING, !recovered_cache_info.empty())
157 << "DB could not be opened for some reasons. "
158 << "Recovering cache files to " << dest_directory.value();
159 if (!cache->RecoverFilesFromCacheDirectory(dest_directory,
160 recovered_cache_info)) {
161 LOG(WARNING) << "Failed to recover cache files.";
162 return FILE_ERROR_FAILED;
166 FileError error = resource_metadata->Initialize();
167 LOG_IF(WARNING, error != FILE_ERROR_OK)
168 << "Failed to initialize resource metadata. " << FileErrorToString(error);
169 return error;
172 } // namespace
174 // Observes drive disable Preference's change.
175 class DriveIntegrationService::PreferenceWatcher {
176 public:
177 explicit PreferenceWatcher(PrefService* pref_service)
178 : pref_service_(pref_service),
179 integration_service_(NULL),
180 weak_ptr_factory_(this) {
181 DCHECK(pref_service);
182 pref_change_registrar_.Init(pref_service);
183 pref_change_registrar_.Add(
184 prefs::kDisableDrive,
185 base::Bind(&PreferenceWatcher::OnPreferenceChanged,
186 weak_ptr_factory_.GetWeakPtr()));
189 void set_integration_service(DriveIntegrationService* integration_service) {
190 integration_service_ = integration_service;
193 private:
194 void OnPreferenceChanged() {
195 DCHECK(integration_service_);
196 integration_service_->SetEnabled(
197 !pref_service_->GetBoolean(prefs::kDisableDrive));
200 PrefService* pref_service_;
201 PrefChangeRegistrar pref_change_registrar_;
202 DriveIntegrationService* integration_service_;
204 base::WeakPtrFactory<PreferenceWatcher> weak_ptr_factory_;
205 DISALLOW_COPY_AND_ASSIGN(PreferenceWatcher);
208 DriveIntegrationService::DriveIntegrationService(
209 Profile* profile,
210 PreferenceWatcher* preference_watcher,
211 DriveServiceInterface* test_drive_service,
212 const std::string& test_mount_point_name,
213 const base::FilePath& test_cache_root,
214 FileSystemInterface* test_file_system)
215 : profile_(profile),
216 state_(NOT_INITIALIZED),
217 enabled_(false),
218 mount_point_name_(test_mount_point_name),
219 cache_root_directory_(!test_cache_root.empty() ?
220 test_cache_root : util::GetCacheRootPath(profile)),
221 weak_ptr_factory_(this) {
222 DCHECK_CURRENTLY_ON(BrowserThread::UI);
223 DCHECK(profile && !profile->IsOffTheRecord());
225 logger_.reset(new EventLogger);
226 base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
227 blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
228 blocking_pool->GetSequenceToken());
230 ProfileOAuth2TokenService* oauth_service =
231 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
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 GetDriveUserAgent()));
244 scheduler_.reset(new JobScheduler(
245 profile_->GetPrefs(),
246 logger_.get(),
247 drive_service_.get(),
248 blocking_task_runner_.get()));
249 metadata_storage_.reset(new internal::ResourceMetadataStorage(
250 cache_root_directory_.Append(kMetadataDirectory),
251 blocking_task_runner_.get()));
252 cache_.reset(new internal::FileCache(
253 metadata_storage_.get(),
254 cache_root_directory_.Append(kCacheFileDirectory),
255 blocking_task_runner_.get(),
256 NULL /* free_disk_space_getter */));
257 drive_app_registry_.reset(new DriveAppRegistry(drive_service_.get()));
259 resource_metadata_.reset(new internal::ResourceMetadata(
260 metadata_storage_.get(), cache_.get(), blocking_task_runner_));
262 file_system_.reset(
263 test_file_system ? test_file_system : new FileSystem(
264 profile_->GetPrefs(),
265 logger_.get(),
266 cache_.get(),
267 scheduler_.get(),
268 resource_metadata_.get(),
269 blocking_task_runner_.get(),
270 cache_root_directory_.Append(kTemporaryFileDirectory)));
271 download_handler_.reset(new DownloadHandler(file_system()));
272 debug_info_collector_.reset(new DebugInfoCollector(
273 resource_metadata_.get(), file_system(), blocking_task_runner_.get()));
275 if (preference_watcher) {
276 preference_watcher_.reset(preference_watcher);
277 preference_watcher->set_integration_service(this);
280 SetEnabled(drive::util::IsDriveEnabledForProfile(profile));
283 DriveIntegrationService::~DriveIntegrationService() {
284 DCHECK_CURRENTLY_ON(BrowserThread::UI);
287 void DriveIntegrationService::Shutdown() {
288 DCHECK_CURRENTLY_ON(BrowserThread::UI);
290 weak_ptr_factory_.InvalidateWeakPtrs();
292 DriveNotificationManager* drive_notification_manager =
293 DriveNotificationManagerFactory::FindForBrowserContext(profile_);
294 if (drive_notification_manager)
295 drive_notification_manager->RemoveObserver(this);
297 RemoveDriveMountPoint();
298 debug_info_collector_.reset();
299 download_handler_.reset();
300 file_system_.reset();
301 drive_app_registry_.reset();
302 scheduler_.reset();
303 drive_service_.reset();
306 void DriveIntegrationService::SetEnabled(bool enabled) {
307 // If Drive is being disabled, ensure the download destination preference to
308 // be out of Drive. Do this before "Do nothing if not changed." because we
309 // want to run the check for the first SetEnabled() called in the constructor,
310 // which may be a change from false to false.
311 if (!enabled)
312 AvoidDriveAsDownloadDirecotryPreference();
314 // Do nothing if not changed.
315 if (enabled_ == enabled)
316 return;
318 if (enabled) {
319 enabled_ = true;
320 switch (state_) {
321 case NOT_INITIALIZED:
322 // If the initialization is not yet done, trigger it.
323 Initialize();
324 return;
326 case INITIALIZING:
327 case REMOUNTING:
328 // If the state is INITIALIZING or REMOUNTING, at the end of the
329 // process, it tries to mounting (with re-checking enabled state).
330 // Do nothing for now.
331 return;
333 case INITIALIZED:
334 // The integration service is already initialized. Add the mount point.
335 AddDriveMountPoint();
336 return;
338 NOTREACHED();
339 } else {
340 RemoveDriveMountPoint();
341 enabled_ = false;
345 bool DriveIntegrationService::IsMounted() const {
346 if (mount_point_name_.empty())
347 return false;
349 // Look up the registered path, and just discard it.
350 // GetRegisteredPath() returns true if the path is available.
351 base::FilePath unused;
352 storage::ExternalMountPoints* const mount_points =
353 storage::ExternalMountPoints::GetSystemInstance();
354 DCHECK(mount_points);
355 return mount_points->GetRegisteredPath(mount_point_name_, &unused);
358 void DriveIntegrationService::AddObserver(
359 DriveIntegrationServiceObserver* observer) {
360 DCHECK_CURRENTLY_ON(BrowserThread::UI);
361 observers_.AddObserver(observer);
364 void DriveIntegrationService::RemoveObserver(
365 DriveIntegrationServiceObserver* observer) {
366 DCHECK_CURRENTLY_ON(BrowserThread::UI);
367 observers_.RemoveObserver(observer);
370 void DriveIntegrationService::OnNotificationReceived() {
371 file_system_->CheckForUpdates();
372 drive_app_registry_->Update();
375 void DriveIntegrationService::OnPushNotificationEnabled(bool enabled) {
376 if (enabled)
377 drive_app_registry_->Update();
379 const char* status = (enabled ? "enabled" : "disabled");
380 logger_->Log(logging::LOG_INFO, "Push notification is %s", status);
383 void DriveIntegrationService::ClearCacheAndRemountFileSystem(
384 const base::Callback<void(bool)>& callback) {
385 DCHECK_CURRENTLY_ON(BrowserThread::UI);
386 DCHECK(!callback.is_null());
388 if (state_ != INITIALIZED) {
389 callback.Run(false);
390 return;
393 RemoveDriveMountPoint();
395 state_ = REMOUNTING;
396 // Reloads the Drive app registry.
397 drive_app_registry_->Update();
398 // Resetting the file system clears resource metadata and cache.
399 file_system_->Reset(base::Bind(
400 &DriveIntegrationService::AddBackDriveMountPoint,
401 weak_ptr_factory_.GetWeakPtr(),
402 callback));
405 void DriveIntegrationService::AddBackDriveMountPoint(
406 const base::Callback<void(bool)>& callback,
407 FileError error) {
408 DCHECK_CURRENTLY_ON(BrowserThread::UI);
409 DCHECK(!callback.is_null());
411 state_ = error == FILE_ERROR_OK ? INITIALIZED : NOT_INITIALIZED;
413 if (error != FILE_ERROR_OK || !enabled_) {
414 // Failed to reset, or Drive was disabled during the reset.
415 callback.Run(false);
416 return;
419 AddDriveMountPoint();
420 callback.Run(true);
423 void DriveIntegrationService::AddDriveMountPoint() {
424 DCHECK_CURRENTLY_ON(BrowserThread::UI);
425 DCHECK_EQ(INITIALIZED, state_);
426 DCHECK(enabled_);
428 const base::FilePath& drive_mount_point =
429 util::GetDriveMountPointPath(profile_);
430 if (mount_point_name_.empty())
431 mount_point_name_ = drive_mount_point.BaseName().AsUTF8Unsafe();
432 storage::ExternalMountPoints* const mount_points =
433 storage::ExternalMountPoints::GetSystemInstance();
434 DCHECK(mount_points);
436 bool success =
437 mount_points->RegisterFileSystem(mount_point_name_,
438 storage::kFileSystemTypeDrive,
439 storage::FileSystemMountOption(),
440 drive_mount_point);
442 if (success) {
443 logger_->Log(logging::LOG_INFO, "Drive mount point is added");
444 FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_,
445 OnFileSystemMounted());
449 void DriveIntegrationService::RemoveDriveMountPoint() {
450 DCHECK_CURRENTLY_ON(BrowserThread::UI);
452 if (!mount_point_name_.empty()) {
453 job_list()->CancelAllJobs();
455 FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_,
456 OnFileSystemBeingUnmounted());
458 storage::ExternalMountPoints* const mount_points =
459 storage::ExternalMountPoints::GetSystemInstance();
460 DCHECK(mount_points);
462 mount_points->RevokeFileSystem(mount_point_name_);
463 logger_->Log(logging::LOG_INFO, "Drive mount point is removed");
467 void DriveIntegrationService::Initialize() {
468 DCHECK_CURRENTLY_ON(BrowserThread::UI);
469 DCHECK_EQ(NOT_INITIALIZED, state_);
470 DCHECK(enabled_);
472 state_ = INITIALIZING;
474 base::PostTaskAndReplyWithResult(
475 blocking_task_runner_.get(),
476 FROM_HERE,
477 base::Bind(&InitializeMetadata,
478 cache_root_directory_,
479 metadata_storage_.get(),
480 cache_.get(),
481 resource_metadata_.get(),
482 file_manager::util::GetDownloadsFolderForProfile(profile_)),
483 base::Bind(&DriveIntegrationService::InitializeAfterMetadataInitialized,
484 weak_ptr_factory_.GetWeakPtr()));
487 void DriveIntegrationService::InitializeAfterMetadataInitialized(
488 FileError error) {
489 DCHECK_CURRENTLY_ON(BrowserThread::UI);
490 DCHECK_EQ(INITIALIZING, state_);
492 SigninManagerBase* signin_manager =
493 SigninManagerFactory::GetForProfile(profile_);
494 drive_service_->Initialize(signin_manager->GetAuthenticatedAccountId());
496 if (error != FILE_ERROR_OK) {
497 LOG(WARNING) << "Failed to initialize: " << FileErrorToString(error);
499 // Cannot used Drive. Set the download destination preference out of Drive.
500 AvoidDriveAsDownloadDirecotryPreference();
502 // Back to NOT_INITIALIZED state. Then, re-running Initialize() should
503 // work if the error is recoverable manually (such as out of disk space).
504 state_ = NOT_INITIALIZED;
505 return;
508 // Initialize Download Handler for hooking downloads to the Drive folder.
509 content::DownloadManager* download_manager =
510 g_browser_process->download_status_updater() ?
511 BrowserContext::GetDownloadManager(profile_) : NULL;
512 download_handler_->Initialize(
513 download_manager,
514 cache_root_directory_.Append(kTemporaryFileDirectory));
516 // Install the handler also to incognito profile.
517 if (g_browser_process->download_status_updater()) {
518 if (profile_->HasOffTheRecordProfile()) {
519 download_handler_->ObserveIncognitoDownloadManager(
520 BrowserContext::GetDownloadManager(
521 profile_->GetOffTheRecordProfile()));
523 profile_notification_registrar_.reset(new content::NotificationRegistrar);
524 profile_notification_registrar_->Add(
525 this,
526 chrome::NOTIFICATION_PROFILE_CREATED,
527 content::NotificationService::AllSources());
530 // Register for Google Drive invalidation notifications.
531 DriveNotificationManager* drive_notification_manager =
532 DriveNotificationManagerFactory::GetForBrowserContext(profile_);
533 if (drive_notification_manager) {
534 drive_notification_manager->AddObserver(this);
535 const bool registered =
536 drive_notification_manager->push_notification_registered();
537 const char* status = (registered ? "registered" : "not registered");
538 logger_->Log(logging::LOG_INFO, "Push notification is %s", status);
540 if (drive_notification_manager->push_notification_enabled())
541 drive_app_registry_->Update();
544 state_ = INITIALIZED;
546 // Mount only when the drive is enabled. Initialize is triggered by
547 // SetEnabled(true), but there is a change to disable it again during
548 // the metadata initialization, so we need to look this up again here.
549 if (enabled_)
550 AddDriveMountPoint();
553 void DriveIntegrationService::AvoidDriveAsDownloadDirecotryPreference() {
554 PrefService* pref_service = profile_->GetPrefs();
555 if (util::IsUnderDriveMountPoint(
556 pref_service->GetFilePath(prefs::kDownloadDefaultDirectory))) {
557 pref_service->SetFilePath(
558 prefs::kDownloadDefaultDirectory,
559 file_manager::util::GetDownloadsFolderForProfile(profile_));
563 void DriveIntegrationService::Observe(
564 int type,
565 const content::NotificationSource& source,
566 const content::NotificationDetails& details) {
567 if (type == chrome::NOTIFICATION_PROFILE_CREATED) {
568 Profile* created_profile = content::Source<Profile>(source).ptr();
569 if (created_profile->IsOffTheRecord() &&
570 created_profile->IsSameProfile(profile_)) {
571 download_handler_->ObserveIncognitoDownloadManager(
572 BrowserContext::GetDownloadManager(created_profile));
577 //===================== DriveIntegrationServiceFactory =======================
579 DriveIntegrationServiceFactory::FactoryCallback*
580 DriveIntegrationServiceFactory::factory_for_test_ = NULL;
582 DriveIntegrationServiceFactory::ScopedFactoryForTest::ScopedFactoryForTest(
583 FactoryCallback* factory_for_test) {
584 factory_for_test_ = factory_for_test;
587 DriveIntegrationServiceFactory::ScopedFactoryForTest::~ScopedFactoryForTest() {
588 factory_for_test_ = NULL;
591 // static
592 DriveIntegrationService* DriveIntegrationServiceFactory::GetForProfile(
593 Profile* profile) {
594 return static_cast<DriveIntegrationService*>(
595 GetInstance()->GetServiceForBrowserContext(profile, true));
598 // static
599 DriveIntegrationService* DriveIntegrationServiceFactory::FindForProfile(
600 Profile* profile) {
601 return static_cast<DriveIntegrationService*>(
602 GetInstance()->GetServiceForBrowserContext(profile, false));
605 // static
606 DriveIntegrationServiceFactory* DriveIntegrationServiceFactory::GetInstance() {
607 return Singleton<DriveIntegrationServiceFactory>::get();
610 DriveIntegrationServiceFactory::DriveIntegrationServiceFactory()
611 : BrowserContextKeyedServiceFactory(
612 "DriveIntegrationService",
613 BrowserContextDependencyManager::GetInstance()) {
614 DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
615 DependsOn(DriveNotificationManagerFactory::GetInstance());
616 DependsOn(DownloadServiceFactory::GetInstance());
619 DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() {
622 content::BrowserContext* DriveIntegrationServiceFactory::GetBrowserContextToUse(
623 content::BrowserContext* context) const {
624 return chrome::GetBrowserContextRedirectedInIncognito(context);
627 KeyedService* DriveIntegrationServiceFactory::BuildServiceInstanceFor(
628 content::BrowserContext* context) const {
629 Profile* profile = Profile::FromBrowserContext(context);
631 DriveIntegrationService* service = NULL;
632 if (!factory_for_test_) {
633 DriveIntegrationService::PreferenceWatcher* preference_watcher = NULL;
634 if (chromeos::IsProfileAssociatedWithGaiaAccount(profile)) {
635 // Drive File System can be enabled.
636 preference_watcher =
637 new DriveIntegrationService::PreferenceWatcher(profile->GetPrefs());
640 service = new DriveIntegrationService(
641 profile, preference_watcher,
642 NULL, std::string(), base::FilePath(), NULL);
643 } else {
644 service = factory_for_test_->Run(profile);
647 return service;
650 } // namespace drive