1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/component_updater/chrome_component_updater_configurator.h" 6 7#include <algorithm> 8#include <string> 9#include <vector> 10 11#include "base/command_line.h" 12#include "base/compiler_specific.h" 13#include "base/strings/string_util.h" 14#include "base/version.h" 15#if defined(OS_WIN) 16#include "base/win/win_util.h" 17#endif // OS_WIN 18#include "build/build_config.h" 19#include "chrome/browser/component_updater/component_patcher_operation_out_of_process.h" 20#include "chrome/browser/omaha_query_params/chrome_omaha_query_params_delegate.h" 21#include "chrome/common/chrome_version_info.h" 22#include "components/component_updater/component_updater_configurator.h" 23#include "components/component_updater/component_updater_switches.h" 24#include "content/public/browser/browser_thread.h" 25#include "net/url_request/url_request_context_getter.h" 26#include "url/gurl.h" 27 28namespace component_updater { 29 30namespace { 31 32// Default time constants. 33const int kDelayOneMinute = 60; 34const int kDelayOneHour = kDelayOneMinute * 60; 35 36// Debug values you can pass to --component-updater=value1,value2. 37// Speed up component checking. 38const char kSwitchFastUpdate[] = "fast-update"; 39 40// Add "testrequest=1" attribute to the update check request. 41const char kSwitchRequestParam[] = "test-request"; 42 43// Disables pings. Pings are the requests sent to the update server that report 44// the success or the failure of component install or update attempts. 45extern const char kSwitchDisablePings[] = "disable-pings"; 46 47// Sets the URL for updates. 48const char kSwitchUrlSource[] = "url-source"; 49 50#define COMPONENT_UPDATER_SERVICE_ENDPOINT \ 51 "//clients2.google.com/service/update2" 52 53// The default URL for the v3 protocol service endpoint. In some cases, the 54// component updater is allowed to fall back to and alternate URL source, if 55// the request to the default URL source fails. 56// The value of |kDefaultUrlSource| can be overridden with 57// --component-updater=url-source=someurl. 58const char kDefaultUrlSource[] = "https:" COMPONENT_UPDATER_SERVICE_ENDPOINT; 59const char kAltUrlSource[] = "http:" COMPONENT_UPDATER_SERVICE_ENDPOINT; 60 61// Disables differential updates. 62const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates"; 63 64#if defined(OS_WIN) 65// Disables background downloads. 66const char kSwitchDisableBackgroundDownloads[] = "disable-background-downloads"; 67#endif // defined(OS_WIN) 68 69// Returns true if and only if |test| is contained in |vec|. 70bool HasSwitchValue(const std::vector<std::string>& vec, const char* test) { 71 if (vec.empty()) 72 return 0; 73 return (std::find(vec.begin(), vec.end(), test) != vec.end()); 74} 75 76// Returns true if falling back on an alternate, unsafe, service URL is 77// allowed. In the fallback case, the security of the component update relies 78// only on the integrity of the CRX payloads, which is self-validating. 79// This is allowed only for some of the pre-Windows Vista versions not including 80// Windows XP SP3. As a side note, pings could be sent to the alternate URL too. 81bool CanUseAltUrlSource() { 82#if defined(OS_WIN) 83 return !base::win::MaybeHasSHA256Support(); 84#else 85 return false; 86#endif // OS_WIN 87} 88 89// If there is an element of |vec| of the form |test|=.*, returns the right- 90// hand side of that assignment. Otherwise, returns an empty string. 91// The right-hand side may contain additional '=' characters, allowing for 92// further nesting of switch arguments. 93std::string GetSwitchArgument(const std::vector<std::string>& vec, 94 const char* test) { 95 if (vec.empty()) 96 return std::string(); 97 for (std::vector<std::string>::const_iterator it = vec.begin(); 98 it != vec.end(); 99 ++it) { 100 const std::size_t found = it->find("="); 101 if (found != std::string::npos) { 102 if (it->substr(0, found) == test) { 103 return it->substr(found + 1); 104 } 105 } 106 } 107 return std::string(); 108} 109 110class ChromeConfigurator : public Configurator { 111 public: 112 ChromeConfigurator(const CommandLine* cmdline, 113 net::URLRequestContextGetter* url_request_getter); 114 115 virtual ~ChromeConfigurator() {} 116 117 virtual int InitialDelay() const OVERRIDE; 118 virtual int NextCheckDelay() OVERRIDE; 119 virtual int StepDelay() const OVERRIDE; 120 virtual int StepDelayMedium() OVERRIDE; 121 virtual int MinimumReCheckWait() const OVERRIDE; 122 virtual int OnDemandDelay() const OVERRIDE; 123 virtual std::vector<GURL> UpdateUrl() const OVERRIDE; 124 virtual std::vector<GURL> PingUrl() const OVERRIDE; 125 virtual base::Version GetBrowserVersion() const OVERRIDE; 126 virtual std::string GetChannel() const OVERRIDE; 127 virtual std::string GetLang() const OVERRIDE; 128 virtual std::string GetOSLongName() const OVERRIDE; 129 virtual std::string ExtraRequestParams() const OVERRIDE; 130 virtual size_t UrlSizeLimit() const OVERRIDE; 131 virtual net::URLRequestContextGetter* RequestContext() const OVERRIDE; 132 virtual scoped_refptr<OutOfProcessPatcher> CreateOutOfProcessPatcher() 133 const OVERRIDE; 134 virtual bool DeltasEnabled() const OVERRIDE; 135 virtual bool UseBackgroundDownloader() const OVERRIDE; 136 virtual scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() 137 const OVERRIDE; 138 virtual scoped_refptr<base::SingleThreadTaskRunner> 139 GetSingleThreadTaskRunner() const OVERRIDE; 140 141 private: 142 net::URLRequestContextGetter* url_request_getter_; 143 std::string extra_info_; 144 GURL url_source_override_; 145 bool fast_update_; 146 bool pings_enabled_; 147 bool deltas_enabled_; 148 bool background_downloads_enabled_; 149 bool fallback_to_alt_source_url_enabled_; 150}; 151 152ChromeConfigurator::ChromeConfigurator( 153 const CommandLine* cmdline, 154 net::URLRequestContextGetter* url_request_getter) 155 : url_request_getter_(url_request_getter), 156 fast_update_(false), 157 pings_enabled_(false), 158 deltas_enabled_(false), 159 background_downloads_enabled_(false), 160 fallback_to_alt_source_url_enabled_(false) { 161 // Parse comma-delimited debug flags. 162 std::vector<std::string> switch_values; 163 Tokenize(cmdline->GetSwitchValueASCII(switches::kComponentUpdater), 164 ",", 165 &switch_values); 166 fast_update_ = HasSwitchValue(switch_values, kSwitchFastUpdate); 167 pings_enabled_ = !HasSwitchValue(switch_values, kSwitchDisablePings); 168 deltas_enabled_ = !HasSwitchValue(switch_values, kSwitchDisableDeltaUpdates); 169 170#if defined(OS_WIN) 171 background_downloads_enabled_ = 172 !HasSwitchValue(switch_values, kSwitchDisableBackgroundDownloads); 173#else 174 background_downloads_enabled_ = false; 175#endif 176 177 const std::string switch_url_source = 178 GetSwitchArgument(switch_values, kSwitchUrlSource); 179 if (!switch_url_source.empty()) { 180 url_source_override_ = GURL(switch_url_source); 181 DCHECK(url_source_override_.is_valid()); 182 } 183 184 if (HasSwitchValue(switch_values, kSwitchRequestParam)) 185 extra_info_ += "testrequest=\"1\""; 186 187 fallback_to_alt_source_url_enabled_ = CanUseAltUrlSource(); 188} 189 190int ChromeConfigurator::InitialDelay() const { 191 return fast_update_ ? 1 : (6 * kDelayOneMinute); 192} 193 194int ChromeConfigurator::NextCheckDelay() { 195 return fast_update_ ? 3 : (6 * kDelayOneHour); 196} 197 198int ChromeConfigurator::StepDelayMedium() { 199 return fast_update_ ? 3 : (15 * kDelayOneMinute); 200} 201 202int ChromeConfigurator::StepDelay() const { 203 return fast_update_ ? 1 : 1; 204} 205 206int ChromeConfigurator::MinimumReCheckWait() const { 207 return fast_update_ ? 30 : (6 * kDelayOneHour); 208} 209 210int ChromeConfigurator::OnDemandDelay() const { 211 return fast_update_ ? 2 : (30 * kDelayOneMinute); 212} 213 214std::vector<GURL> ChromeConfigurator::UpdateUrl() const { 215 std::vector<GURL> urls; 216 if (url_source_override_.is_valid()) { 217 urls.push_back(GURL(url_source_override_)); 218 } else { 219 urls.push_back(GURL(kDefaultUrlSource)); 220 if (fallback_to_alt_source_url_enabled_) { 221 urls.push_back(GURL(kAltUrlSource)); 222 } 223 } 224 return urls; 225} 226 227std::vector<GURL> ChromeConfigurator::PingUrl() const { 228 return pings_enabled_ ? UpdateUrl() : std::vector<GURL>(); 229} 230 231base::Version ChromeConfigurator::GetBrowserVersion() const { 232 return base::Version(chrome::VersionInfo().Version()); 233} 234 235std::string ChromeConfigurator::GetChannel() const { 236 return ChromeOmahaQueryParamsDelegate::GetChannelString(); 237} 238 239std::string ChromeConfigurator::GetLang() const { 240 return ChromeOmahaQueryParamsDelegate::GetLang(); 241} 242 243std::string ChromeConfigurator::GetOSLongName() const { 244 return chrome::VersionInfo().OSType(); 245} 246 247std::string ChromeConfigurator::ExtraRequestParams() const { 248 return extra_info_; 249} 250 251size_t ChromeConfigurator::UrlSizeLimit() const { 252 return 1024ul; 253} 254 255net::URLRequestContextGetter* ChromeConfigurator::RequestContext() const { 256 return url_request_getter_; 257} 258 259scoped_refptr<OutOfProcessPatcher> 260ChromeConfigurator::CreateOutOfProcessPatcher() const { 261 return make_scoped_refptr(new ChromeOutOfProcessPatcher); 262} 263 264bool ChromeConfigurator::DeltasEnabled() const { 265 return deltas_enabled_; 266} 267 268bool ChromeConfigurator::UseBackgroundDownloader() const { 269 return background_downloads_enabled_; 270} 271 272scoped_refptr<base::SequencedTaskRunner> 273ChromeConfigurator::GetSequencedTaskRunner() const { 274 return content::BrowserThread::GetBlockingPool() 275 ->GetSequencedTaskRunnerWithShutdownBehavior( 276 content::BrowserThread::GetBlockingPool()->GetSequenceToken(), 277 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 278} 279 280scoped_refptr<base::SingleThreadTaskRunner> 281ChromeConfigurator::GetSingleThreadTaskRunner() const { 282 return content::BrowserThread::GetMessageLoopProxyForThread( 283 content::BrowserThread::FILE); 284} 285 286} // namespace 287 288Configurator* MakeChromeComponentUpdaterConfigurator( 289 const base::CommandLine* cmdline, 290 net::URLRequestContextGetter* context_getter) { 291 return new ChromeConfigurator(cmdline, context_getter); 292} 293 294} // namespace component_updater 295