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