// 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/extensions/updater/extension_updater.h"

#include <algorithm>
#include <set>
#include <vector>

#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/module/module.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/browser/extensions/updater/extension_downloader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "crypto/sha2.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest.h"

using base::RandDouble;
using base::RandInt;
using base::Time;
using base::TimeDelta;
using content::BrowserThread;

typedef extensions::ExtensionDownloaderDelegate::Error Error;
typedef extensions::ExtensionDownloaderDelegate::PingResult PingResult;

namespace {

// Wait at least 5 minutes after browser startup before we do any checks. If you
// change this value, make sure to update comments where it is used.
const int kStartupWaitSeconds = 60 * 5;

// For sanity checking on update frequency - enforced in release mode only.
#if defined(NDEBUG)
const int kMinUpdateFrequencySeconds = 30;
#endif
const int kMaxUpdateFrequencySeconds = 60 * 60 * 24 * 7;  // 7 days

// Require at least 5 seconds between consecutive non-succesful extension update
// checks.
const int kMinUpdateThrottleTime = 5;

// When we've computed a days value, we want to make sure we don't send a
// negative value (due to the system clock being set backwards, etc.), since -1
// is a special sentinel value that means "never pinged", and other negative
// values don't make sense.
int SanitizeDays(int days) {
  if (days < 0)
    return 0;
  return days;
}

// Calculates the value to use for the ping days parameter.
int CalculatePingDays(const Time& last_ping_day) {
  int days = extensions::ManifestFetchData::kNeverPinged;
  if (!last_ping_day.is_null()) {
    days = SanitizeDays((Time::Now() - last_ping_day).InDays());
  }
  return days;
}

int CalculateActivePingDays(const Time& last_active_ping_day,
                            bool hasActiveBit) {
  if (!hasActiveBit)
    return 0;
  if (last_active_ping_day.is_null())
    return extensions::ManifestFetchData::kNeverPinged;
  return SanitizeDays((Time::Now() - last_active_ping_day).InDays());
}

}  // namespace

namespace extensions {

ExtensionUpdater::CheckParams::CheckParams()
    : install_immediately(false) {}

ExtensionUpdater::CheckParams::~CheckParams() {}

ExtensionUpdater::FetchedCRXFile::FetchedCRXFile(
    const std::string& i,
    const base::FilePath& p,
    bool file_ownership_passed,
    const std::set<int>& request_ids)
    : extension_id(i),
      path(p),
      file_ownership_passed(file_ownership_passed),
      request_ids(request_ids) {}

ExtensionUpdater::FetchedCRXFile::FetchedCRXFile()
    : path(), file_ownership_passed(true) {}

ExtensionUpdater::FetchedCRXFile::~FetchedCRXFile() {}

ExtensionUpdater::InProgressCheck::InProgressCheck()
    : install_immediately(false) {}

ExtensionUpdater::InProgressCheck::~InProgressCheck() {}

struct ExtensionUpdater::ThrottleInfo {
  ThrottleInfo()
      : in_progress(true),
        throttle_delay(kMinUpdateThrottleTime),
        check_start(Time::Now()) {}

  bool in_progress;
  int throttle_delay;
  Time check_start;
};

ExtensionUpdater::ExtensionUpdater(ExtensionServiceInterface* service,
                                   ExtensionPrefs* extension_prefs,
                                   PrefService* prefs,
                                   Profile* profile,
                                   int frequency_seconds,
                                   ExtensionCache* cache)
    : alive_(false),
      weak_ptr_factory_(this),
      service_(service), frequency_seconds_(frequency_seconds),
      will_check_soon_(false), extension_prefs_(extension_prefs),
      prefs_(prefs), profile_(profile),
      next_request_id_(0),
      crx_install_is_running_(false),
      extension_cache_(cache) {
  DCHECK_GE(frequency_seconds_, 5);
  DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds);
#if defined(NDEBUG)
  // In Release mode we enforce that update checks don't happen too often.
  frequency_seconds_ = std::max(frequency_seconds_, kMinUpdateFrequencySeconds);
#endif
  frequency_seconds_ = std::min(frequency_seconds_, kMaxUpdateFrequencySeconds);

  registrar_.Add(this,
                 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
                 content::NotificationService::AllBrowserContextsAndSources());
}

ExtensionUpdater::~ExtensionUpdater() {
  Stop();
}

// The overall goal here is to balance keeping clients up to date while
// avoiding a thundering herd against update servers.
TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() {
  DCHECK(alive_);
  // If someone's testing with a quick frequency, just allow it.
  if (frequency_seconds_ < kStartupWaitSeconds)
    return TimeDelta::FromSeconds(frequency_seconds_);

  // If we've never scheduled a check before, start at frequency_seconds_.
  if (!prefs_->HasPrefPath(pref_names::kNextUpdateCheck))
    return TimeDelta::FromSeconds(frequency_seconds_);

  // If it's been a long time since our last actual check, we want to do one
  // relatively soon.
  Time now = Time::Now();
  Time last = Time::FromInternalValue(prefs_->GetInt64(
      pref_names::kLastUpdateCheck));
  int days = (now - last).InDays();
  if (days >= 30) {
    // Wait 5-10 minutes.
    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds,
                                          kStartupWaitSeconds * 2));
  } else if (days >= 14) {
    // Wait 10-20 minutes.
    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 2,
                                          kStartupWaitSeconds * 4));
  } else if (days >= 3) {
    // Wait 20-40 minutes.
    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 4,
                                          kStartupWaitSeconds * 8));
  }

  // Read the persisted next check time, and use that if it isn't too soon
  // or too late. Otherwise pick something random.
  Time saved_next = Time::FromInternalValue(prefs_->GetInt64(
      pref_names::kNextUpdateCheck));
  Time earliest = now + TimeDelta::FromSeconds(kStartupWaitSeconds);
  Time latest = now + TimeDelta::FromSeconds(frequency_seconds_);
  if (saved_next >= earliest && saved_next <= latest) {
    return saved_next - now;
  } else {
    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds,
                                          frequency_seconds_));
  }
}

void ExtensionUpdater::Start() {
  DCHECK(!alive_);
  // If these are NULL, then that means we've been called after Stop()
  // has been called.
  DCHECK(service_);
  DCHECK(extension_prefs_);
  DCHECK(prefs_);
  DCHECK(profile_);
  DCHECK(!weak_ptr_factory_.HasWeakPtrs());
  alive_ = true;
  // Make sure our prefs are registered, then schedule the first check.
  ScheduleNextCheck(DetermineFirstCheckDelay());
}

void ExtensionUpdater::Stop() {
  weak_ptr_factory_.InvalidateWeakPtrs();
  alive_ = false;
  service_ = NULL;
  extension_prefs_ = NULL;
  prefs_ = NULL;
  profile_ = NULL;
  timer_.Stop();
  will_check_soon_ = false;
  downloader_.reset();
}

void ExtensionUpdater::ScheduleNextCheck(const TimeDelta& target_delay) {
  DCHECK(alive_);
  DCHECK(!timer_.IsRunning());
  DCHECK(target_delay >= TimeDelta::FromSeconds(1));

  // Add +/- 10% random jitter.
  double delay_ms = target_delay.InMillisecondsF();
  double jitter_factor = (RandDouble() * .2) - 0.1;
  delay_ms += delay_ms * jitter_factor;
  TimeDelta actual_delay = TimeDelta::FromMilliseconds(
      static_cast<int64>(delay_ms));

  // Save the time of next check.
  Time next = Time::Now() + actual_delay;
  prefs_->SetInt64(pref_names::kNextUpdateCheck, next.ToInternalValue());

  timer_.Start(FROM_HERE, actual_delay, this, &ExtensionUpdater::TimerFired);
}

void ExtensionUpdater::TimerFired() {
  DCHECK(alive_);
  CheckNow(default_params_);

  // If the user has overridden the update frequency, don't bother reporting
  // this.
  if (frequency_seconds_ == extensions::kDefaultUpdateFrequencySeconds) {
    Time last = Time::FromInternalValue(prefs_->GetInt64(
        pref_names::kLastUpdateCheck));
    if (last.ToInternalValue() != 0) {
      // Use counts rather than time so we can use minutes rather than millis.
      UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.UpdateCheckGap",
          (Time::Now() - last).InMinutes(),
          TimeDelta::FromSeconds(kStartupWaitSeconds).InMinutes(),
          TimeDelta::FromDays(40).InMinutes(),
          50);  // 50 buckets seems to be the default.
    }
  }

  // Save the last check time, and schedule the next check.
  int64 now = Time::Now().ToInternalValue();
  prefs_->SetInt64(pref_names::kLastUpdateCheck, now);
  ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_));
}

