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