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
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 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 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:
PreferenceWatcher(PrefService * pref_service)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
set_integration_service(DriveIntegrationService * integration_service)192 void set_integration_service(DriveIntegrationService* integration_service) {
193 integration_service_ = integration_service;
194 }
195
196 private:
OnPreferenceChanged()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
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)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
~DriveIntegrationService()288 DriveIntegrationService::~DriveIntegrationService() {
289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
290 }
291
Shutdown()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
SetEnabled(bool enabled)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
IsMounted() const350 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
AddObserver(DriveIntegrationServiceObserver * observer)363 void DriveIntegrationService::AddObserver(
364 DriveIntegrationServiceObserver* observer) {
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
366 observers_.AddObserver(observer);
367 }
368
RemoveObserver(DriveIntegrationServiceObserver * observer)369 void DriveIntegrationService::RemoveObserver(
370 DriveIntegrationServiceObserver* observer) {
371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372 observers_.RemoveObserver(observer);
373 }
374
OnNotificationReceived()375 void DriveIntegrationService::OnNotificationReceived() {
376 file_system_->CheckForUpdates();
377 drive_app_registry_->Update();
378 }
379
OnPushNotificationEnabled(bool enabled)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
ClearCacheAndRemountFileSystem(const base::Callback<void (bool)> & callback)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
AddBackDriveMountPoint(const base::Callback<void (bool)> & callback,FileError error)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
AddDriveMountPoint()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
RemoveDriveMountPoint()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
Initialize()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
InitializeAfterMetadataInitialized(FileError error)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
AvoidDriveAsDownloadDirecotryPreference()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
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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
ScopedFactoryForTest(FactoryCallback * factory_for_test)587 DriveIntegrationServiceFactory::ScopedFactoryForTest::ScopedFactoryForTest(
588 FactoryCallback* factory_for_test) {
589 factory_for_test_ = factory_for_test;
590 }
591
~ScopedFactoryForTest()592 DriveIntegrationServiceFactory::ScopedFactoryForTest::~ScopedFactoryForTest() {
593 factory_for_test_ = NULL;
594 }
595
596 // static
GetForProfile(Profile * profile)597 DriveIntegrationService* DriveIntegrationServiceFactory::GetForProfile(
598 Profile* profile) {
599 return static_cast<DriveIntegrationService*>(
600 GetInstance()->GetServiceForBrowserContext(profile, true));
601 }
602
603 // static
FindForProfile(Profile * profile)604 DriveIntegrationService* DriveIntegrationServiceFactory::FindForProfile(
605 Profile* profile) {
606 return static_cast<DriveIntegrationService*>(
607 GetInstance()->GetServiceForBrowserContext(profile, false));
608 }
609
610 // static
GetInstance()611 DriveIntegrationServiceFactory* DriveIntegrationServiceFactory::GetInstance() {
612 return Singleton<DriveIntegrationServiceFactory>::get();
613 }
614
DriveIntegrationServiceFactory()615 DriveIntegrationServiceFactory::DriveIntegrationServiceFactory()
616 : BrowserContextKeyedServiceFactory(
617 "DriveIntegrationService",
618 BrowserContextDependencyManager::GetInstance()) {
619 DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
620 DependsOn(DriveNotificationManagerFactory::GetInstance());
621 DependsOn(DownloadServiceFactory::GetInstance());
622 }
623
~DriveIntegrationServiceFactory()624 DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() {
625 }
626
GetBrowserContextToUse(content::BrowserContext * context) const627 content::BrowserContext* DriveIntegrationServiceFactory::GetBrowserContextToUse(
628 content::BrowserContext* context) const {
629 return chrome::GetBrowserContextRedirectedInIncognito(context);
630 }
631
BuildServiceInstanceFor(content::BrowserContext * context) const632 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