void ExtensionUpdater::CheckSoon() {
  DCHECK(alive_);
  if (will_check_soon_)
    return;
  if (BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&ExtensionUpdater::DoCheckSoon,
                     weak_ptr_factory_.GetWeakPtr()))) {
    will_check_soon_ = true;
  } else {
    NOTREACHED();
  }
}

bool ExtensionUpdater::WillCheckSoon() const {
  return will_check_soon_;
}

void ExtensionUpdater::DoCheckSoon() {
  DCHECK(will_check_soon_);
  CheckNow(default_params_);
  will_check_soon_ = false;
}

void ExtensionUpdater::AddToDownloader(
    const ExtensionSet* extensions,
    const std::list<std::string>& pending_ids,
    int request_id) {
  InProgressCheck& request = requests_in_progress_[request_id];
  for (ExtensionSet::const_iterator extension_iter = extensions->begin();
       extension_iter != extensions->end(); ++extension_iter) {
    const Extension& extension = *extension_iter->get();
    if (!Manifest::IsAutoUpdateableLocation(extension.location())) {
      VLOG(2) << "Extension " << extension.id() << " is not auto updateable";
      continue;
    }
    // An extension might be overwritten by policy, and have its update url
    // changed. Make sure existing extensions aren't fetched again, if a
    // pending fetch for an extension with the same id already exists.
    std::list<std::string>::const_iterator pending_id_iter = std::find(
        pending_ids.begin(), pending_ids.end(), extension.id());
    if (pending_id_iter == pending_ids.end()) {
      if (downloader_->AddExtension(extension, request_id))
        request.in_progress_ids_.push_back(extension.id());
    }
  }
}

void ExtensionUpdater::CheckNow(const CheckParams& params) {
  int request_id = next_request_id_++;

  VLOG(2) << "Starting update check " << request_id;
  if (params.ids.empty())
    NotifyStarted();

  DCHECK(alive_);

  InProgressCheck& request = requests_in_progress_[request_id];
  request.callback = params.callback;
  request.install_immediately = params.install_immediately;

  if (!downloader_.get()) {
    downloader_.reset(
        new ExtensionDownloader(this, profile_->GetRequestContext()));
  }

  // Add fetch records for extensions that should be fetched by an update URL.
  // These extensions are not yet installed. They come from group policy
  // and external install sources.
  const PendingExtensionManager* pending_extension_manager =
      service_->pending_extension_manager();

  std::list<std::string> pending_ids;

  if (params.ids.empty()) {
    // If no extension ids are specified, check for updates for all extensions.
    pending_extension_manager->GetPendingIdsForUpdateCheck(&pending_ids);

    std::list<std::string>::const_iterator iter;
    for (iter = pending_ids.begin(); iter != pending_ids.end(); ++iter) {
      const PendingExtensionInfo* info = pending_extension_manager->GetById(
          *iter);
      if (!Manifest::IsAutoUpdateableLocation(info->install_source())) {
        VLOG(2) << "Extension " << *iter << " is not auto updateable";
        continue;
      }
      if (downloader_->AddPendingExtension(*iter, info->update_url(),
                                           request_id))
        request.in_progress_ids_.push_back(*iter);
    }

    ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
    AddToDownloader(&registry->enabled_extensions(), pending_ids, request_id);
    AddToDownloader(&registry->disabled_extensions(), pending_ids, request_id);
  } else {
    for (std::list<std::string>::const_iterator it = params.ids.begin();
         it != params.ids.end(); ++it) {
      const Extension* extension = service_->GetExtensionById(*it, true);
      DCHECK(extension);
      if (downloader_->AddExtension(*extension, request_id))
        request.in_progress_ids_.push_back(extension->id());
    }
  }

  // StartAllPending() might call OnExtensionDownloadFailed/Finished before
  // it returns, which would cause NotifyIfFinished to incorrectly try to
  // send out a notification. So check before we call StartAllPending if any
  // extensions are going to be updated, and use that to figure out if
  // NotifyIfFinished should be called.
  bool noChecks = request.in_progress_ids_.empty();

  // StartAllPending() will call OnExtensionDownloadFailed or
  // OnExtensionDownloadFinished for each extension that was checked.
  downloader_->StartAllPending(extension_cache_);

  if (noChecks)
    NotifyIfFinished(request_id);
}

bool ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id,
                                          const FinishedCallback& callback) {
  bool have_throttle_info = ContainsKey(throttle_info_, extension_id);
  ThrottleInfo& info = throttle_info_[extension_id];
  if (have_throttle_info) {
    // We already had a ThrottleInfo object for this extension, check if the
    // update check request should be allowed.

    // If another check is in progress, don't start a new check.
    if (info.in_progress)
      return false;

    Time now = Time::Now();
    Time last = info.check_start;
    // If somehow time moved back, we don't want to infinitely keep throttling.
    if (now < last) {
      last = now;
      info.check_start = now;
    }
    Time earliest = last + TimeDelta::FromSeconds(info.throttle_delay);
    // If check is too soon, throttle.
    if (now < earliest)
      return false;

    // TODO(mek): Somehow increase time between allowing checks when checks
    // are repeatedly throttled and don't result in updates being installed.

    // It's okay to start a check, update values.
    info.check_start = now;
    info.in_progress = true;
  }

  CheckParams params;
  params.ids.push_back(extension_id);
  params.callback = base::Bind(&ExtensionUpdater::ExtensionCheckFinished,
                               weak_ptr_factory_.GetWeakPtr(),
                               extension_id, callback);
  CheckNow(params);
  return true;
}

void ExtensionUpdater::ExtensionCheckFinished(
    const std::string& extension_id,
    const FinishedCallback& callback) {
  std::map<std::string, ThrottleInfo>::iterator it =
      throttle_info_.find(extension_id);
  if (it != throttle_info_.end()) {
    it->second.in_progress = false;
  }
  callback.Run();
}

void ExtensionUpdater::OnExtensionDownloadFailed(
    const std::string& id,
    Error error,
    const PingResult& ping,
    const std::set<int>& request_ids) {
  DCHECK(alive_);
  UpdatePingData(id, ping);
  bool install_immediately = false;
  for (std::set<int>::const_iterator it = request_ids.begin();
       it != request_ids.end(); ++it) {
    InProgressCheck& request = requests_in_progress_[*it];
    install_immediately |= request.install_immediately;
    request.in_progress_ids_.remove(id);
    NotifyIfFinished(*it);
  }

  // This method is called if no updates were found. However a previous update
  // check might have queued an update for this extension already. If a
  // current update check has |install_immediately| set the previously
  // queued update should be installed now.
  if (install_immediately && service_->GetPendingExtensionUpdate(id))
    service_->FinishDelayedInstallation(id);
}

void ExtensionUpdater::OnExtensionDownloadFinished(
    const std::string& id,
    const base::FilePath& path,
    bool file_ownership_passed,
    const GURL& download_url,
    const std::string& version,
    const PingResult& ping,
    const std::set<int>& request_ids) {
  DCHECK(alive_);
  UpdatePingData(id, ping);

  VLOG(2) << download_url << " written to " << path.value();

  FetchedCRXFile fetched(id, path, file_ownership_passed, request_ids);
  fetched_crx_files_.push(fetched);

  // MaybeInstallCRXFile() removes extensions from |in_progress_ids_| after
  // starting the crx installer.
  MaybeInstallCRXFile();
}

bool ExtensionUpdater::GetPingDataForExtension(
    const std::string& id,
    ManifestFetchData::PingData* ping_data) {
  DCHECK(alive_);
  ping_data->rollcall_days = CalculatePingDays(
      extension_prefs_->LastPingDay(id));
  ping_data->is_enabled = service_->IsExtensionEnabled(id);
  ping_data->active_days =
      CalculateActivePingDays(extension_prefs_->LastActivePingDay(id),
                              extension_prefs_->GetActiveBit(id));
  return true;
}

std::string ExtensionUpdater::GetUpdateUrlData(const std::string& id) {
  DCHECK(alive_);
  return extension::GetUpdateURLData(extension_prefs_, id);
}

bool ExtensionUpdater::IsExtensionPending(const std::string& id) {
  DCHECK(alive_);
  return service_->pending_extension_manager()->IsIdPending(id);
}

