Merge lp:~mandel/ubuntuone-windows-installer/windows_selfupdate into lp:ubuntuone-windows-installer/beta

Proposed by Manuel de la Peña
Status: Merged
Approved by: Stuart Colville
Approved revision: 12
Merged at revision: 38
Proposed branch: lp:~mandel/ubuntuone-windows-installer/windows_selfupdate
Merge into: lp:ubuntuone-windows-installer/beta
Diff against target: 1290 lines (+1163/-0)
15 files modified
lib/DotUpdater/license.txt (+49/-0)
src/Canonical.UbuntuOne.Common.Tests/Canonical.UbuntuOne.Common.Tests.csproj (+5/-0)
src/Canonical.UbuntuOne.Common.Tests/Update/UpdaterFixture.cs (+198/-0)
src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj (+29/-0)
src/Canonical.UbuntuOne.Common/Properties/AssemblyInfo.cs (+3/-0)
src/Canonical.UbuntuOne.Common/Update/DotLogger.cs (+48/-0)
src/Canonical.UbuntuOne.Common/Update/DotUpdaterWrapper.cs (+70/-0)
src/Canonical.UbuntuOne.Common/Update/Enumerators.cs (+31/-0)
src/Canonical.UbuntuOne.Common/Update/IDotUpdaterWrapper.cs (+65/-0)
src/Canonical.UbuntuOne.Common/Update/IUpdateView.cs (+78/-0)
src/Canonical.UbuntuOne.Common/Update/IUpdater.cs (+55/-0)
src/Canonical.UbuntuOne.Common/Update/SelfUpdateException.cs (+46/-0)
src/Canonical.UbuntuOne.Common/Update/UpdateResources.Designer.cs (+117/-0)
src/Canonical.UbuntuOne.Common/Update/UpdateResources.resx (+138/-0)
src/Canonical.UbuntuOne.Common/Update/Updater.cs (+231/-0)
To merge this branch: bzr merge lp:~mandel/ubuntuone-windows-installer/windows_selfupdate
Reviewer Review Type Date Requested Status
Stuart Colville (community) Approve
Vincenzo Di Somma (community) Approve
Review via email: mp+30502@code.launchpad.net

Description of the change

This branch provides the initial code that will allows the windows package selfupdate. It currently uses DotUpdater but it has been wrapped with an interface for two reasons:

1. Low coupling with the DotUpdater lib.
2. Simplify testing with RhinoMocks.

To post a comment you must log in.
Revision history for this message
Vincenzo Di Somma (vds) wrote :

As usual builds and tests pass.

