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(®istry->enabled_extensions(), pending_ids, request_id); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AddToDownloader(®istry->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