1 // Copyright 2013 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/component_updater_utils.h" 6 7 #include <cmath> 8 9 #include "base/file_util.h" 10 #include "base/files/file_path.h" 11 #include "base/guid.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_piece.h" 14 #include "base/strings/string_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "base/sys_info.h" 17 #include "base/win/windows_version.h" 18 #include "chrome/browser/component_updater/component_updater_service.h" 19 #include "chrome/browser/component_updater/crx_update_item.h" 20 #include "chrome/browser/omaha_query_params/omaha_query_params.h" 21 #include "chrome/common/chrome_version_info.h" 22 #include "extensions/common/extension.h" 23 #include "net/base/load_flags.h" 24 #include "net/url_request/url_fetcher.h" 25 #include "net/url_request/url_request_context_getter.h" 26 #include "net/url_request/url_request_status.h" 27 28 namespace component_updater { 29 30 namespace { 31 32 // Returns the amount of physical memory in GB, rounded to the nearest GB. 33 int GetPhysicalMemoryGB() { 34 const double kOneGB = 1024 * 1024 * 1024; 35 const int64 phys_mem = base::SysInfo::AmountOfPhysicalMemory(); 36 return static_cast<int>(std::floor(0.5 + phys_mem / kOneGB)); 37 } 38 39 } // namespace 40 41 std::string BuildProtocolRequest(const std::string& request_body, 42 const std::string& additional_attributes) { 43 const std::string prod_id(chrome::OmahaQueryParams::GetProdIdString( 44 chrome::OmahaQueryParams::CHROME)); 45 const chrome::VersionInfo chrome_version_info; 46 const std::string chrome_version(chrome_version_info.Version()); 47 48 std::string request( 49 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 50 "<request protocol=\"3.0\" "); 51 52 if (!additional_attributes.empty()) 53 base::StringAppendF(&request, "%s ", additional_attributes.c_str()); 54 55 // Chrome version and platform information. 56 base::StringAppendF( 57 &request, 58 "version=\"%s-%s\" prodversion=\"%s\" " 59 "requestid=\"{%s}\" lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" " 60 "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"", 61 prod_id.c_str(), 62 chrome_version.c_str(), // "version" 63 chrome_version.c_str(), // "prodversion" 64 base::GenerateGUID().c_str(), // "requestid" 65 chrome::OmahaQueryParams::GetLang(), // "lang", 66 chrome::OmahaQueryParams::GetChannelString(), // "updaterchannel" 67 chrome::OmahaQueryParams::GetChannelString(), // "prodchannel" 68 chrome::OmahaQueryParams::GetOS(), // "os" 69 chrome::OmahaQueryParams::GetArch(), // "arch" 70 chrome::OmahaQueryParams::GetNaclArch()); // "nacl_arch" 71 #if defined(OS_WIN) 72 const bool is_wow64(base::win::OSInfo::GetInstance()->wow64_status() == 73 base::win::OSInfo::WOW64_ENABLED); 74 if (is_wow64) 75 base::StringAppendF(&request, " wow64=\"1\""); 76 #endif 77 base::StringAppendF(&request, ">"); 78 79 // HW platform information. 80 base::StringAppendF(&request, 81 "<hw physmemory=\"%d\"/>", 82 GetPhysicalMemoryGB()); // "physmem" in GB. 83 84 // OS version and platform information. 85 base::StringAppendF( 86 &request, 87 "<os platform=\"%s\" version=\"%s\" arch=\"%s\"/>", 88 chrome::VersionInfo().OSType().c_str(), // "platform" 89 base::SysInfo().OperatingSystemVersion().c_str(), // "version" 90 base::SysInfo().OperatingSystemArchitecture().c_str()); // "arch" 91 92 // The actual payload of the request. 93 base::StringAppendF(&request, "%s</request>", request_body.c_str()); 94 95 return request; 96 } 97 98 net::URLFetcher* SendProtocolRequest( 99 const GURL& url, 100 const std::string& protocol_request, 101 net::URLFetcherDelegate* url_fetcher_delegate, 102 net::URLRequestContextGetter* url_request_context_getter) { 103 net::URLFetcher* url_fetcher(net::URLFetcher::Create( 104 0, url, net::URLFetcher::POST, url_fetcher_delegate)); 105 106 url_fetcher->SetUploadData("application/xml", protocol_request); 107 url_fetcher->SetRequestContext(url_request_context_getter); 108 url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 109 net::LOAD_DO_NOT_SAVE_COOKIES | 110 net::LOAD_DISABLE_CACHE); 111 url_fetcher->SetAutomaticallyRetryOn5xx(false); 112 url_fetcher->Start(); 113 114 return url_fetcher; 115 } 116 117 bool FetchSuccess(const net::URLFetcher& fetcher) { 118 return GetFetchError(fetcher) == 0; 119 } 120 121 int GetFetchError(const net::URLFetcher& fetcher) { 122 const net::URLRequestStatus::Status status(fetcher.GetStatus().status()); 123 switch (status) { 124 case net::URLRequestStatus::IO_PENDING: 125 case net::URLRequestStatus::CANCELED: 126 // Network status is a small positive number. 127 return status; 128 129 case net::URLRequestStatus::SUCCESS: { 130 // Response codes are positive numbers, greater than 100. 131 const int response_code(fetcher.GetResponseCode()); 132 if (response_code == 200) 133 return 0; 134 else 135 return response_code ? response_code : -1; 136 } 137 138 case net::URLRequestStatus::FAILED: { 139 // Network errors are small negative numbers. 140 const int error = fetcher.GetStatus().error(); 141 return error ? error : -1; 142 } 143 144 default: 145 return -1; 146 } 147 } 148 149 bool HasDiffUpdate(const CrxUpdateItem* update_item) { 150 return !update_item->crx_diffurls.empty(); 151 } 152 153 bool IsHttpServerError(int status_code) { 154 return 500 <= status_code && status_code < 600; 155 } 156 157 bool DeleteFileAndEmptyParentDirectory(const base::FilePath& filepath) { 158 if (!base::DeleteFile(filepath, false)) 159 return false; 160 161 const base::FilePath dirname(filepath.DirName()); 162 if (!base::IsDirectoryEmpty(dirname)) 163 return true; 164 165 return base::DeleteFile(dirname, false); 166 } 167 168 // Produces an extension-like friendly id. 169 std::string HexStringToID(const std::string& hexstr) { 170 std::string id; 171 for (size_t i = 0; i < hexstr.size(); ++i) { 172 int val = 0; 173 if (base::HexStringToInt( 174 base::StringPiece(hexstr.begin() + i, hexstr.begin() + i + 1), 175 &val)) { 176 id.append(1, val + 'a'); 177 } else { 178 id.append(1, 'a'); 179 } 180 } 181 DCHECK(extensions::Extension::IdIsValid(id)); 182 return id; 183 } 184 185 std::string GetCrxComponentID(const CrxComponent& component) { 186 return HexStringToID(StringToLowerASCII( 187 base::HexEncode(&component.pk_hash[0], component.pk_hash.size() / 2))); 188 } 189 190 } // namespace component_updater 191