review: Approve
Revision history for this message
Stuart Colville (muffinresearch) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'lib/DotUpdater'
2=== added file 'lib/DotUpdater/DotUpdater.dll'
3Binary files lib/DotUpdater/DotUpdater.dll 1970-01-01 00:00:00 +0000 and lib/DotUpdater/DotUpdater.dll 2010-07-21 10:14:43 +0000 differ
4=== added file 'lib/DotUpdater/Interop.WindowsInstaller.dll'
5Binary files lib/DotUpdater/Interop.WindowsInstaller.dll 1970-01-01 00:00:00 +0000 and lib/DotUpdater/Interop.WindowsInstaller.dll 2010-07-21 10:14:43 +0000 differ
6=== added file 'lib/DotUpdater/license.txt'
7--- lib/DotUpdater/license.txt 1970-01-01 00:00:00 +0000
8+++ lib/DotUpdater/license.txt 2010-07-21 10:14:43 +0000
9@@ -0,0 +1,49 @@
10+Microsoft Public License (Ms-PL)
11+
12+This license governs use of the accompanying software. If you use the software, you accept this license.
13+If you do not accept the license, do not use the software.
14+
15+1. Definitions
16+
17+The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning
18+here as under U.S. copyright law.
19+
20+A "contribution" is the original software, or any additions or changes to the software.
21+
22+A "contributor" is any person that distributes its contribution under this license.
23+
24+"Licensed patents" are a contributor's patent claims that read directly on its contribution.
25+
26+2. Grant of Rights
27+
28+(A) Copyright Grant- Subject to the terms of this license, including the license conditions and
29+limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free
30+copyright license to reproduce its contribution, prepare derivative works of its contribution,
31+and distribute its contribution or any derivative works that you create.
32+
33+(B) Patent Grant- Subject to the terms of this license, including the license conditions and
34+limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free
35+license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or
36+otherwise dispose of its contribution in the software or derivative works of the contribution in
37+the software.
38+
39+3. Conditions and Limitations
40+
41+(A) No Trademark License- This license does not grant you rights to use any contributors' name,
42+logo, or trademarks.
43+
44+(B) If you bring a patent claim against any contributor over patents that you claim are infringed
45+by the software, your patent license from such contributor to the software ends automatically.
46+
47+(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark,
48+and attribution notices that are present in the software.
49+
50+(D) If you distribute any portion of the software in source code form, you may do so only under this
51+license by including a complete copy of this license with your distribution. If you distribute any
52+portion of the software in compiled or object code form, you may only do so under a license that complies
53+with this license.
54+
55+(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express
56+warranties, guarantees or conditions. You may have additional consumer rights under your local laws
57+which this license cannot change. To the extent permitted under your local laws, the contributors exclude
58+the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
59\ No newline at end of file
60
61=== modified file 'src/Canonical.UbuntuOne.Common.Tests/Canonical.UbuntuOne.Common.Tests.csproj'
62--- src/Canonical.UbuntuOne.Common.Tests/Canonical.UbuntuOne.Common.Tests.csproj 2010-07-13 15:37:56 +0000
63+++ src/Canonical.UbuntuOne.Common.Tests/Canonical.UbuntuOne.Common.Tests.csproj 2010-07-21 10:14:43 +0000
64@@ -35,12 +35,17 @@
65 <Compile Include="Aop\DebugLogAfterCallInterceptorFixture.cs" />
66 <Compile Include="Aop\DebugLogAfterThrowInterceptorFixture.cs" />
67 <Compile Include="Properties\AssemblyInfo.cs" />
68+ <Compile Include="Update\UpdaterFixture.cs" />
69 <Compile Include="Validation\ArgumentValidationFixture.cs" />
70 <Compile Include="Validation\EqualityExtensionsValidation.cs" />
71 <Compile Include="Validation\MultiExceptionFixture.cs" />
72 <Compile Include="Validation\ValidationExtensionsFixture.cs" />
73 </ItemGroup>
74 <ItemGroup>
75+ <Reference Include="DotUpdater, Version=0.2.0.4, Culture=neutral, processorArchitecture=MSIL">
76+ <SpecificVersion>False</SpecificVersion>
77+ <HintPath>..\..\lib\DotUpdater\DotUpdater.dll</HintPath>
78+ </Reference>
79 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
80 <SpecificVersion>False</SpecificVersion>
81 <HintPath>..\..\lib\log4net\log4net.dll</HintPath>
82
83=== added directory 'src/Canonical.UbuntuOne.Common.Tests/Update'
84=== added file 'src/Canonical.UbuntuOne.Common.Tests/Update/UpdaterFixture.cs'
85--- src/Canonical.UbuntuOne.Common.Tests/Update/UpdaterFixture.cs 1970-01-01 00:00:00 +0000
86+++ src/Canonical.UbuntuOne.Common.Tests/Update/UpdaterFixture.cs 2010-07-21 10:14:43 +0000
87@@ -0,0 +1,198 @@
88+/**
89+ * Copyright 2010 Canonical Ltd.
90+ *
91+ * This file is part of UbuntuOne on Windows.
92+ *
93+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
94+ * it under the terms of the GNU Lesser General Public License version
95+ * as published by the Free Software Foundation.
96+ *
97+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
98+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
99+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100+ * GNU Lesser General Public License for more details.
101+ *
102+ * You should have received a copy of the GNU Lesser General Public License
103+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
104+ *
105+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
106+ */
107+using Canonical.UbuntuOne.Common.Update;
108+using log4net;
109+using Microsoft.ApplicationBlocks.Updater;
110+using NUnit.Framework;
111+using DotUpdater;
112+using Rhino.Mocks;
113+using Updater = Canonical.UbuntuOne.Common.Update.Updater;
114+
115+
116+namespace Canonical.UbuntuOne.Common.Tests.Update
117+{
118+ [TestFixture]
119+ public class UpdaterFixture
120+ {
121+ #region Setup
122+
123+ private Logger _dotLogger;
124+ private ILog _logger;
125+ private MockRepository _mocks;
126+ private Updater _updater;
127+ private IUpdateView _view;
128+ private IDotUpdaterWrapper _dotUpdaterWrapper;
129+
130+ [SetUp]
131+ public void Setup()
132+ {
133+
134+ _mocks = new MockRepository();
135+ _logger = _mocks.DynamicMock<ILog>();
136+ _dotLogger = _mocks.DynamicMock<Logger>();
137+ _dotUpdaterWrapper = _mocks.DynamicMock<IDotUpdaterWrapper>();
138+ _view = _mocks.DynamicMock<IUpdateView>();
139+ _updater = new Updater
140+ {
141+ Logger = _logger,
142+ UpdateView = _view,
143+ DotUpdater = _dotUpdaterWrapper
144+ };
145+ }
146+
147+
148+ #endregion
149+
150+ #region Tests
151+
152+ [Test]
153+ public void DisposeTest()
154+ {
155+ using(_mocks.Record())
156+ {
157+ Expect.Call(() => _dotUpdaterWrapper.Dispose())
158+ .Repeat.Once();
159+ }
160+ using(_mocks.Playback())
161+ {
162+ using (_updater)
163+ {
164+ // do something
165+ }
166+ }
167+ }
168+
169+ [Test]
170+ public void UpdatesArePresentFalseTest()
171+ {
172+ using(_mocks.Record())
173+ {
174+ Expect.Call(_dotUpdaterWrapper.CheckForUpdates())
175+ .Return(null)
176+ .Repeat.Once();
177+ }
178+
179+ using(_mocks.Playback())
180+ {
181+ Assert.IsFalse(_updater.UpdatesArePresent());
182+ }
183+ }
184+
185+ [Test]
186+ public void UpdatesArePresentTrueTest()
187+ {
188+ using(_mocks.Record())
189+ {
190+ Expect.Call(_dotUpdaterWrapper.CheckForUpdates())
191+ .Return(new UpdaterTask("", "wewe", new string[0], "code", new string[0]))
192+ .Repeat.Once();
193+ }
194+
195+ using (_mocks.Playback())
196+ {
197+ Assert.IsTrue(_updater.UpdatesArePresent());
198+ }
199+ }
200+
201+ [Test]
202+ [ExpectedException(typeof(SelfUpdateException))]
203+ public void PerformUpdateNoCheckDoneTest()
204+ {
205+ _updater.PerformUpdate();
206+ }
207+
208+ [Test]
209+ [ExpectedException(typeof(SelfUpdateException))]
210+ public void PerformUpdateCheckDoneNoUpdateTest()
211+ {
212+ using (_mocks.Record())
213+ {
214+ Expect.Call(_dotUpdaterWrapper.CheckForUpdates())
215+ .Return(null)
216+ .Repeat.Once();
217+ }
218+ using (_mocks.Playback())
219+ {
220+ var areAvialable = _updater.UpdatesArePresent();
221+ Assert.IsFalse(areAvialable);
222+ _updater.PerformUpdate();
223+ }
224+ }
225+
226+ [Test]
227+ public void PerformUpdateNotDownloadedNotDownloadingTest()
228+ {
229+ var task = _mocks.DynamicMock<UpdaterTask>("", "wewe", new string[0], "code", new string[0]);
230+ using(_mocks.Record())
231+ {
232+ Expect.Call(_dotUpdaterWrapper.CheckForUpdates())
233+ .Return(task)
234+ .Repeat.Once();
235+
236+ Expect.Call(() => _dotUpdaterWrapper.BeginDownload(task))
237+ .Repeat.Once();
238+
239+ // ensure the handlers have been registered
240+ _dotUpdaterWrapper.OnDownloadProgress += _view.DownloadProgressHandler;
241+
242+ _dotUpdaterWrapper.OnDownloadCompleted += _view.DownloadUpdateCompleted;
243+ _dotUpdaterWrapper.OnDownloadCompleted += null;
244+ LastCall.IgnoreArguments();
245+
246+ _dotUpdaterWrapper.OnDownloadError += _view.DownloadErrorHandler;
247+ _dotUpdaterWrapper.OnDownloadError += null;
248+ LastCall.IgnoreArguments();
249+
250+ }
251+ using (_mocks.Playback())
252+ {
253+ if(_updater.UpdatesArePresent())
254+ {
255+ _updater.PerformUpdate();
256+ }
257+ }
258+ }
259+
260+ [Test]
261+ [ExpectedException(typeof(SelfUpdateException))]
262+ public void PerformUpdateDownloadExceptionTest()
263+ {
264+ var task = _mocks.DynamicMock<UpdaterTask>("", "wewe", new string[0], "code", new string[0]);
265+ using (_mocks.Record())
266+ {
267+ Expect.Call(_dotUpdaterWrapper.CheckForUpdates())
268+ .Return(task)
269+ .Repeat.Once();
270+
271+ Expect.Call(() => _dotUpdaterWrapper.BeginDownload(task))
272+ .Throw(new UpdaterException(""));
273+ }
274+ using (_mocks.Playback())
275+ {
276+ if (_updater.UpdatesArePresent())
277+ {
278+ _updater.PerformUpdate();
279+ }
280+ }
281+ }
282+
283+ #endregion
284+ }
285+}
286
287=== modified file 'src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj'
288--- src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj 2010-07-13 15:37:56 +0000
289+++ src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj 2010-07-21 10:14:43 +0000
290@@ -67,6 +67,19 @@
291 <Compile Include="OperationContracts\ISyncFolders.cs" />
292 <Compile Include="OperationContracts\ISyncShares.cs" />
293 <Compile Include="Properties\AssemblyInfo.cs" />
294+ <Compile Include="Update\DotLogger.cs" />
295+ <Compile Include="Update\DotUpdaterWrapper.cs" />
296+ <Compile Include="Update\Enumerators.cs" />
297+ <Compile Include="Update\IDotUpdaterWrapper.cs" />
298+ <Compile Include="Update\IUpdateView.cs" />
299+ <Compile Include="Update\IUpdater.cs" />
300+ <Compile Include="Update\Updater.cs" />
301+ <Compile Include="Update\UpdateResources.Designer.cs">
302+ <AutoGen>True</AutoGen>
303+ <DesignTime>True</DesignTime>
304+ <DependentUpon>UpdateResources.resx</DependentUpon>
305+ </Compile>
306+ <Compile Include="Update\SelfUpdateException.cs" />
307 <Compile Include="Validation\ArgumentValidation.cs" />
308 <Compile Include="Validation\EqualityValidationExtensions.cs" />
309 <Compile Include="Validation\MultiException.cs" />
310@@ -75,6 +88,14 @@
311 <Compile Include="Validation\ValidationExtensions.cs" />
312 </ItemGroup>
313 <ItemGroup>
314+ <Reference Include="DotUpdater, Version=0.2.0.4, Culture=neutral, processorArchitecture=MSIL">
315+ <SpecificVersion>False</SpecificVersion>
316+ <HintPath>..\..\lib\DotUpdater\DotUpdater.dll</HintPath>
317+ </Reference>
318+ <Reference Include="Interop.WindowsInstaller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
319+ <SpecificVersion>False</SpecificVersion>
320+ <HintPath>..\..\lib\DotUpdater\Interop.WindowsInstaller.dll</HintPath>
321+ </Reference>
322 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
323 <SpecificVersion>False</SpecificVersion>
324 <HintPath>..\..\lib\log4net\log4net.dll</HintPath>
325@@ -92,6 +113,9 @@
326 <Reference Include="System.Runtime.Serialization">
327 </Reference>
328 <Reference Include="System.Xml" />
329+ <Reference Include="WindowsBase">
330+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
331+ </Reference>
332 </ItemGroup>
333 <ItemGroup>
334 <EmbeddedResource Include="Aop\AopResources.resx">
335@@ -99,6 +123,11 @@
336 <LastGenOutput>AopResources.Designer.cs</LastGenOutput>
337 <SubType>Designer</SubType>
338 </EmbeddedResource>
339+ <EmbeddedResource Include="Update\UpdateResources.resx">
340+ <Generator>ResXFileCodeGenerator</Generator>
341+ <LastGenOutput>UpdateResources.Designer.cs</LastGenOutput>
342+ <SubType>Designer</SubType>
343+ </EmbeddedResource>
344 </ItemGroup>
345 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
346 </Project>
347\ No newline at end of file
348
349=== modified file 'src/Canonical.UbuntuOne.Common/Properties/AssemblyInfo.cs'
350--- src/Canonical.UbuntuOne.Common/Properties/AssemblyInfo.cs 2010-07-04 11:53:55 +0000
351+++ src/Canonical.UbuntuOne.Common/Properties/AssemblyInfo.cs 2010-07-21 10:14:43 +0000
352@@ -34,3 +34,6 @@
353 // [assembly: AssemblyVersion("1.0.*")]
354 [assembly: AssemblyVersion("1.0.0.0")]
355 [assembly: AssemblyFileVersion("1.0.0.0")]
356+[assembly: InternalsVisibleTo("Canonical.UbuntuOne.Common.Tests")]
357+// add the internals to be visible to the Rhino mocks code
358+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
359\ No newline at end of file
360
361=== added directory 'src/Canonical.UbuntuOne.Common/Update'
362=== added file 'src/Canonical.UbuntuOne.Common/Update/DotLogger.cs'
363--- src/Canonical.UbuntuOne.Common/Update/DotLogger.cs 1970-01-01 00:00:00 +0000
364+++ src/Canonical.UbuntuOne.Common/Update/DotLogger.cs 2010-07-21 10:14:43 +0000
365@@ -0,0 +1,48 @@
366+/**
367+ * Copyright 2010 Canonical Ltd.
368+ *
369+ * This file is part of UbuntuOne on Windows.
370+ *
371+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
372+ * it under the terms of the GNU Lesser General Public License version
373+ * as published by the Free Software Foundation.
374+ *
375+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
378+ * GNU Lesser General Public License for more details.
379+ *
380+ * You should have received a copy of the GNU Lesser General Public License
381+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
382+ *
383+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
384+ */
385+using System;
386+using DotUpdater;
387+using log4net;
388+
389+namespace Canonical.UbuntuOne.Common.Update
390+{
391+ internal class DotLogger : Logger
392+ {
393+ private readonly ILog _logger = LogManager.GetLogger(typeof(Updater));
394+
395+ public override void LogWarning(string info)
396+ {
397+ _logger.Warn(info);
398+ base.LogWarning(info);
399+ }
400+
401+ public override void LogException(Exception e)
402+ {
403+ _logger.Error(e);
404+ base.LogException(e);
405+ }
406+
407+ public override void LogAndThrowException(Exception exception)
408+ {
409+ _logger.Error(exception);
410+ base.LogAndThrowException(exception);
411+ }
412+ }
413+}
414
415=== added file 'src/Canonical.UbuntuOne.Common/Update/DotUpdaterWrapper.cs'
416--- src/Canonical.UbuntuOne.Common/Update/DotUpdaterWrapper.cs 1970-01-01 00:00:00 +0000
417+++ src/Canonical.UbuntuOne.Common/Update/DotUpdaterWrapper.cs 2010-07-21 10:14:43 +0000
418@@ -0,0 +1,70 @@
419+/**
420+ * Copyright 2010 Canonical Ltd.
421+ *
422+ * This file is part of UbuntuOne on Windows.
423+ *
424+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
425+ * it under the terms of the GNU Lesser General Public License version
426+ * as published by the Free Software Foundation.
427+ *
428+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
429+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
430+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
431+ * GNU Lesser General Public License for more details.
432+ *
433+ * You should have received a copy of the GNU Lesser General Public License
434+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
435+ *
436+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
437+ */
438+using System;
439+using DotUpdater;
440+using Microsoft.ApplicationBlocks.Updater;
441+
442+namespace Canonical.UbuntuOne.Common.Update
443+{
444+ internal class DotUpdaterWrapper : IDotUpdaterWrapper
445+ {
446+ #region Events
447+
448+ public event EventHandler<TaskEventArgs> OnDownloadCompleted;
449+ public event EventHandler<DownloadTaskProgressEventArgs> OnDownloadProgress;
450+ public event EventHandler<DownloadTaskErrorEventArgs> OnDownloadError;
451+
452+ #endregion
453+
454+ #region Variables
455+
456+ private DotUpdater.Updater _updater;
457+
458+ #endregion
459+
460+ public DotUpdaterWrapper(Logger logger, string rss)
461+ {
462+ _updater = new DotUpdater.Updater(logger, rss);
463+ OnDownloadCompleted = _updater.OnDownloadCompleted;
464+ OnDownloadProgress = _updater.OnDownloadProgress;
465+ OnDownloadError = _updater.OnDownloadError;
466+ }
467+
468+ public UpdaterTask CheckForUpdates()
469+ {
470+ return _updater.CheckForUpdates();
471+ }
472+
473+ public void Install(UpdaterTask task)
474+ {
475+ _updater.Install(task);
476+ }
477+
478+ public void BeginDownload(UpdaterTask task)
479+ {
480+ _updater.BeginDownload(task);
481+ }
482+
483+ public void Dispose()
484+ {
485+ _updater.Dispose();
486+ }
487+ }
488+}
489
490=== added file 'src/Canonical.UbuntuOne.Common/Update/Enumerators.cs'
491--- src/Canonical.UbuntuOne.Common/Update/Enumerators.cs 1970-01-01 00:00:00 +0000
492+++ src/Canonical.UbuntuOne.Common/Update/Enumerators.cs 2010-07-21 10:14:43 +0000
493@@ -0,0 +1,31 @@
494+/**
495+ * Copyright 2010 Canonical Ltd.
496+ *
497+ * This file is part of UbuntuOne on Windows.
498+ *
499+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
500+ * it under the terms of the GNU Lesser General Public License version
501+ * as published by the Free Software Foundation.
502+ *
503+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
506+ * GNU Lesser General Public License for more details.
507+ *
508+ * You should have received a copy of the GNU Lesser General Public License
509+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
510+ *
511+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
512+ */
513+namespace Canonical.UbuntuOne.Common.Update
514+{
515+ /// <summary>
516+ /// Enumerator that statest the different responses that a IUpdateConfirmation view
517+ /// can return.
518+ /// </summary>
519+ public enum UpdateConfirmation
520+ {
521+ YES,
522+ NO
523+ }
524+}
525
526=== added file 'src/Canonical.UbuntuOne.Common/Update/IDotUpdaterWrapper.cs'
527--- src/Canonical.UbuntuOne.Common/Update/IDotUpdaterWrapper.cs 1970-01-01 00:00:00 +0000
528+++ src/Canonical.UbuntuOne.Common/Update/IDotUpdaterWrapper.cs 2010-07-21 10:14:43 +0000
529@@ -0,0 +1,65 @@
530+/**
531+ * Copyright 2010 Canonical Ltd.
532+ *
533+ * This file is part of UbuntuOne on Windows.
534+ *
535+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
536+ * it under the terms of the GNU Lesser General Public License version
537+ * as published by the Free Software Foundation.
538+ *
539+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
542+ * GNU Lesser General Public License for more details.
543+ *
544+ * You should have received a copy of the GNU Lesser General Public License
545+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
546+ *
547+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
548+ */
549+using System;
550+using Microsoft.ApplicationBlocks.Updater;
551+
552+namespace Canonical.UbuntuOne.Common.Update
553+{
554+ /// <summary>
555+ /// Internal interface that is used as a wrapper for the DotUpdater so that it can be
556+ /// mock in the unit tests.
557+ /// </summary>
558+ internal interface IDotUpdaterWrapper : IDisposable
559+ {
560+ /// <summary>
561+ /// Event that is reaised when the download of an update has been completed.
562+ /// </summary>
563+ event EventHandler<TaskEventArgs> OnDownloadCompleted;
564+
565+ /// <summary>
566+ /// Event that is raised when there has been progress when downloading the update.
567+ /// </summary>
568+ event EventHandler<DownloadTaskProgressEventArgs> OnDownloadProgress;
569+
570+ /// <summary>
571+ /// Event that is raised when there has been an error with the download.
572+ /// </summary>
573+ event EventHandler<DownloadTaskErrorEventArgs> OnDownloadError;
574+
575+ /// <summary>
576+ /// Method that will connect to the server and will return a UpdaterTask if there is a possible
577+ /// update, if there are no updates available a null pointer will be returned.
578+ /// </summary>
579+ /// <returns>A null pointer if no updates are available or an update taks if there are.</returns>
580+ UpdaterTask CheckForUpdates();
581+
582+ /// <summary>
583+ /// Method that will install the given update.
584+ /// </summary>
585+ /// <param name="task">The taks that will be used to udpate.</param>
586+ void Install(UpdaterTask task);
587+
588+ /// <summary>
589+ /// Method that will being the download of a given update task.
590+ /// </summary>
591+ /// <param name="task">The taks that will have to be downloaded.</param>
592+ void BeginDownload(UpdaterTask task);
593+ }
594+}
595
596=== added file 'src/Canonical.UbuntuOne.Common/Update/IUpdateView.cs'
597--- src/Canonical.UbuntuOne.Common/Update/IUpdateView.cs 1970-01-01 00:00:00 +0000
598+++ src/Canonical.UbuntuOne.Common/Update/IUpdateView.cs 2010-07-21 10:14:43 +0000
599@@ -0,0 +1,78 @@
600+/**
601+ * Copyright 2010 Canonical Ltd.
602+ *
603+ * This file is part of UbuntuOne on Windows.
604+ *
605+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
606+ * it under the terms of the GNU Lesser General Public License version
607+ * as published by the Free Software Foundation.
608+ *
609+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
610+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
611+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
612+ * GNU Lesser General Public License for more details.
613+ *
614+ * You should have received a copy of the GNU Lesser General Public License
615+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
616+ *
617+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
618+ */
619+using Microsoft.ApplicationBlocks.Updater;
620+
621+namespace Canonical.UbuntuOne.Common.Update
622+{
623+ /// <summary>
624+ /// Interface that represents the view that will ask for a confirmation to the user
625+ /// regarding the update procedure.
626+ /// </summary>
627+ public interface IUpdateView
628+ {
629+ /// <summary>
630+ /// This method should prompt some kind of confirmation message to the user
631+ /// and return if he decided to update the application or not.
632+ /// </summary>
633+ /// <returns>The answer that the user provided.</returns>
634+ UpdateConfirmation AskForDownloadConfirmation();
635+
636+ /// <summary>
637+ /// This method should prompt some kind of confirmation to the user to close and install the update
638+ /// of the application.
639+ /// </summary>
640+ /// <returns>The answer that the suer provided.</returns>
641+ UpdateConfirmation AskForCloseAnInstallConfirmation();
642+
643+ /// <summary>
644+ /// This method wil be called when the update finished. The view should show the appropiate
645+ /// data to the user when this occurs.
646+ /// </summary>
647+ void Updatefinished();
648+
649+ /// <summary>
650+ /// Handler that will be used when there is an update in the progress of the download.
651+ /// This handler can be used to allow the user know the progress of the download.
652+ /// </summary>
653+ /// <param name="sender">The object that sent the arguments.</param>
654+ /// <param name="args">The event arguments that provide the information to be
655+ /// shown to the user.</param>
656+ void DownloadProgressHandler(object sender, DownloadTaskProgressEventArgs args);
657+
658+ /// <summary>
659+ /// Handler that will be used when there was an error in the update. This will allow
660+ /// the view to communicate the user that there was an error but should not try to do anything about
661+ /// it since this object is just a view.
662+ /// </summary>
663+ /// <param name="sender">The object that sent the event.</param>
664+ /// <param name="args">The event arguments that provide the information to be
665+ /// shown to the user.</param>
666+ void DownloadErrorHandler(object sender, DownloadTaskErrorEventArgs args);
667+
668+ /// <summary>
669+ /// Handler that will be used when the download of the updates finished. This will allows th view
670+ /// to let the user know that we finished and that the updating will be in progress.
671+ /// </summary>
672+ /// <param name="sender">The object that sent the event.</param>
673+ /// <param name="e">The event arguments that provide the information to be
674+ /// shown to the user.</param>
675+ void DownloadUpdateCompleted(object sender, TaskEventArgs e);
676+ }
677+}
678
679=== added file 'src/Canonical.UbuntuOne.Common/Update/IUpdater.cs'
680--- src/Canonical.UbuntuOne.Common/Update/IUpdater.cs 1970-01-01 00:00:00 +0000
681+++ src/Canonical.UbuntuOne.Common/Update/IUpdater.cs 2010-07-21 10:14:43 +0000
682@@ -0,0 +1,55 @@
683+/**
684+ * Copyright 2010 Canonical Ltd.
685+ *
686+ * This file is part of UbuntuOne on Windows.
687+ *
688+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
689+ * it under the terms of the GNU Lesser General Public License version
690+ * as published by the Free Software Foundation.
691+ *
692+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
693+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
694+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
695+ * GNU Lesser General Public License for more details.
696+ *
697+ * You should have received a copy of the GNU Lesser General Public License
698+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
699+ *
700+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
701+ */
702+
703+using System;
704+
705+namespace Canonical.UbuntuOne.Common.Update
706+{
707+ /// <summary>
708+ /// This interface must be implemented by those classes that will provide the avility of
709+ /// updating the application.
710+ /// </summary>
711+ public interface IUpdater : IDisposable
712+ {
713+
714+ /// <summary>
715+ /// Gets and sets the feed that will be used to check for updates.
716+ /// </summary>
717+ string RSSFeed { get; set; }
718+
719+ /// <summary>
720+ /// Gets and sets the view that will be used to ask for confirmation when an update exists.
721+ /// </summary>
722+ IUpdateView UpdateView { get; set; }
723+
724+ /// <summary>
725+ /// Returns if the are updates present for the application.
726+ /// </summary>
727+ /// <returns>A flag indicating if updates are available.</returns>
728+ bool UpdatesArePresent();
729+
730+ /// <summary>
731+ /// This method will perform the update of the application using a msi installer that
732+ /// is fecthed from the rss feed.
733+ /// </summary>
734+ void PerformUpdate();
735+
736+ }
737+}
738
739=== added file 'src/Canonical.UbuntuOne.Common/Update/SelfUpdateException.cs'
740--- src/Canonical.UbuntuOne.Common/Update/SelfUpdateException.cs 1970-01-01 00:00:00 +0000
741+++ src/Canonical.UbuntuOne.Common/Update/SelfUpdateException.cs 2010-07-21 10:14:43 +0000
742@@ -0,0 +1,46 @@
743+/**
744+ * Copyright 2010 Canonical Ltd.
745+ *
746+ * This file is part of UbuntuOne on Windows.
747+ *
748+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
749+ * it under the terms of the GNU Lesser General Public License version
750+ * as published by the Free Software Foundation.
751+ *
752+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
753+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
754+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
755+ * GNU Lesser General Public License for more details.
756+ *
757+ * You should have received a copy of the GNU Lesser General Public License
758+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
759+ *
760+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
761+ */
762+using System;
763+
764+namespace Canonical.UbuntuOne.Common.Update
765+{
766+ /// <summary>
767+ /// Exception thrown when there has been an issue while the update operation
768+ /// was taking place.
769+ /// </summary>
770+ public class SelfUpdateException : Exception
771+ {
772+ public SelfUpdateException()
773+ {
774+ }
775+
776+ public SelfUpdateException(string message)
777+ : base(message)
778+ {
779+
780+ }
781+
782+ public SelfUpdateException(string message, Exception inner)
783+ : base(message, inner)
784+ {
785+
786+ }
787+ }
788+}
789
790=== added file 'src/Canonical.UbuntuOne.Common/Update/UpdateResources.Designer.cs'
791--- src/Canonical.UbuntuOne.Common/Update/UpdateResources.Designer.cs 1970-01-01 00:00:00 +0000
792+++ src/Canonical.UbuntuOne.Common/Update/UpdateResources.Designer.cs 2010-07-21 10:14:43 +0000
793@@ -0,0 +1,117 @@
794+//------------------------------------------------------------------------------
795+// <auto-generated>
796+// This code was generated by a tool.
797+// Runtime Version:2.0.50727.4927
798+//
799+// Changes to this file may cause incorrect behavior and will be lost if
800+// the code is regenerated.
801+// </auto-generated>
802+//------------------------------------------------------------------------------
803+
804+namespace Canonical.UbuntuOne.Common.Update {
805+ using System;
806+
807+
808+ /// <summary>
809+ /// A strongly-typed resource class, for looking up localized strings, etc.
810+ /// </summary>
811+ // This class was auto-generated by the StronglyTypedResourceBuilder
812+ // class via a tool like ResGen or Visual Studio.
813+ // To add or remove a member, edit your .ResX file then rerun ResGen
814+ // with the /str option, or rebuild your VS project.
815+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
816+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
817+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
818+ internal class UpdateResources {
819+
820+ private static global::System.Resources.ResourceManager resourceMan;
821+
822+ private static global::System.Globalization.CultureInfo resourceCulture;
823+
824+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
825+ internal UpdateResources() {
826+ }
827+
828+ /// <summary>
829+ /// Returns the cached ResourceManager instance used by this class.
830+ /// </summary>
831+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
832+ internal static global::System.Resources.ResourceManager ResourceManager {
833+ get {
834+ if (object.ReferenceEquals(resourceMan, null)) {
835+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Canonical.UbuntuOne.Common.Update.UpdateResources", typeof(UpdateResources).Assembly);
836+ resourceMan = temp;
837+ }
838+ return resourceMan;
839+ }
840+ }
841+
842+ /// <summary>
843+ /// Overrides the current thread's CurrentUICulture property for all
844+ /// resource lookups using this strongly typed resource class.
845+ /// </summary>
846+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
847+ internal static global::System.Globalization.CultureInfo Culture {
848+ get {
849+ return resourceCulture;
850+ }
851+ set {
852+ resourceCulture = value;
853+ }
854+ }
855+
856+ /// <summary>
857+ /// Looks up a localized string similar to Update could not be downloaded..
858+ /// </summary>
859+ internal static string CannotDownload {
860+ get {
861+ return ResourceManager.GetString("CannotDownload", resourceCulture);
862+ }
863+ }
864+
865+ /// <summary>
866+ /// Looks up a localized string similar to Trying to update when check has not yet been performed..
867+ /// </summary>
868+ internal static string CheckNotDone {
869+ get {
870+ return ResourceManager.GetString("CheckNotDone", resourceCulture);
871+ }
872+ }
873+
874+ /// <summary>
875+ /// Looks up a localized string similar to The download was completed..
876+ /// </summary>
877+ internal static string DownloadCompleted {
878+ get {
879+ return ResourceManager.GetString("DownloadCompleted", resourceCulture);
880+ }
881+ }
882+
883+ /// <summary>
884+ /// Looks up a localized string similar to The download could not me completed..
885+ /// </summary>
886+ internal static string DownloadError {
887+ get {
888+ return ResourceManager.GetString("DownloadError", resourceCulture);
889+ }
890+ }
891+
892+ /// <summary>
893+ /// Looks up a localized string similar to Updater RSS feed is null or empty..
894+ /// </summary>
895+ internal static string NoRSSFeedPresent {
896+ get {
897+ return ResourceManager.GetString("NoRSSFeedPresent", resourceCulture);
898+ }
899+ }
900+
901+ /// <summary>
902+ /// Looks up a localized string similar to There are no updates available..
903+ /// </summary>
904+ internal static string NoUpdatesAvailable {
905+ get {
906+ return ResourceManager.GetString("NoUpdatesAvailable", resourceCulture);
907+ }
908+ }
909+ }
910+}
911
912=== added file 'src/Canonical.UbuntuOne.Common/Update/UpdateResources.resx'
913--- src/Canonical.UbuntuOne.Common/Update/UpdateResources.resx 1970-01-01 00:00:00 +0000
914+++ src/Canonical.UbuntuOne.Common/Update/UpdateResources.resx 2010-07-21 10:14:43 +0000
915@@ -0,0 +1,138 @@
916+<?xml version="1.0" encoding="utf-8"?>
917+<root>
918+ <!--
919+ Microsoft ResX Schema
920+
921+ Version 2.0
922+
923+ The primary goals of this format is to allow a simple XML format
924+ that is mostly human readable. The generation and parsing of the
925+ various data types are done through the TypeConverter classes
926+ associated with the data types.
927+
928+ Example:
929+
930+ ... ado.net/XML headers & schema ...
931+ <resheader name="resmimetype">text/microsoft-resx</resheader>
932+ <resheader name="version">2.0</resheader>
933+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
934+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
935+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
936+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
937+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
938+ <value>[base64 mime encoded serialized .NET Framework object]</value>
939+ </data>
940+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
941+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
942+ <comment>This is a comment</comment>
943+ </data>
944+
945+ There are any number of "resheader" rows that contain simple
946+ name/value pairs.
947+
948+ Each data row contains a name, and value. The row also contains a
949+ type or mimetype. Type corresponds to a .NET class that support
950+ text/value conversion through the TypeConverter architecture.
951+ Classes that don't support this are serialized and stored with the
952+ mimetype set.
953+
954+ The mimetype is used for serialized objects, and tells the
955+ ResXResourceReader how to depersist the object. This is currently not
956+ extensible. For a given mimetype the value must be set accordingly:
957+
958+ Note - application/x-microsoft.net.object.binary.base64 is the format
959+ that the ResXResourceWriter will generate, however the reader can
960+ read any of the formats listed below.
961+
962+ mimetype: application/x-microsoft.net.object.binary.base64
963+ value : The object must be serialized with
964+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
965+ : and then encoded with base64 encoding.
966+
967+ mimetype: application/x-microsoft.net.object.soap.base64
968+ value : The object must be serialized with
969+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
970+ : and then encoded with base64 encoding.
971+
972+ mimetype: application/x-microsoft.net.object.bytearray.base64
973+ value : The object must be serialized into a byte array
974+ : using a System.ComponentModel.TypeConverter
975+ : and then encoded with base64 encoding.
976+ -->
977+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
978+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
979+ <xsd:element name="root" msdata:IsDataSet="true">
980+ <xsd:complexType>
981+ <xsd:choice maxOccurs="unbounded">
982+ <xsd:element name="metadata">
983+ <xsd:complexType>
984+ <xsd:sequence>
985+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
986+ </xsd:sequence>
987+ <xsd:attribute name="name" use="required" type="xsd:string" />
988+ <xsd:attribute name="type" type="xsd:string" />
989+ <xsd:attribute name="mimetype" type="xsd:string" />
990+ <xsd:attribute ref="xml:space" />
991+ </xsd:complexType>
992+ </xsd:element>
993+ <xsd:element name="assembly">
994+ <xsd:complexType>
995+ <xsd:attribute name="alias" type="xsd:string" />
996+ <xsd:attribute name="name" type="xsd:string" />
997+ </xsd:complexType>
998+ </xsd:element>
999+ <xsd:element name="data">
1000+ <xsd:complexType>
1001+ <xsd:sequence>
1002+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
1003+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
1004+ </xsd:sequence>
1005+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
1006+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
1007+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
1008+ <xsd:attribute ref="xml:space" />
1009+ </xsd:complexType>
1010+ </xsd:element>
1011+ <xsd:element name="resheader">
1012+ <xsd:complexType>
1013+ <xsd:sequence>
1014+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
1015+ </xsd:sequence>
1016+ <xsd:attribute name="name" type="xsd:string" use="required" />
1017+ </xsd:complexType>
1018+ </xsd:element>
1019+ </xsd:choice>
1020+ </xsd:complexType>
1021+ </xsd:element>
1022+ </xsd:schema>
1023+ <resheader name="resmimetype">
1024+ <value>text/microsoft-resx</value>
1025+ </resheader>
1026+ <resheader name="version">
1027+ <value>2.0</value>
1028+ </resheader>
1029+ <resheader name="reader">
1030+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
1031+ </resheader>
1032+ <resheader name="writer">
1033+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
1034+ </resheader>
1035+ <data name="CannotDownload" xml:space="preserve">
1036+ <value>Update could not be downloaded.</value>
1037+ </data>
1038+ <data name="CheckNotDone" xml:space="preserve">
1039+ <value>Trying to update when check has not yet been performed.</value>
1040+ </data>
1041+ <data name="DownloadCompleted" xml:space="preserve">
1042+ <value>The download was completed.</value>
1043+ </data>
1044+ <data name="DownloadError" xml:space="preserve">
1045+ <value>The download could not me completed.</value>
1046+ </data>
1047+ <data name="NoRSSFeedPresent" xml:space="preserve">
1048+ <value>Updater RSS feed is null or empty.</value>
1049+ </data>
1050+ <data name="NoUpdatesAvailable" xml:space="preserve">
1051+ <value>There are no updates available.</value>
1052+ </data>
1053+</root>
1054\ No newline at end of file
1055
1056=== added file 'src/Canonical.UbuntuOne.Common/Update/Updater.cs'
1057--- src/Canonical.UbuntuOne.Common/Update/Updater.cs 1970-01-01 00:00:00 +0000
1058+++ src/Canonical.UbuntuOne.Common/Update/Updater.cs 2010-07-21 10:14:43 +0000
1059@@ -0,0 +1,231 @@
1060+/**
1061+ * Copyright 2010 Canonical Ltd.
1062+ *
1063+ * This file is part of UbuntuOne on Windows.
1064+ *
1065+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
1066+ * it under the terms of the GNU Lesser General Public License version
1067+ * as published by the Free Software Foundation.
1068+ *
1069+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
1070+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1071+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1072+ * GNU Lesser General Public License for more details.
1073+ *
1074+ * You should have received a copy of the GNU Lesser General Public License
1075+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1076+ *
1077+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1078+ */
1079+using System;
1080+using System.Windows.Threading;
1081+using DotUpdater;
1082+using log4net;
1083+using Microsoft.ApplicationBlocks.Updater;
1084+
1085+namespace Canonical.UbuntuOne.Common.Update
1086+{
1087+ /// <summary>
1088+ /// Implementation of the IUpdater interface that will be wrapping the DotUpdater classes
1089+ /// from http://dotupdater.codeplex.com/
1090+ /// </summary>
1091+ public class Updater : IUpdater
1092+ {
1093+
1094+ #region Variables
1095+
1096+ private IDotUpdaterWrapper _updater;
1097+ private readonly object _updaterLock = new object();
1098+ private UpdaterTask _task;
1099+ private ILog _logger;
1100+ private readonly object _loggerLock = new object();
1101+ private bool _updateChecked;
1102+ private readonly object _updateLock = new object();
1103+ private bool _downloadingUpdate;
1104+
1105+ #endregion
1106+
1107+ #region Delegats
1108+
1109+ delegate void UpdaterDelegate(UpdaterTask task);
1110+
1111+ #endregion
1112+
1113+ #region DI properties
1114+
1115+ public string RSSFeed { get; set; }
1116+
1117+ public IUpdateView UpdateView { get; set; }
1118+
1119+ #endregion
1120+
1121+ #region Helper properties
1122+
1123+ /// <summary>
1124+ /// Gets and sets the DotUpdater used by the class to perform the different
1125+ /// operaqtions, this allows to later use mocks when testing.
1126+ /// </summary>
1127+ internal IDotUpdaterWrapper DotUpdater
1128+ {
1129+ get
1130+ {
1131+ if(_updater == null)
1132+ {
1133+ lock (_updaterLock)
1134+ {
1135+ if(String.IsNullOrEmpty(RSSFeed))
1136+ {
1137+ Logger.Error(UpdateResources.NoRSSFeedPresent);
1138+ throw new SelfUpdateException(UpdateResources.NoRSSFeedPresent);
1139+ }
1140+ _updater = new DotUpdaterWrapper(new DotLogger(), RSSFeed);
1141+ }
1142+ }
1143+ return _updater;
1144+ }
1145+ set
1146+ {
1147+ lock (_updaterLock)
1148+ {
1149+ _updater = value;
1150+ }
1151+ }
1152+ }
1153+
1154+ /// <summary>
1155+ /// Gets and sets the logger that is used by the class.
1156+ /// </summary>
1157+ public ILog Logger
1158+ {
1159+ get
1160+ {
1161+ return _logger ?? (_logger = LogManager.GetLogger(typeof (Updater)));
1162+ }
1163+ set
1164+ {
1165+ lock (_loggerLock)
1166+ {
1167+ _logger = value;
1168+ }
1169+ }
1170+ }
1171+ #endregion
1172+
1173+ #region Helper methods
1174+
1175+ /// <summary>
1176+ /// Helper that will dispatch the update operation to a different thread to be performed.
1177+ /// </summary>
1178+ /// <param name="sender">The object that sent the event args.</param>
1179+ /// <param name="e">The arguments of the event.</param>
1180+ private void DownloadUpdateCompleted(object sender, TaskEventArgs e)
1181+ {
1182+ Logger.Info(UpdateResources.DownloadCompleted);
1183+ // call the method in an other thread that will perform the update
1184+ UpdaterDelegate updaterDelegate = UpdateDownloadedMainThread;
1185+ Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, updaterDelegate, e.Task);
1186+ }
1187+
1188+ /// <summary>
1189+ /// Helper that will take care of cleaning up and logging after an expcetion has occurred when
1190+ /// the download failed.
1191+ /// </summary>
1192+ /// <param name="sender">The object that sent the event.</param>
1193+ /// <param name="args">The argumens of the event.</param>
1194+ private void DownloadErrorHandler(object sender, DownloadTaskErrorEventArgs args)
1195+ {
1196+ Logger.Error(args.Exception.Message);
1197+ throw new SelfUpdateException(UpdateResources.DownloadError, args.Exception);
1198+ }
1199+
1200+ /// <summary>
1201+ /// Helper method that will perform the actual update of the application, to do so the updater will
1202+ /// close and update the application adter asking the user throw the view.
1203+ /// </summary>
1204+ /// <param name="task">The updater tasks that was being performed.</param>
1205+ private void UpdateDownloadedMainThread(UpdaterTask task)
1206+ {
1207+ if (UpdateView.AskForCloseAnInstallConfirmation() != UpdateConfirmation.YES)
1208+ return;
1209+
1210+ // perform the update
1211+ DotUpdater.Install(_task);
1212+ // clean the resoruces
1213+ _task = null;
1214+ _updateChecked = false;
1215+ _downloadingUpdate = false;
1216+ }
1217+
1218+ #endregion
1219+
1220+ public bool UpdatesArePresent()
1221+ {
1222+ // we lock since this is done in a multithreaded enviroment and
1223+ // we want to make sure that we do not check for the update twice at the same time
1224+ if(_task == null)
1225+ {
1226+ lock (_updateLock)
1227+ {
1228+ _task = DotUpdater.CheckForUpdates();
1229+ _updateChecked = true;
1230+ }
1231+ }
1232+ return _task != null;
1233+ }
1234+
1235+ public void PerformUpdate()
1236+ {
1237+ lock (_updateLock)
1238+ {
1239+ if (!_updateChecked)
1240+ {
1241+ Logger.Error(UpdateResources.CheckNotDone);
1242+ throw new SelfUpdateException(UpdateResources.CheckNotDone);
1243+ }
1244+ if(_task == null)
1245+ {
1246+ Logger.Error(UpdateResources.NoUpdatesAvailable);
1247+ throw new SelfUpdateException(UpdateResources.NoUpdatesAvailable);
1248+ }
1249+ if(!_task.Downloaded && !_downloadingUpdate)
1250+ {
1251+ // we need to download the update
1252+ try
1253+ {
1254+ _downloadingUpdate = true;
1255+ DotUpdater.BeginDownload(_task);
1256+ // provide the handler for the progress of the download as well as the
1257+ // error and finish
1258+ DotUpdater.OnDownloadProgress += UpdateView.DownloadProgressHandler;
1259+ // we provide two handlers one for the view to let the user know we completed
1260+ // the download and a second one for the updater that will do the actual work
1261+ DotUpdater.OnDownloadCompleted += UpdateView.DownloadUpdateCompleted;
1262+ DotUpdater.OnDownloadCompleted += DownloadUpdateCompleted;
1263+ // register to handlers, one for the view that will show the error and an other
1264+ // one for the updater that will handle the error.
1265+ DotUpdater.OnDownloadError += UpdateView.DownloadErrorHandler;
1266+ DotUpdater.OnDownloadError += DownloadErrorHandler;
1267+ }
1268+ catch (UpdaterException e)
1269+ {
1270+ Logger.Error(UpdateResources.CannotDownload);
1271+ throw new SelfUpdateException(UpdateResources.CannotDownload, e);
1272+ }
1273+ }
1274+ if(_task.Downloaded)
1275+ {
1276+ _downloadingUpdate = false;
1277+ // just call the handler directly
1278+ DownloadUpdateCompleted(this, new TaskEventArgs(_task));
1279+ }
1280+ }
1281+ }
1282+
1283+ public void Dispose()
1284+ {
1285+ if (_updater == null) return;
1286+ _updater.Dispose();
1287+ _updater = null;
1288+ }
1289+ }
1290+}

Subscribers

People subscribed via source and target branches

to all changes: