15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/updater/extension_updater.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/api/module/module.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/crx_installer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/pending_extension_manager.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omaha_query_params/omaha_query_params.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/sha2.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/pref_names.h"
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "extensions/common/constants.h"
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/manifest_constants.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::RandDouble;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::RandInt;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::Extension;
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::ExtensionSet;
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing omaha_query_params::OmahaQueryParams;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef extensions::ExtensionDownloaderDelegate::Error Error;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef extensions::ExtensionDownloaderDelegate::PingResult PingResult;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wait at least 5 minutes after browser startup before we do any checks. If you
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// change this value, make sure to update comments where it is used.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStartupWaitSeconds = 60 * 5;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For sanity checking on update frequency - enforced in release mode only.
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(NDEBUG)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinUpdateFrequencySeconds = 30;
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxUpdateFrequencySeconds = 60 * 60 * 24 * 7;  // 7 days
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Require at least 5 seconds between consecutive non-succesful extension update
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// checks.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMinUpdateThrottleTime = 5;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The installsource query parameter to use when forcing updates due to NaCl
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// arch mismatch.
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char kWrongMultiCrxInstallSource[] = "wrong_multi_crx";
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we've computed a days value, we want to make sure we don't send a
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// negative value (due to the system clock being set backwards, etc.), since -1
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is a special sentinel value that means "never pinged", and other negative
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// values don't make sense.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SanitizeDays(int days) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (days < 0)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return days;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calculates the value to use for the ping days parameter.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculatePingDays(const Time& last_ping_day) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int days = extensions::ManifestFetchData::kNeverPinged;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!last_ping_day.is_null()) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    days = SanitizeDays((Time::Now() - last_ping_day).InDays());
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return days;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CalculateActivePingDays(const Time& last_active_ping_day,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool hasActiveBit) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!hasActiveBit)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_active_ping_day.is_null())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extensions::ManifestFetchData::kNeverPinged;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SanitizeDays((Time::Now() - last_active_ping_day).InDays());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RespondWithForcedUpdates(
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Callback<void(const std::set<std::string>&)>& callback,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<std::set<std::string> > forced_updates) {
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(*forced_updates.get());
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DetermineForcedUpdatesOnBlockingPool(
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<std::vector<scoped_refptr<const Extension> > > extensions,
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Callback<void(const std::set<std::string>&)>& callback) {
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<std::set<std::string> > forced_updates(
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new std::set<std::string>());
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<scoped_refptr<const Extension> >::const_iterator iter =
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          extensions->begin();
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       iter != extensions->end();
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++iter) {
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<const Extension> extension = *iter;
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::FilePath platform_specific_path = extension->path().Append(
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        extensions::kPlatformSpecificFolder);
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (base::PathExists(platform_specific_path)) {
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bool force = true;
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const base::ListValue* platforms;
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (extension->manifest()->GetList(extensions::manifest_keys::kPlatforms,
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         &platforms)) {
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        for (size_t i = 0; i < platforms->GetSize(); ++i) {
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          const base::DictionaryValue* p;
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (platforms->GetDictionary(i, &p)) {
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            std::string nacl_arch;
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            if (p->GetString(extensions::manifest_keys::kNaClArch,
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             &nacl_arch) &&
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                nacl_arch == OmahaQueryParams::GetNaclArch()) {
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              std::string subpath;
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              if (p->GetString(extensions::manifest_keys::kSubPackagePath,
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               &subpath)) {
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                // _platform_specific is part of the sub_package_path entry.
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                base::FilePath platform_specific_subpath =
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    extension->path().AppendASCII(subpath);
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                if (base::PathExists(platform_specific_subpath)) {
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  force = false;
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                }
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              }
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            }
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (force)
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        forced_updates->insert(extension->id());
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   }
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserThread::PostTask(
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserThread::UI,
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&RespondWithForcedUpdates,
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(&forced_updates)));
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CollectExtensionsFromSet(
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ExtensionSet& extensions,
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::vector<scoped_refptr<const Extension> >* paths) {
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::copy(extensions.begin(), extensions.end(), std::back_inserter(*paths));
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DetermineForcedUpdates(
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    content::BrowserContext* browser_context,
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Callback<void(const std::set<std::string>&)>& callback) {
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<std::vector<scoped_refptr<const Extension> > > extensions(
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new std::vector<scoped_refptr<const Extension> >());
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const extensions::ExtensionRegistry* registry =
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionRegistry::Get(browser_context);
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ExtensionSet> installed_extensions =
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      registry->GenerateInstalledExtensionsSet();
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CollectExtensionsFromSet(*installed_extensions.get(), extensions.get());
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserThread::PostBlockingPoolTask(
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&DetermineForcedUpdatesOnBlockingPool,
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(&extensions),
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback));
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionUpdater::CheckParams::CheckParams()
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : install_immediately(false) {}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionUpdater::CheckParams::~CheckParams() {}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionUpdater::FetchedCRXFile::FetchedCRXFile(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& i,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& p,
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool file_ownership_passed,
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<int>& request_ids)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : extension_id(i),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path(p),
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_ownership_passed(file_ownership_passed),
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_ids(request_ids) {}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionUpdater::FetchedCRXFile::FetchedCRXFile()
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : path(), file_ownership_passed(true) {}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionUpdater::FetchedCRXFile::~FetchedCRXFile() {}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionUpdater::InProgressCheck::InProgressCheck()
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : install_immediately(false) {}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionUpdater::InProgressCheck::~InProgressCheck() {}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ExtensionUpdater::ThrottleInfo {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThrottleInfo()
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : in_progress(true),
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        throttle_delay(kMinUpdateThrottleTime),
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        check_start(Time::Now()) {}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool in_progress;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int throttle_delay;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Time check_start;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ExtensionUpdater::ExtensionUpdater(
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionServiceInterface* service,
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionPrefs* extension_prefs,
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    PrefService* prefs,
2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Profile* profile,
2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int frequency_seconds,
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ExtensionCache* cache,
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const ExtensionDownloader::Factory& downloader_factory)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : alive_(false),
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      service_(service),
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      downloader_factory_(downloader_factory),
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      frequency_seconds_(frequency_seconds),
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      will_check_soon_(false),
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      extension_prefs_(extension_prefs),
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      prefs_(prefs),
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      profile_(profile),
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_request_id_(0),
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_registry_observer_(this),
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      crx_install_is_running_(false),
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extension_cache_(cache),
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_ptr_factory_(this) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(frequency_seconds_, 5);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds);
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(NDEBUG)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In Release mode we enforce that update checks don't happen too often.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frequency_seconds_ = std::max(frequency_seconds_, kMinUpdateFrequencySeconds);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frequency_seconds_ = std::min(frequency_seconds_, kMaxUpdateFrequencySeconds);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionUpdater::~ExtensionUpdater() {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ExtensionUpdater::EnsureDownloaderCreated() {
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!downloader_.get()) {
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    downloader_ = downloader_factory_.Run(this);
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The overall goal here is to balance keeping clients up to date while
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// avoiding a thundering herd against update servers.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If someone's testing with a quick frequency, just allow it.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frequency_seconds_ < kStartupWaitSeconds)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(frequency_seconds_);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we've never scheduled a check before, start at frequency_seconds_.
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!prefs_->HasPrefPath(pref_names::kNextUpdateCheck))
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(frequency_seconds_);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it's been a long time since our last actual check, we want to do one
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // relatively soon.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time now = Time::Now();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time last = Time::FromInternalValue(prefs_->GetInt64(
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_names::kLastUpdateCheck));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int days = (now - last).InDays();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (days >= 30) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait 5-10 minutes.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          kStartupWaitSeconds * 2));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (days >= 14) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait 10-20 minutes.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 2,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          kStartupWaitSeconds * 4));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (days >= 3) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait 20-40 minutes.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 4,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          kStartupWaitSeconds * 8));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Read the persisted next check time, and use that if it isn't too soon
2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // or too late. Otherwise pick something random.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time saved_next = Time::FromInternalValue(prefs_->GetInt64(
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_names::kNextUpdateCheck));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time earliest = now + TimeDelta::FromSeconds(kStartupWaitSeconds);
3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Time latest = now + TimeDelta::FromSeconds(frequency_seconds_);
3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (saved_next >= earliest && saved_next <= latest) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return saved_next - now;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          frequency_seconds_));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::Start() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!alive_);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If these are NULL, then that means we've been called after Stop()
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has been called.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service_);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(extension_prefs_);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(prefs_);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!weak_ptr_factory_.HasWeakPtrs());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  alive_ = true;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure our prefs are registered, then schedule the first check.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleNextCheck(DetermineFirstCheckDelay());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::Stop() {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  alive_ = false;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_ = NULL;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_prefs_ = NULL;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs_ = NULL;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = NULL;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.Stop();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  will_check_soon_ = false;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  downloader_.reset();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::ScheduleNextCheck(const TimeDelta& target_delay) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!timer_.IsRunning());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(target_delay >= TimeDelta::FromSeconds(1));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add +/- 10% random jitter.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double delay_ms = target_delay.InMillisecondsF();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double jitter_factor = (RandDouble() * .2) - 0.1;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_ms += delay_ms * jitter_factor;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta actual_delay = TimeDelta::FromMilliseconds(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<int64>(delay_ms));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the time of next check.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time next = Time::Now() + actual_delay;
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs_->SetInt64(pref_names::kNextUpdateCheck, next.ToInternalValue());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_.Start(FROM_HERE, actual_delay, this, &ExtensionUpdater::TimerFired);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::TimerFired() {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckNow(default_params_);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the user has overridden the update frequency, don't bother reporting
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this.
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (frequency_seconds_ == extensions::kDefaultUpdateFrequencySeconds) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Time last = Time::FromInternalValue(prefs_->GetInt64(
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pref_names::kLastUpdateCheck));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last.ToInternalValue() != 0) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use counts rather than time so we can use minutes rather than millis.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.UpdateCheckGap",
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (Time::Now() - last).InMinutes(),
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TimeDelta::FromSeconds(kStartupWaitSeconds).InMinutes(),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TimeDelta::FromDays(40).InMinutes(),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          50);  // 50 buckets seems to be the default.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the last check time, and schedule the next check.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 now = Time::Now().ToInternalValue();
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs_->SetInt64(pref_names::kLastUpdateCheck, now);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::CheckSoon() {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (will_check_soon_)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BrowserThread::PostTask(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BrowserThread::UI, FROM_HERE,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ExtensionUpdater::DoCheckSoon,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()))) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    will_check_soon_ = true;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionUpdater::WillCheckSoon() const {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return will_check_soon_;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::DoCheckSoon() {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(will_check_soon_);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckNow(default_params_);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  will_check_soon_ = false;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::AddToDownloader(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ExtensionSet* extensions,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::list<std::string>& pending_ids,
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int request_id) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InProgressCheck& request = requests_in_progress_[request_id];
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionSet::const_iterator extension_iter = extensions->begin();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       extension_iter != extensions->end(); ++extension_iter) {
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const Extension& extension = *extension_iter->get();
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!Manifest::IsAutoUpdateableLocation(extension.location())) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(2) << "Extension " << extension.id() << " is not auto updateable";
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // An extension might be overwritten by policy, and have its update url
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // changed. Make sure existing extensions aren't fetched again, if a
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pending fetch for an extension with the same id already exists.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::list<std::string>::const_iterator pending_id_iter = std::find(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_ids.begin(), pending_ids.end(), extension.id());
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_id_iter == pending_ids.end()) {
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (downloader_->AddExtension(extension, request_id))
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request.in_progress_ids_.push_back(extension.id());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::CheckNow(const CheckParams& params) {
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DetermineForcedUpdates(
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      profile_,
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ExtensionUpdater::OnForcedUpdatesDetermined,
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr(),
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 params));
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionUpdater::OnForcedUpdatesDetermined(
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const CheckParams& params,
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::set<std::string>& forced_updates) {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int request_id = next_request_id_++;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(2) << "Starting update check " << request_id;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params.ids.empty())
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyStarted();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InProgressCheck& request = requests_in_progress_[request_id];
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.callback = params.callback;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.install_immediately = params.install_immediately;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EnsureDownloaderCreated();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  forced_updates_ = forced_updates;
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add fetch records for extensions that should be fetched by an update URL.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These extensions are not yet installed. They come from group policy
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and external install sources.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PendingExtensionManager* pending_extension_manager =
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->pending_extension_manager();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<std::string> pending_ids;
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params.ids.empty()) {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If no extension ids are specified, check for updates for all extensions.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_extension_manager->GetPendingIdsForUpdateCheck(&pending_ids);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::list<std::string>::const_iterator iter;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (iter = pending_ids.begin(); iter != pending_ids.end(); ++iter) {
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const PendingExtensionInfo* info = pending_extension_manager->GetById(
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          *iter);
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!Manifest::IsAutoUpdateableLocation(info->install_source())) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(2) << "Extension " << *iter << " is not auto updateable";
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (downloader_->AddPendingExtension(*iter, info->update_url(),
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           request_id))
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request.in_progress_ids_.push_back(*iter);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddToDownloader(&registry->enabled_extensions(), pending_ids, request_id);
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddToDownloader(&registry->disabled_extensions(), pending_ids, request_id);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::list<std::string>::const_iterator it = params.ids.begin();
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != params.ids.end(); ++it) {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const Extension* extension = service_->GetExtensionById(*it, true);
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(extension);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (downloader_->AddExtension(*extension, request_id))
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request.in_progress_ids_.push_back(extension->id());
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // StartAllPending() might call OnExtensionDownloadFailed/Finished before
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it returns, which would cause NotifyIfFinished to incorrectly try to
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // send out a notification. So check before we call StartAllPending if any
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extensions are going to be updated, and use that to figure out if
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NotifyIfFinished should be called.
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool noChecks = request.in_progress_ids_.empty();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // StartAllPending() will call OnExtensionDownloadFailed or
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnExtensionDownloadFinished for each extension that was checked.
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  downloader_->StartAllPending(extension_cache_);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (noChecks)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyIfFinished(request_id);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id,
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const FinishedCallback& callback) {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool have_throttle_info = ContainsKey(throttle_info_, extension_id);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThrottleInfo& info = throttle_info_[extension_id];
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (have_throttle_info) {
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We already had a ThrottleInfo object for this extension, check if the
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // update check request should be allowed.
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If another check is in progress, don't start a new check.
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (info.in_progress)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Time now = Time::Now();
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Time last = info.check_start;
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If somehow time moved back, we don't want to infinitely keep throttling.
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (now < last) {
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last = now;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info.check_start = now;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Time earliest = last + TimeDelta::FromSeconds(info.throttle_delay);
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If check is too soon, throttle.
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (now < earliest)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(mek): Somehow increase time between allowing checks when checks
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // are repeatedly throttled and don't result in updates being installed.
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // It's okay to start a check, update values.
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    info.check_start = now;
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    info.in_progress = true;
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckParams params;
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.ids.push_back(extension_id);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.callback = base::Bind(&ExtensionUpdater::ExtensionCheckFinished,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               weak_ptr_factory_.GetWeakPtr(),
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               extension_id, callback);
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckNow(params);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::ExtensionCheckFinished(
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FinishedCallback& callback) {
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, ThrottleInfo>::iterator it =
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      throttle_info_.find(extension_id);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it != throttle_info_.end()) {
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->second.in_progress = false;
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::OnExtensionDownloadFailed(
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& id,
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Error error,
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PingResult& ping,
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<int>& request_ids) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePingData(id, ping);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool install_immediately = false;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::set<int>::const_iterator it = request_ids.begin();
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != request_ids.end(); ++it) {
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InProgressCheck& request = requests_in_progress_[*it];
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    install_immediately |= request.install_immediately;
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request.in_progress_ids_.remove(id);
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyIfFinished(*it);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method is called if no updates were found. However a previous update
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check might have queued an update for this extension already. If a
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // current update check has |install_immediately| set the previously
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // queued update should be installed now.
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (install_immediately && service_->GetPendingExtensionUpdate(id))
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    service_->FinishDelayedInstallation(id);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::OnExtensionDownloadFinished(
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& id,
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool file_ownership_passed,
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& download_url,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& version,
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PingResult& ping,
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<int>& request_ids) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePingData(id, ping);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << download_url << " written to " << path.value();
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FetchedCRXFile fetched(id, path, file_ownership_passed, request_ids);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_crx_files_.push(fetched);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MaybeInstallCRXFile() removes extensions from |in_progress_ids_| after
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // starting the crx installer.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeInstallCRXFile();
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionUpdater::GetPingDataForExtension(
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id,
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManifestFetchData::PingData* ping_data) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ping_data->rollcall_days = CalculatePingDays(
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_prefs_->LastPingDay(id));
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ping_data->is_enabled = service_->IsExtensionEnabled(id);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ping_data->active_days =
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CalculateActivePingDays(extension_prefs_->LastActivePingDay(id),
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extension_prefs_->GetActiveBit(id));
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionUpdater::GetUpdateUrlData(const std::string& id) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return extension::GetUpdateURLData(extension_prefs_, id);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionUpdater::IsExtensionPending(const std::string& id) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_->pending_extension_manager()->IsIdPending(id);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionUpdater::GetExtensionExistingVersion(const std::string& id,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   std::string* version) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension = service_->GetExtensionById(id, true);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Extension* update = service_->GetPendingExtensionUpdate(id);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (update)
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *version = update->VersionString();
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *version = extension->VersionString();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ExtensionUpdater::ShouldForceUpdate(
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& extension_id,
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string* source) {
6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool force = forced_updates_.find(extension_id) != forced_updates_.end();
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Currently the only reason to force is a NaCl arch mismatch with the
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // installed extension contents.
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (force) {
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    *source = kWrongMultiCrxInstallSource;
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return force;
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::UpdatePingData(const std::string& id,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const PingResult& ping_result) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(alive_);
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ping_result.did_ping)
65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    extension_prefs_->SetLastPingDay(id, ping_result.day_start);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_prefs_->GetActiveBit(id)) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_prefs_->SetActiveBit(id, false);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_prefs_->SetLastActivePingDay(id, ping_result.day_start);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::MaybeInstallCRXFile() {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (crx_install_is_running_ || fetched_crx_files_.empty())
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<int> request_ids;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!fetched_crx_files_.empty() && !crx_install_is_running_) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FetchedCRXFile& crx_file = fetched_crx_files_.top();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(2) << "updating " << crx_file.extension_id
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " with " << crx_file.path.value();
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The ExtensionService is now responsible for cleaning up the temp file
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at |crx_file.path|.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrxInstaller* installer = NULL;
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (service_->UpdateExtension(crx_file.extension_id,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  crx_file.path,
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  crx_file.file_ownership_passed,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &installer)) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crx_install_is_running_ = true;
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_crx_file_ = crx_file;
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          it != crx_file.request_ids.end(); ++it) {
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        InProgressCheck& request = requests_in_progress_[*it];
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (request.install_immediately) {
691f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          installer->set_install_immediately(true);
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Source parameter ensures that we only see the completion event for the
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the installer we started.
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registrar_.Add(this,
6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     extensions::NOTIFICATION_CRX_INSTALLER_DONE,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     content::Source<CrxInstaller>(installer));
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           it != crx_file.request_ids.end(); ++it) {
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        InProgressCheck& request = requests_in_progress_[*it];
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request.in_progress_ids_.remove(crx_file.extension_id);
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_ids.insert(crx_file.request_ids.begin(),
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         crx_file.request_ids.end());
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetched_crx_files_.pop();
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::set<int>::const_iterator it = request_ids.begin();
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != request_ids.end(); ++it) {
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyIfFinished(*it);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::Observe(int type,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const content::NotificationSource& source,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const content::NotificationDetails& details) {
7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(type, extensions::NOTIFICATION_CRX_INSTALLER_DONE);
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Remove(this, extensions::NOTIFICATION_CRX_INSTALLER_DONE, source);
725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crx_install_is_running_ = false;
726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const FetchedCRXFile& crx_file = current_crx_file_;
728116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::set<int>::const_iterator it = crx_file.request_ids.begin();
729116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      it != crx_file.request_ids.end(); ++it) {
730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    InProgressCheck& request = requests_in_progress_[*it];
731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    request.in_progress_ids_.remove(crx_file.extension_id);
732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NotifyIfFinished(*it);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If any files are available to update, start one.
736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MaybeInstallCRXFile();
737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
738116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
739116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionUpdater::OnExtensionWillBeInstalled(
740116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
741116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
742116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update,
743116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool from_ephemeral,
744116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& old_name) {
745116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  throttle_info_.erase(extension->id());
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionUpdater::NotifyStarted() {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<Profile>(profile_),
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::NoDetails());
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionUpdater::NotifyIfFinished(int request_id) {
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(ContainsKey(requests_in_progress_, request_id));
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const InProgressCheck& request = requests_in_progress_[request_id];
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request.in_progress_ids_.empty()) {
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(2) << "Finished update check " << request_id;
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!request.callback.is_null())
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request.callback.Run();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    requests_in_progress_.erase(request_id);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
767