1 // Copyright 2016 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 #ifndef CHROME_INSTALL_STATIC_INSTALL_DETAILS_H_ 6 #define CHROME_INSTALL_STATIC_INSTALL_DETAILS_H_ 7 8 #include <windows.h> 9 10 #include <memory> 11 #include <string> 12 13 #include "chrome/install_static/install_constants.h" 14 #include "chrome/install_static/install_modes.h" 15 #include "chrome/install_static/install_util.h" 16 17 namespace install_static { 18 19 class PrimaryInstallDetails; 20 class ScopedInstallDetails; 21 22 // The origin of the active channel. 23 enum class ChannelOrigin { 24 kInstallMode, // The channel dictated by the install mode. 25 kAdditionalParameters, // The legacy "ap" value. 26 kPolicy, // The updater's "TargetChannel" policy. 27 }; 28 29 // Details relating to how Chrome is installed. This class and 30 // PrimaryInstallDetails (below) are used in tandem so that one instance of the 31 // latter may be initialized early during process startup and then shared with 32 // other modules in the process. For example, chrome_elf creates the instance 33 // for a Chrome process and exports a GetInstallDetailsPayload function used by 34 // chrome.exe and chrome.dll to create their own module-specific instances 35 // referring to the same underlying payload. See install_modes.h for a gentle 36 // introduction to such terms as "brand" and "mode". 37 class InstallDetails { 38 public: 39 // A POD-struct containing the underlying data for an InstallDetails 40 // instance. Multiple InstallDetails instances (e.g., one per module in a 41 // process) share a single underlying Payload. 42 struct Payload { 43 // The size (in bytes) of this structure. This serves to verify that all 44 // modules in a process have the same definition of the struct. 45 size_t size; 46 47 // The compile-time version of the product at the time that the process's 48 // primary module was built. This is used to detect version skew across 49 // modules in the process. 50 const char* product_version; 51 52 // The brand-specific install mode for this install; see kInstallModes. 53 const InstallConstants* mode; 54 55 // The friendly name of this Chrome's channel, or an empty string if the 56 // brand does not integrate with Google Update. 57 const wchar_t* channel; 58 59 // The string length of |channel| (not including the string terminator). 60 size_t channel_length; 61 62 // The origin of the |channel| value. Install modes that use the 63 // ADDITIONAL_PARAMETERS channel strategy may determine the channel by 64 // either the "ap" value (kAdditionalParameters) or by an administrative 65 // policy override (kPolicy). For all other install modes, the channel is 66 // dictated by the mode itself (kInstallMode). 67 ChannelOrigin channel_origin; 68 69 // The "ap" (additional parameters) value read from Chrome's ClientState key 70 // during process startup. 71 const wchar_t* update_ap; 72 73 // The "name" value read from Chrome's ClientState\cohort key during process 74 // startup. 75 const wchar_t* update_cohort_name; 76 77 // True if installed in C:\Program Files{, {x86)}; otherwise, false. 78 bool system_level; 79 }; 80 81 InstallDetails(const InstallDetails&) = delete; 82 InstallDetails(InstallDetails&&) = delete; 83 InstallDetails& operator=(const InstallDetails&) = delete; 84 virtual ~InstallDetails() = default; 85 86 // Returns the instance for this module. 87 static const InstallDetails& Get(); 88 89 // This mode's index into the brand's array of install modes. This will match 90 // a brand-specific InstallConstantIndex enumerator. install_mode_index()91 int install_mode_index() const { return payload_->mode->index; } 92 93 // Returns true if the current mode is the brand's primary install mode rather 94 // than one of its secondary modes (e.g., canary Chrome). is_primary_mode()95 bool is_primary_mode() const { return install_mode_index() == 0; } 96 97 // Returns the installer command-line switch that selects the current mode. install_switch()98 const char* install_switch() const { return payload_->mode->install_switch; } 99 100 // The mode's install suffix (e.g., " SxS" for canary Chrome), or an empty 101 // string for a brand's primary install mode. install_suffix()102 const wchar_t* install_suffix() const { 103 return payload_->mode->install_suffix; 104 } 105 106 // The mode's logo suffix (e.g., "Canary" for canary Chrome), or an empty 107 // string for a brand's primary install mode. logo_suffix()108 const wchar_t* logo_suffix() const { return payload_->mode->logo_suffix; } 109 110 // Returns the full name of the installed product (e.g. "Chrome SxS" for 111 // canary chrome). install_full_name()112 std::wstring install_full_name() const { 113 return std::wstring(kProductPathName, kProductPathNameLength) 114 .append(install_suffix()); 115 } 116 mode()117 const InstallConstants& mode() const { return *payload_->mode; } 118 119 // The app GUID with which this mode is registered with Google Update, or an 120 // empty string if this brand does not integrate with Google Update. app_guid()121 const wchar_t* app_guid() const { return payload_->mode->app_guid; } 122 123 // The toast activator CLSID with which Chrome is registered with the Windows 124 // OS. toast_activator_clsid()125 const CLSID& toast_activator_clsid() const { 126 return payload_->mode->toast_activator_clsid; 127 } 128 129 // The CLSID of the COM server that provides silent elevation functionality. elevator_clsid()130 const CLSID& elevator_clsid() const { return payload_->mode->elevator_clsid; } 131 132 // The IID and the TypeLib of the IElevator interface that provides silent 133 // elevation functionality. elevator_iid()134 const IID& elevator_iid() const { return payload_->mode->elevator_iid; } 135 136 // Returns the unsuffixed portion of the AppUserModelId. The AppUserModelId is 137 // used to group an app's windows together on the Windows taskbar along with 138 // its corresponding shortcuts; see 139 // https://msdn.microsoft.com/library/windows/desktop/dd378459.aspx for more 140 // information. Use ShellUtil::GetBrowserModelId to get the suffixed value -- 141 // it is almost never correct to use the unsuffixed (base) portion of this id 142 // directly. base_app_id()143 const wchar_t* base_app_id() const { return payload_->mode->base_app_id; } 144 145 // True if the mode supports installation at system-level. supports_system_level()146 bool supports_system_level() const { 147 return payload_->mode->supports_system_level; 148 } 149 150 // Returns the resource id of this mode's main application icon. app_icon_resource_id()151 int32_t app_icon_resource_id() const { 152 return payload_->mode->app_icon_resource_id; 153 } 154 155 // The install's update channel, or an empty string if the brand does not 156 // integrate with Google Update. channel()157 std::wstring channel() const { 158 return std::wstring(payload_->channel, payload_->channel_length); 159 } 160 161 // The origin of a ChannelStrategy::ADDITIONAL_PARAMETERS install mode's 162 // channel, or kInstallMode. channel_origin()163 ChannelOrigin channel_origin() const { return payload_->channel_origin; } 164 165 // Returns the "ap" (additional parameters) value read from Chrome's 166 // ClientState key during process startup. update_ap()167 std::wstring update_ap() const { 168 return payload_->update_ap ? std::wstring(payload_->update_ap) 169 : std::wstring(); 170 } 171 172 // Returns the "name" value read from Chrome's ClientState\cohort key during 173 // process startup. update_cohort_name()174 std::wstring update_cohort_name() const { 175 return payload_->update_cohort_name 176 ? std::wstring(payload_->update_cohort_name) 177 : std::wstring(); 178 } 179 system_level()180 bool system_level() const { return payload_->system_level; } 181 182 // Returns the path to the installation's ClientState registry key. This 183 // registry key is used to hold various installation-related values, including 184 // an indication of consent for usage stats. 185 std::wstring GetClientStateKeyPath() const; 186 187 // Returns the path to the installation's ClientStateMedium registry key. This 188 // registry key is used to hold various installation-related values, including 189 // an indication of consent for usage stats for a system-level install. 190 std::wstring GetClientStateMediumKeyPath() const; 191 192 // Returns true if there is an indication of a mismatch between the primary 193 // module and this module. 194 bool VersionMismatch() const; 195 196 // Sets the instance for the process. This must be called only once per 197 // process during startup. 198 static void SetForProcess(std::unique_ptr<PrimaryInstallDetails> details); 199 200 // Returns a pointer to the module's payload so that it may be shared with 201 // other modules in the process. 202 static const Payload* GetPayload(); 203 204 // Initializes this module's instance with the payload from the process's 205 // primary module (the one that used SetForProcess). 206 static void InitializeFromPayload(const Payload* payload); 207 208 protected: InstallDetails(const Payload * payload)209 explicit InstallDetails(const Payload* payload) : payload_(payload) {} default_channel_name()210 const wchar_t* default_channel_name() const { 211 return payload_->mode->default_channel_name; 212 } 213 214 private: 215 friend class ScopedInstallDetails; 216 217 // Swaps this module's instance with a provided instance, returning the 218 // module's previous instance. 219 static std::unique_ptr<const InstallDetails> Swap( 220 std::unique_ptr<const InstallDetails> install_details); 221 222 const Payload* const payload_; 223 }; 224 225 // A kind of InstallDetails that owns its payload. A single instance of this 226 // class is initialized early on in process startup (e.g., in chrome_elf for the 227 // case of chrome.exe; see InitializeProductDetailsForPrimaryModule). Its 228 // underlying data (its "payload") is shared with other interested modules in 229 // the process. 230 class PrimaryInstallDetails : public InstallDetails { 231 public: 232 PrimaryInstallDetails(); 233 PrimaryInstallDetails(const PrimaryInstallDetails&) = delete; 234 PrimaryInstallDetails(PrimaryInstallDetails&&) = delete; 235 PrimaryInstallDetails& operator=(const PrimaryInstallDetails&) = delete; 236 set_mode(const InstallConstants * mode)237 void set_mode(const InstallConstants* mode) { payload_.mode = mode; } set_channel(const std::wstring & channel)238 void set_channel(const std::wstring& channel) { 239 channel_ = channel; 240 payload_.channel = channel_.c_str(); 241 payload_.channel_length = channel_.size(); 242 } set_channel_origin(ChannelOrigin origin)243 void set_channel_origin(ChannelOrigin origin) { 244 payload_.channel_origin = origin; 245 } set_update_ap(const std::wstring & update_ap)246 void set_update_ap(const std::wstring& update_ap) { 247 update_ap_ = update_ap; 248 payload_.update_ap = update_ap_.c_str(); 249 } set_update_cohort_name(const std::wstring & update_cohort_name)250 void set_update_cohort_name(const std::wstring& update_cohort_name) { 251 update_cohort_name_ = update_cohort_name; 252 payload_.update_cohort_name = update_cohort_name_.c_str(); 253 } set_system_level(bool system_level)254 void set_system_level(bool system_level) { 255 payload_.system_level = system_level; 256 } 257 258 private: 259 std::wstring channel_; 260 std::wstring update_ap_; 261 std::wstring update_cohort_name_; 262 Payload payload_ = Payload(); 263 }; 264 265 } // namespace install_static 266 267 #endif // CHROME_INSTALL_STATIC_INSTALL_DETAILS_H_ 268