bool ExtensionUpdater::GetExtensionExistingVersion(const std::string& id,
                                                   std::string* version) {
  DCHECK(alive_);
  const Extension* extension = service_->GetExtensionById(id, true);
  if (!extension)
    return false;
  const Extension* update = service_->GetPendingExtensionUpdate(id);
  if (update)
    *version = update->VersionString();
  else
    *version = extension->VersionString();
  return true;
}

void ExtensionUpdater::UpdatePingData(const std::string& id,
                                      const PingResult& ping_result) {
  DCHECK(alive_);
  if (ping_result.did_ping)
    extension_prefs_->SetLastPingDay(id, ping_result.day_start);
  if (extension_prefs_->GetActiveBit(id)) {
    extension_prefs_->SetActiveBit(id, false);
    extension_prefs_->SetLastActivePingDay(id, ping_result.day_start);
  }
}

void ExtensionUpdater::MaybeInstallCRXFile() {
  if (crx_install_is_running_ || fetched_crx_files_.empty())
    return;

  std::set<int> request_ids;

  while (!fetched_crx_files_.empty() && !crx_install_is_running_) {
    const FetchedCRXFile& crx_file = fetched_crx_files_.top();

    VLOG(2) << "updating " << crx_file.extension_id
            << " with " << crx_file.path.value();

    // The ExtensionService is now responsible for cleaning up the temp file
    // at |crx_file.path|.
    CrxInstaller* installer = NULL;
    if (service_->UpdateExtension(crx_file.extension_id,
                                  crx_file.path,
                                  crx_file.file_ownership_passed,
                                  &installer)) {
      crx_install_is_running_ = true;
      current_crx_file_ = crx_file;

      for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
          it != crx_file.request_ids.end(); ++it) {
        InProgressCheck& request = requests_in_progress_[*it];
        if (request.install_immediately) {
          installer->set_install_immediately(true);
          break;
        }
      }

      // Source parameter ensures that we only see the completion event for the
      // the installer we started.
      registrar_.Add(this,
                     chrome::NOTIFICATION_CRX_INSTALLER_DONE,
                     content::Source<CrxInstaller>(installer));
    } else {
      for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
           it != crx_file.request_ids.end(); ++it) {
        InProgressCheck& request = requests_in_progress_[*it];
        request.in_progress_ids_.remove(crx_file.extension_id);
      }
      request_ids.insert(crx_file.request_ids.begin(),
                         crx_file.request_ids.end());
    }
    fetched_crx_files_.pop();
  }

  for (std::set<int>::const_iterator it = request_ids.begin();
       it != request_ids.end(); ++it) {
    NotifyIfFinished(*it);
  }
}

void ExtensionUpdater::Observe(int type,
                               const content::NotificationSource& source,
                               const content::NotificationDetails& details) {
  switch (type) {
    case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
      // No need to listen for CRX_INSTALLER_DONE anymore.
      registrar_.Remove(this,
                        chrome::NOTIFICATION_CRX_INSTALLER_DONE,
                        source);
      crx_install_is_running_ = false;

      const FetchedCRXFile& crx_file = current_crx_file_;
      for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
          it != crx_file.request_ids.end(); ++it) {
        InProgressCheck& request = requests_in_progress_[*it];
        request.in_progress_ids_.remove(crx_file.extension_id);
        NotifyIfFinished(*it);
      }

      // If any files are available to update, start one.
      MaybeInstallCRXFile();
      break;
    }
    case chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED: {
      const Extension* extension =
          content::Details<const InstalledExtensionInfo>(details)->extension;
      if (extension)
        throttle_info_.erase(extension->id());
      break;
    }
    default:
      NOTREACHED();
  }
}

void ExtensionUpdater::NotifyStarted() {
  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED,
      content::Source<Profile>(profile_),
      content::NotificationService::NoDetails());
}

void ExtensionUpdater::NotifyIfFinished(int request_id) {
  DCHECK(ContainsKey(requests_in_progress_, request_id));
  const InProgressCheck& request = requests_in_progress_[request_id];
  if (request.in_progress_ids_.empty()) {
    VLOG(2) << "Finished update check " << request_id;
    if (!request.callback.is_null())
      request.callback.Run();
    requests_in_progress_.erase(request_id);
  }
}

}  // namespace extensions
