Home | History | Annotate | Download | only in ash
      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/ui/ash/app_sync_ui_state.h"
      6 
      7 #include "base/prefs/pref_service.h"
      8 #include "chrome/browser/chrome_notification_types.h"
      9 #include "chrome/browser/extensions/extension_service.h"
     10 #include "chrome/browser/extensions/extension_system.h"
     11 #include "chrome/browser/extensions/pending_extension_manager.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/sync/profile_sync_service.h"
     14 #include "chrome/browser/sync/profile_sync_service_factory.h"
     15 #include "chrome/browser/ui/ash/app_sync_ui_state_factory.h"
     16 #include "chrome/browser/ui/ash/app_sync_ui_state_observer.h"
     17 #include "content/public/browser/notification_details.h"
     18 #include "content/public/browser/notification_service.h"
     19 #include "content/public/browser/notification_source.h"
     20 
     21 #if defined(OS_CHROMEOS)
     22 #include "chrome/browser/chromeos/login/user_manager.h"
     23 #endif
     24 
     25 namespace {
     26 
     27 // Max loading animation time in milliseconds.
     28 const int kMaxSyncingTimeMs = 60 * 1000;
     29 
     30 }  // namespace
     31 
     32 // static
     33 AppSyncUIState* AppSyncUIState::Get(Profile* profile) {
     34   return AppSyncUIStateFactory::GetForProfile(profile);
     35 }
     36 
     37 // static
     38 bool AppSyncUIState::ShouldObserveAppSyncForProfile(Profile* profile) {
     39 #if defined(OS_CHROMEOS)
     40   if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
     41     return false;
     42 
     43   if (!profile || profile->IsOffTheRecord())
     44     return false;
     45 
     46   if (!ProfileSyncServiceFactory::HasProfileSyncService(profile))
     47     return false;
     48 
     49   return profile->IsNewProfile();
     50 #else
     51   return false;
     52 #endif
     53 }
     54 
     55 AppSyncUIState::AppSyncUIState(Profile* profile)
     56     : profile_(profile),
     57       sync_service_(NULL),
     58       status_(STATUS_NORMAL) {
     59   StartObserving();
     60 }
     61 
     62 AppSyncUIState::~AppSyncUIState() {
     63   StopObserving();
     64 }
     65 
     66 void AppSyncUIState::AddObserver(AppSyncUIStateObserver* observer) {
     67   observers_.AddObserver(observer);
     68 }
     69 
     70 void AppSyncUIState::RemoveObserver(AppSyncUIStateObserver* observer) {
     71   observers_.RemoveObserver(observer);
     72 }
     73 
     74 void AppSyncUIState::StartObserving() {
     75   DCHECK(ShouldObserveAppSyncForProfile(profile_));
     76   DCHECK(!sync_service_);
     77 
     78   registrar_.Add(this,
     79                  chrome::NOTIFICATION_EXTENSION_LOADED,
     80                  content::Source<Profile>(profile_));
     81 
     82   sync_service_ = ProfileSyncServiceFactory::GetForProfile(profile_);
     83   CHECK(sync_service_);
     84   sync_service_->AddObserver(this);
     85 }
     86 
     87 void AppSyncUIState::StopObserving() {
     88   if (!sync_service_)
     89     return;
     90 
     91   registrar_.RemoveAll();
     92   sync_service_->RemoveObserver(this);
     93   sync_service_ = NULL;
     94   profile_ = NULL;
     95 }
     96 
     97 void AppSyncUIState::SetStatus(Status status) {
     98   if (status_ == status)
     99     return;
    100 
    101   status_ = status;
    102   switch (status_) {
    103     case STATUS_SYNCING:
    104       max_syncing_status_timer_.Start(
    105           FROM_HERE,
    106           base::TimeDelta::FromMilliseconds(kMaxSyncingTimeMs),
    107           this, &AppSyncUIState::OnMaxSyncingTimer);
    108       break;
    109     case STATUS_NORMAL:
    110     case STATUS_TIMED_OUT:
    111       max_syncing_status_timer_.Stop();
    112       StopObserving();
    113       break;
    114   }
    115 
    116   FOR_EACH_OBSERVER(AppSyncUIStateObserver,
    117                     observers_,
    118                     OnAppSyncUIStatusChanged());
    119 }
    120 
    121 void AppSyncUIState::CheckAppSync() {
    122   if (!sync_service_ || !sync_service_->HasSyncSetupCompleted())
    123     return;
    124 
    125   const bool synced = sync_service_->ShouldPushChanges();
    126   const bool has_pending_extension =
    127       extensions::ExtensionSystem::Get(profile_)->extension_service()->
    128           pending_extension_manager()->HasPendingExtensionFromSync();
    129 
    130   if (synced && !has_pending_extension)
    131     SetStatus(STATUS_NORMAL);
    132   else
    133     SetStatus(STATUS_SYNCING);
    134 }
    135 
    136 void AppSyncUIState::OnMaxSyncingTimer() {
    137   SetStatus(STATUS_TIMED_OUT);
    138 }
    139 
    140 void AppSyncUIState::Observe(int type,
    141                              const content::NotificationSource& source,
    142                              const content::NotificationDetails& details) {
    143   DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_LOADED, type);
    144   CheckAppSync();
    145 }
    146 
    147 void AppSyncUIState::OnStateChanged() {
    148   DCHECK(sync_service_);
    149   CheckAppSync();
    150 }
    151