aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.WixBA/UpdateViewModel.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/WixToolset.WixBA/UpdateViewModel.cs207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/WixToolset.WixBA/UpdateViewModel.cs b/src/WixToolset.WixBA/UpdateViewModel.cs
new file mode 100644
index 00000000..6b60112c
--- /dev/null
+++ b/src/WixToolset.WixBA/UpdateViewModel.cs
@@ -0,0 +1,207 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.UX
4{
5 using System;
6 using System.ComponentModel;
7 using System.Windows.Input;
8 using WixToolset.Bootstrapper;
9
10 /// <summary>
11 /// The states of the update view model.
12 /// </summary>
13 public enum UpdateState
14 {
15 Unknown,
16 Initializing,
17 Checking,
18 Current,
19 Available,
20 Failed,
21 }
22
23 /// <summary>
24 /// The model of the update view.
25 /// </summary>
26 public class UpdateViewModel : PropertyNotifyBase
27 {
28 private RootViewModel root;
29 private UpdateState state;
30 private ICommand updateCommand;
31 private string updateVersion;
32 private string updateChanges;
33
34
35 public UpdateViewModel(RootViewModel root)
36 {
37 this.root = root;
38 WixBA.Model.Bootstrapper.DetectUpdateBegin += this.DetectUpdateBegin;
39 WixBA.Model.Bootstrapper.DetectUpdate += this.DetectUpdate;
40 WixBA.Model.Bootstrapper.DetectUpdateComplete += this.DetectUpdateComplete;
41
42 this.root.PropertyChanged += new PropertyChangedEventHandler(this.RootPropertyChanged);
43
44 this.State = UpdateState.Initializing;
45 }
46
47 void RootPropertyChanged(object sender, PropertyChangedEventArgs e)
48 {
49 if ("InstallState" == e.PropertyName)
50 {
51 base.OnPropertyChanged("CanUpdate");
52 }
53 }
54
55 public bool CheckingEnabled
56 {
57 get { return this.State == UpdateState.Initializing || this.State == UpdateState.Checking; }
58 }
59
60 public bool CanUpdate
61 {
62 get
63 {
64 switch(this.root.InstallState)
65 {
66 case InstallationState.Waiting:
67 case InstallationState.Applied:
68 case InstallationState.Failed:
69 return this.IsUpdateAvailable;
70 default:
71 return false;
72 }
73 }
74 }
75
76 public ICommand UpdateCommand
77 {
78 get
79 {
80 if (this.updateCommand == null)
81 {
82 this.updateCommand = new RelayCommand(param => WixBA.Plan(LaunchAction.UpdateReplace), param => this.CanUpdate);
83 }
84
85 return this.updateCommand;
86 }
87 }
88
89 public bool IsUpdateAvailable
90 {
91 get { return this.State == UpdateState.Available; }
92 }
93
94 /// <summary>
95 /// Gets and sets the state of the update view model.
96 /// </summary>
97 public UpdateState State
98 {
99 get
100 {
101 return this.state;
102 }
103
104 set
105 {
106 if (this.state != value)
107 {
108 this.state = value;
109 base.OnPropertyChanged("State");
110 base.OnPropertyChanged("CanUpdate");
111 base.OnPropertyChanged("CheckingEnabled");
112 base.OnPropertyChanged("IsUpdateAvailable");
113 }
114 }
115 }
116 /// <summary>
117 /// The version of an available update.
118 /// </summary>
119 public string UpdateVersion
120 {
121 get
122 {
123 return updateVersion;
124 }
125 set
126 {
127 if (this.updateVersion != value)
128 {
129 this.updateVersion = value;
130 base.OnPropertyChanged("UpdateVersion");
131 }
132 }
133 }
134
135 /// <summary>
136 /// The changes in the available update.
137 /// </summary>
138 public string UpdateChanges
139 {
140 get
141 {
142 return updateChanges;
143 }
144 set
145 {
146 if (this.updateChanges != value)
147 {
148 this.updateChanges = value;
149 base.OnPropertyChanged("UpdateChanges");
150 }
151 }
152 }
153
154 private void DetectUpdateBegin(object sender, Bootstrapper.DetectUpdateBeginEventArgs e)
155 {
156 // Don't check for updates if:
157 // the first check failed (no retry)
158 // if we are being run as an uninstall
159 // if we are not under a full UI.
160 if ((UpdateState.Failed != this.State) && (LaunchAction.Uninstall != WixBA.Model.Command.Action) && (Display.Full == WixBA.Model.Command.Display))
161 {
162 this.State = UpdateState.Checking;
163 e.Skip = false;
164 }
165 }
166
167 private void DetectUpdate(object sender, Bootstrapper.DetectUpdateEventArgs e)
168 {
169 // The list of updates is sorted in descending version, so the first callback should be the largest update available.
170 // This update should be either larger than ours (so we are out of date), the same as ours (so we are current)
171 // or smaller than ours (we have a private build). If we really wanted to, we could leave the e.StopProcessingUpdates alone and
172 // enumerate all of the updates.
173 WixBA.Model.Engine.Log(LogLevel.Verbose, String.Format("Potential update v{0} from '{1}'; current version: v{2}", e.Version, e.UpdateLocation, WixBA.Model.Version));
174 if (e.Version > WixBA.Model.Version)
175 {
176 WixBA.Model.Engine.SetUpdate(null, e.UpdateLocation, e.Size, UpdateHashType.None, null);
177 this.UpdateVersion = String.Concat("v", e.Version.ToString());
178 string changesFormat = @"<body style='overflow: auto;'>{0}</body>";
179 this.UpdateChanges = String.Format(changesFormat, e.Content);
180 this.State = UpdateState.Available;
181 }
182 else
183 {
184 this.State = UpdateState.Current;
185 }
186 e.StopProcessingUpdates = true;
187 }
188
189 private void DetectUpdateComplete(object sender, Bootstrapper.DetectUpdateCompleteEventArgs e)
190 {
191 // Failed to process an update, allow the existing bundle to still install.
192 if ((UpdateState.Failed != this.State) && !Hresult.Succeeded(e.Status))
193 {
194 this.State = UpdateState.Failed;
195 WixBA.Model.Engine.Log(LogLevel.Verbose, String.Format("Failed to locate an update, status of 0x{0:X8}, updates disabled.", e.Status));
196 e.IgnoreError = true;
197 }
198 // If we are uninstalling, we don't want to check or show an update
199 // If we are checking, then the feed didn't find any valid enclosures
200 // If we are initializing, we're either uninstalling or not a full UI
201 else if ((LaunchAction.Uninstall == WixBA.Model.Command.Action) || (UpdateState.Initializing == this.State) || (UpdateState.Checking == this.State))
202 {
203 this.State = UpdateState.Unknown;
204 }
205 }
206 }
207}