// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/upgrade_detector_chromeos.h" #include "base/memory/singleton.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/update_engine_client.h" using chromeos::DBusThreadManager; using chromeos::UpdateEngineClient; namespace { // How long to wait (each cycle) before checking which severity level we should // be at. Once we reach the highest severity, the timer will stop. const int kNotifyCycleTimeMs = 20 * 60 * 1000; // 20 minutes. } // namespace class UpgradeDetectorChromeos::ChannelsRequester { public: typedef base::Callback OnChannelsReceivedCallback; ChannelsRequester() : weak_factory_(this) {} void RequestChannels(const OnChannelsReceivedCallback& callback) { UpdateEngineClient* client = DBusThreadManager::Get()->GetUpdateEngineClient(); callback_ = callback; client->GetChannel(true /* get_current_channel */, base::Bind(&ChannelsRequester::SetCurrentChannel, weak_factory_.GetWeakPtr())); client->GetChannel(false /* get_current_channel */, base::Bind(&ChannelsRequester::SetTargetChannel, weak_factory_.GetWeakPtr())); } private: void SetCurrentChannel(const std::string& current_channel) { DCHECK(!current_channel.empty()); current_channel_ = current_channel; TriggerCallbackIfReady(); } void SetTargetChannel(const std::string& target_channel) { DCHECK(!target_channel.empty()); target_channel_ = target_channel; TriggerCallbackIfReady(); } void TriggerCallbackIfReady() { if (current_channel_.empty() || target_channel_.empty()) return; if (!callback_.is_null()) callback_.Run(current_channel_, target_channel_); } std::string current_channel_; std::string target_channel_; OnChannelsReceivedCallback callback_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChannelsRequester); }; UpgradeDetectorChromeos::UpgradeDetectorChromeos() : initialized_(false), weak_factory_(this) { } UpgradeDetectorChromeos::~UpgradeDetectorChromeos() { } void UpgradeDetectorChromeos::Init() { DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this); initialized_ = true; } void UpgradeDetectorChromeos::Shutdown() { // Init() may not be called from tests. if (!initialized_) return; DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); } void UpgradeDetectorChromeos::UpdateStatusChanged( const UpdateEngineClient::Status& status) { if (status.status != UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) return; upgrade_detected_time_ = base::Time::Now(); channels_requester_.reset(new UpgradeDetectorChromeos::ChannelsRequester()); channels_requester_->RequestChannels( base::Bind(&UpgradeDetectorChromeos::OnChannelsReceived, weak_factory_.GetWeakPtr())); } void UpgradeDetectorChromeos::NotifyOnUpgrade() { base::TimeDelta delta = base::Time::Now() - upgrade_detected_time_; int64 time_passed = delta.InDays(); const int kSevereThreshold = 7; const int kHighThreshold = 4; const int kElevatedThreshold = 2; const int kLowThreshold = 0; // These if statements must be sorted (highest interval first). if (time_passed >= kSevereThreshold) { set_upgrade_notification_stage(UPGRADE_ANNOYANCE_SEVERE); // We can't get any higher, baby. upgrade_notification_timer_.Stop(); } else if (time_passed >= kHighThreshold) { set_upgrade_notification_stage(UPGRADE_ANNOYANCE_HIGH); } else if (time_passed >= kElevatedThreshold) { set_upgrade_notification_stage(UPGRADE_ANNOYANCE_ELEVATED); } else if (time_passed >= kLowThreshold) { set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW); } else { return; // Not ready to recommend upgrade. } NotifyUpgradeRecommended(); } void UpgradeDetectorChromeos::OnChannelsReceived( const std::string& current_channel, const std::string& target_channel) { // As current update engine status is UPDATE_STATUS_UPDATED_NEED_REBOOT // and target channel is more stable than current channel, powerwash // will be performed after reboot. set_is_factory_reset_required(UpdateEngineClient::IsTargetChannelMoreStable( current_channel, target_channel)); // ChromeOS shows upgrade arrow once the upgrade becomes available. NotifyOnUpgrade(); // Setup timer to to move along the upgrade advisory system. upgrade_notification_timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds(kNotifyCycleTimeMs), this, &UpgradeDetectorChromeos::NotifyOnUpgrade); } // static UpgradeDetectorChromeos* UpgradeDetectorChromeos::GetInstance() { return Singleton::get(); } // static UpgradeDetector* UpgradeDetector::GetInstance() { return UpgradeDetectorChromeos::GetInstance(); }