@appzung/react-native-code-push 6.4.2 → 8.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.azurepipelines/build-rn-code-push-1es.yml +104 -0
  2. package/.azurepipelines/test-rn-code-push.yml +94 -0
  3. package/.config/CredScanSuppressions.json +14 -0
  4. package/CONTRIBUTING.md +3 -3
  5. package/CodePush.js +26 -28
  6. package/CodePush.podspec +1 -1
  7. package/README.md +8 -7
  8. package/SECURITY.md +41 -0
  9. package/android/app/build.gradle +1 -1
  10. package/android/app/src/main/AndroidManifest.xml +1 -5
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +14 -5
  12. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +1 -0
  13. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +19 -1
  14. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +5 -4
  15. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +3 -1
  16. package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +8 -9
  17. package/android/build.gradle +3 -2
  18. package/android/codepush.gradle +79 -30
  19. package/docs/api-js.md +1 -1
  20. package/docs/setup-android.md +27 -3
  21. package/docs/setup-ios.md +1 -1
  22. package/docs/setup-windows.md +59 -3
  23. package/ios/CodePush/CodePushPackage.m +4 -0
  24. package/ios/CodePush/CodePushUpdateUtils.m +1 -1
  25. package/ios/CodePush.xcodeproj/project.pbxproj +2 -2
  26. package/package.json +11 -11
  27. package/typings/react-native-code-push.d.ts +1 -1
  28. package/windows/CodePush/CodePush.def +3 -0
  29. package/windows/CodePush/CodePush.vcxproj +198 -0
  30. package/windows/CodePush/CodePush.vcxproj.filters +91 -0
  31. package/windows/CodePush/CodePushConfig.cpp +104 -0
  32. package/windows/CodePush/CodePushConfig.h +66 -0
  33. package/windows/CodePush/CodePushConfig.idl +12 -0
  34. package/windows/CodePush/CodePushDownloadHandler.cpp +73 -0
  35. package/windows/CodePush/CodePushDownloadHandler.h +32 -0
  36. package/windows/CodePush/CodePushNativeModule.cpp +934 -0
  37. package/windows/CodePush/CodePushNativeModule.h +247 -0
  38. package/windows/CodePush/CodePushPackage.cpp +456 -0
  39. package/windows/CodePush/CodePushPackage.h +49 -0
  40. package/windows/CodePush/CodePushTelemetryManager.cpp +213 -0
  41. package/windows/CodePush/CodePushTelemetryManager.h +29 -0
  42. package/windows/CodePush/CodePushUpdateUtils.cpp +86 -0
  43. package/windows/CodePush/CodePushUpdateUtils.h +38 -0
  44. package/windows/CodePush/CodePushUtils.cpp +29 -0
  45. package/windows/CodePush/CodePushUtils.h +18 -0
  46. package/windows/CodePush/FileUtils.cpp +131 -0
  47. package/windows/CodePush/FileUtils.h +28 -0
  48. package/windows/CodePush/PropertySheet.props +16 -0
  49. package/windows/CodePush/ReactPackageProvider.cpp +15 -0
  50. package/windows/CodePush/ReactPackageProvider.h +22 -0
  51. package/windows/CodePush/ReactPackageProvider.idl +9 -0
  52. package/windows/CodePush/miniz/LICENSE +22 -0
  53. package/windows/CodePush/miniz/miniz.c +7657 -0
  54. package/windows/CodePush/miniz/miniz.h +1338 -0
  55. package/windows/CodePush/miniz/readme.md +37 -0
  56. package/windows/CodePush/packages.config +4 -0
  57. package/windows/CodePush/pch.cpp +1 -0
  58. package/windows/CodePush/pch.h +4 -0
  59. package/{windows → windows-legacy}/CodePush/CodePush.csproj +1 -1
  60. package/{windows → windows-legacy}/CodePush.Net46/CodePush.Net46.csproj +2 -2
  61. package/{windows → windows-legacy}/CodePush.Net46/packages.config +1 -1
  62. package/windows-legacy/CodePush.Net46.Test/ApplicationDataContainerTest.cs +105 -0
  63. package/windows-legacy/CodePush.Net46.Test/CodePush.Net46.Test.csproj +137 -0
  64. package/windows-legacy/CodePush.Net46.Test/Properties/AssemblyInfo.cs +36 -0
  65. package/windows-legacy/CodePush.Net46.Test/TelemetryManagerTest.cs +117 -0
  66. package/windows-legacy/CodePush.Net46.Test/app.config +11 -0
  67. package/windows-legacy/CodePush.Net46.Test/packages.config +4 -0
  68. /package/{windows → windows-legacy}/CodePush/CodePushUtils.cs +0 -0
  69. /package/{windows → windows-legacy}/CodePush/FileUtils.cs +0 -0
  70. /package/{windows → windows-legacy}/CodePush/Properties/AssemblyInfo.cs +0 -0
  71. /package/{windows → windows-legacy}/CodePush/Properties/CodePush.rd.xml +0 -0
  72. /package/{windows → windows-legacy}/CodePush/UpdateManager.cs +0 -0
  73. /package/{windows → windows-legacy}/CodePush/UpdateUtils.cs +0 -0
  74. /package/{windows → windows-legacy}/CodePush.Net46/Adapters/Http/HttpProgress.cs +0 -0
  75. /package/{windows → windows-legacy}/CodePush.Net46/Adapters/Storage/ApplicationDataContainer.cs +0 -0
  76. /package/{windows → windows-legacy}/CodePush.Net46/CodePushUtils.cs +0 -0
  77. /package/{windows → windows-legacy}/CodePush.Net46/FileUtils.cs +0 -0
  78. /package/{windows → windows-legacy}/CodePush.Net46/Properties/AssemblyInfo.cs +0 -0
  79. /package/{windows → windows-legacy}/CodePush.Net46/UpdateManager.cs +0 -0
  80. /package/{windows → windows-legacy}/CodePush.Net46/UpdateUtils.cs +0 -0
  81. /package/{windows → windows-legacy}/CodePush.Shared/CodePush.Shared.projitems +0 -0
  82. /package/{windows → windows-legacy}/CodePush.Shared/CodePush.Shared.shproj +0 -0
  83. /package/{windows → windows-legacy}/CodePush.Shared/CodePushConstants.cs +0 -0
  84. /package/{windows → windows-legacy}/CodePush.Shared/CodePushNativeModule.cs +0 -0
  85. /package/{windows → windows-legacy}/CodePush.Shared/CodePushReactPackage.cs +0 -0
  86. /package/{windows → windows-legacy}/CodePush.Shared/CodePushUtils.cs +0 -0
  87. /package/{windows → windows-legacy}/CodePush.Shared/InstallMode.cs +0 -0
  88. /package/{windows → windows-legacy}/CodePush.Shared/MinimumBackgroundListener.cs +0 -0
  89. /package/{windows → windows-legacy}/CodePush.Shared/SettingsManager.cs +0 -0
  90. /package/{windows → windows-legacy}/CodePush.Shared/TelemetryManager.cs +0 -0
  91. /package/{windows → windows-legacy}/CodePush.Shared/UpdateState.cs +0 -0
@@ -0,0 +1,456 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #include "pch.h"
5
+
6
+ #include "CodePushDownloadHandler.h"
7
+ #include "CodePushNativeModule.h"
8
+ #include "CodePushPackage.h"
9
+ #include "CodePushUtils.h"
10
+ #include "CodePushUpdateUtils.h"
11
+ #include "FileUtils.h"
12
+
13
+ #include <winrt/Windows.Storage.h>
14
+ #include <winrt/Windows.Storage.Streams.h>
15
+ #include <winrt/Windows.Foundation.h>
16
+
17
+ #include <functional>
18
+
19
+ namespace Microsoft::CodePush::ReactNative
20
+ {
21
+ using namespace winrt;
22
+ using namespace Windows::Data::Json;
23
+ using namespace Windows::Foundation;
24
+ using namespace Windows::Storage;
25
+ using namespace Windows::Storage::Streams;
26
+
27
+ /*static*/ IAsyncAction CodePushPackage::ClearUpdatesAsync()
28
+ {
29
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
30
+ codePushFolder.DeleteAsync();
31
+ }
32
+
33
+ /*static*/ IAsyncAction CodePushPackage::DownloadPackageAsync(
34
+ JsonObject& updatePackage,
35
+ std::wstring_view expectedBundleFileName,
36
+ std::wstring_view publicKey,
37
+ std::function<void(int64_t, int64_t)> progressCallback)
38
+ {
39
+ auto newUpdateHash{ updatePackage.GetNamedString(L"packageHash") };
40
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
41
+
42
+ auto downloadFile{ co_await codePushFolder.CreateFileAsync(DownloadFileName, CreationCollisionOption::ReplaceExisting) };
43
+
44
+ CodePushDownloadHandler downloadHandler{
45
+ downloadFile,
46
+ progressCallback };
47
+
48
+ auto isZip{ co_await downloadHandler.Download(updatePackage.GetNamedString(L"downloadUrl")) };
49
+
50
+ StorageFolder newUpdateFolder{ co_await codePushFolder.CreateFolderAsync(newUpdateHash, CreationCollisionOption::ReplaceExisting) };
51
+ StorageFile newUpdateMetadataFile{ nullptr };
52
+ auto mutableUpdatePackage{ updatePackage };
53
+ if (isZip)
54
+ {
55
+ auto unzippedFolder{ co_await codePushFolder.CreateFolderAsync(UnzippedFolderName, CreationCollisionOption::ReplaceExisting) };
56
+ co_await FileUtils::UnzipAsync(downloadFile, unzippedFolder);
57
+ downloadFile.DeleteAsync();
58
+
59
+ auto isDiffUpdate{ false };
60
+
61
+ auto diffManifestFile{ (co_await unzippedFolder.TryGetItemAsync(DiffManifestFileName)).try_as<StorageFile>() };
62
+ if (diffManifestFile != nullptr)
63
+ {
64
+ isDiffUpdate = true;
65
+ }
66
+
67
+ if (isDiffUpdate)
68
+ {
69
+ // Copy the current package to the new package.
70
+ auto currentPackageFolder{ co_await GetCurrentPackageFolderAsync() };
71
+
72
+ if (currentPackageFolder == nullptr)
73
+ {
74
+ // Currently running the binary version, copy files from the bundled resources
75
+ auto newUpdateCodePushFolder{ co_await newUpdateFolder.CreateFolderAsync(CodePushUpdateUtils::ManifestFolderPrefix) };
76
+
77
+ auto binaryAssetsFolder{ co_await CodePushNativeModule::GetBundleAssetsFolderAsync() };
78
+ auto newUpdateAssetsFolder{ co_await newUpdateCodePushFolder.CreateFolderAsync(CodePushUpdateUtils::AssetsFolderName) };
79
+ CodePushUpdateUtils::CopyEntriesInFolderAsync(binaryAssetsFolder, newUpdateAssetsFolder);
80
+
81
+ auto binaryBundleFile{ co_await CodePushNativeModule::GetBinaryBundleAsync() };
82
+ co_await binaryBundleFile.CopyAsync(newUpdateCodePushFolder);
83
+ }
84
+ else
85
+ {
86
+ // Copy the contents of the current package to the new package. (how are conflicts resolved?)
87
+ co_await CodePushUpdateUtils::CopyEntriesInFolderAsync(currentPackageFolder, newUpdateFolder);
88
+ }
89
+
90
+ auto manifestContent{ co_await FileIO::ReadTextAsync(diffManifestFile, UnicodeEncoding::Utf8) };
91
+ auto manifestJson{ JsonObject::Parse(manifestContent) };
92
+ auto deletedFiles{ manifestJson.TryLookup(L"deletedFiles") };
93
+ auto deletedFilesArray{ deletedFiles.try_as<JsonArray>() };
94
+
95
+ if (deletedFilesArray != nullptr)
96
+ {
97
+ for (const auto& deletedFileName : deletedFilesArray)
98
+ {
99
+ auto fileToDelete{ (co_await newUpdateFolder.TryGetItemAsync(deletedFileName.GetString())).try_as<StorageFile>() };
100
+ if (fileToDelete != nullptr)
101
+ {
102
+ co_await fileToDelete.DeleteAsync();
103
+ }
104
+ }
105
+ }
106
+
107
+ co_await diffManifestFile.DeleteAsync();
108
+ }
109
+
110
+ co_await CodePushUpdateUtils::CopyEntriesInFolderAsync(unzippedFolder, newUpdateFolder);
111
+ co_await unzippedFolder.DeleteAsync();
112
+
113
+ auto relativeBundlePath{ co_await FileUtils::FindFilePathAsync(newUpdateFolder, expectedBundleFileName) };
114
+ if (!relativeBundlePath.empty())
115
+ {
116
+ mutableUpdatePackage.Insert(RelativeBundlePathKey, JsonValue::CreateStringValue(relativeBundlePath));
117
+ }
118
+ else
119
+ {
120
+ auto errorMessage{ L"Error: Unable to find JS bundle in downloaded package." };
121
+ hresult_error error{ E_INVALIDARG, errorMessage };
122
+ CodePushUtils::Log(error);
123
+ throw error;
124
+ }
125
+
126
+ auto newUpdateMetadata{ co_await newUpdateFolder.TryGetItemAsync(UpdateMetadataFileName) };
127
+ if (newUpdateMetadata != nullptr)
128
+ {
129
+ co_await newUpdateMetadata.DeleteAsync();
130
+ }
131
+
132
+ CodePushUtils::Log((isDiffUpdate) ? L"Applying diff update." : L"Applying full update.");
133
+ auto isSignatureVerificationEnabled{ !publicKey.empty() };
134
+
135
+ auto signatureFile{ co_await CodePushUpdateUtils::GetSignatureFileAsync(newUpdateFolder) };
136
+ auto isSignatureAppearedInBundle{ signatureFile != nullptr };
137
+
138
+ if (isSignatureVerificationEnabled)
139
+ {
140
+ if (isSignatureAppearedInBundle)
141
+ {
142
+ auto errorMessage{ L"Error: Signature Verification is not currently supported." };
143
+ hresult_error error{ E_NOTIMPL, errorMessage };
144
+ CodePushUtils::Log(error);
145
+ throw error;
146
+ }
147
+ else
148
+ {
149
+ auto errorMessage{ L"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
150
+ L"Possible reasons, why that might happen: \n" \
151
+ L"1. You've been released CodePush bundle update using a version of the CodePush CLI that does not support code signing.\n" \
152
+ L"2. You've been released CodePush bundle update without providing --privateKeyPath option." };
153
+ hresult_error error{ E_FAIL, errorMessage };
154
+ CodePushUtils::Log(error);
155
+ throw error;
156
+ }
157
+ }
158
+ else
159
+ {
160
+ bool needToVerifyHash;
161
+ if (isSignatureAppearedInBundle)
162
+ {
163
+ CodePushUtils::Log(L"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
164
+ L" because there is no public key configured. " \
165
+ L"Please ensure that a public key is properly configured within your application.");
166
+ needToVerifyHash = true;
167
+ }
168
+ else
169
+ {
170
+ needToVerifyHash = isDiffUpdate;
171
+ }
172
+
173
+ if (needToVerifyHash)
174
+ {
175
+ auto errorMessage{ L"Error: package content verification is not currently supported." };
176
+ hresult_error error{ E_NOTIMPL, errorMessage };
177
+ CodePushUtils::Log(error);
178
+ }
179
+ }
180
+ }
181
+ else
182
+ {
183
+ co_await downloadFile.MoveAsync(newUpdateFolder, UpdateBundleFileName, NameCollisionOption::ReplaceExisting);
184
+ }
185
+
186
+ newUpdateMetadataFile = co_await newUpdateFolder.CreateFileAsync(UpdateMetadataFileName, CreationCollisionOption::ReplaceExisting);
187
+
188
+ auto packageJsonString{ mutableUpdatePackage.Stringify() };
189
+ co_await FileIO::WriteTextAsync(newUpdateMetadataFile, packageJsonString);
190
+
191
+ co_return;
192
+ }
193
+
194
+ /*static*/ IAsyncOperation<StorageFolder> CodePushPackage::GetCodePushFolderAsync()
195
+ {
196
+ auto localStorage{ CodePushNativeModule::GetLocalStorageFolder() };
197
+ auto codePushFolder{ co_await localStorage.CreateFolderAsync(L"CodePush", CreationCollisionOption::OpenIfExists) };
198
+ co_return codePushFolder;
199
+ }
200
+
201
+ /*static*/ IAsyncOperation<JsonObject> CodePushPackage::GetCurrentPackageAsync()
202
+ {
203
+ auto packageHash{ co_await GetCurrentPackageHashAsync() };
204
+ if (packageHash.empty())
205
+ {
206
+ co_return nullptr;
207
+ }
208
+ co_return co_await GetPackageAsync(packageHash);
209
+ }
210
+
211
+ /*static*/ IAsyncOperation<StorageFile> CodePushPackage::GetCurrentPackageBundleAsync()
212
+ {
213
+ auto packageFolder{ co_await GetCurrentPackageFolderAsync() };
214
+ if (packageFolder == nullptr)
215
+ {
216
+ co_return nullptr;
217
+ }
218
+
219
+ auto currentPackage{ co_await GetCurrentPackageAsync() };
220
+ if (currentPackage == nullptr)
221
+ {
222
+ co_return nullptr;
223
+ }
224
+
225
+ auto relativeBundlePath{ currentPackage.GetNamedString(RelativeBundlePathKey, L"") };
226
+ if (!relativeBundlePath.empty())
227
+ {
228
+ auto currentBundle{ (co_await packageFolder.TryGetItemAsync(relativeBundlePath)).try_as<StorageFile>() };
229
+ co_return currentBundle;
230
+ }
231
+
232
+ co_return nullptr;
233
+ }
234
+
235
+ /*static*/ IAsyncOperation<StorageFolder> CodePushPackage::GetCurrentPackageFolderAsync()
236
+ {
237
+ auto info{ co_await GetCurrentPackageInfoAsync() };
238
+ if (info == nullptr)
239
+ {
240
+ return nullptr;
241
+ }
242
+
243
+ auto packageHash{ info.GetNamedString(L"currentPackage", L"") };
244
+ if (packageHash.empty())
245
+ {
246
+ return nullptr;
247
+ }
248
+
249
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
250
+ auto packageFolder{ (co_await codePushFolder.TryGetItemAsync(packageHash)).try_as<StorageFolder>() };
251
+ co_return packageFolder;
252
+ }
253
+
254
+ /*static*/ IAsyncOperation<hstring> CodePushPackage::GetCurrentPackageHashAsync()
255
+ {
256
+ auto info{ co_await GetCurrentPackageInfoAsync() };
257
+ if (info == nullptr)
258
+ {
259
+ co_return L"";
260
+ }
261
+ auto currentPackage{ info.TryLookup(L"currentPackage") };
262
+ if (currentPackage == nullptr)
263
+ {
264
+ co_return L"";
265
+ }
266
+ co_return currentPackage.GetString();
267
+ }
268
+
269
+ /*static*/ IAsyncOperation<JsonObject> CodePushPackage::GetCurrentPackageInfoAsync()
270
+ {
271
+ try
272
+ {
273
+ auto statusFile{ co_await GetStatusFileAsync() };
274
+ if (statusFile == nullptr)
275
+ {
276
+ co_return JsonObject{};
277
+ }
278
+ auto content{ co_await FileIO::ReadTextAsync(statusFile) };
279
+ JsonObject json;
280
+ auto success{ JsonObject::TryParse(content, json) };
281
+ if (!success)
282
+ {
283
+ co_return nullptr;
284
+ }
285
+ co_return json;
286
+ }
287
+ catch (...)
288
+ {
289
+ // Either the file does not exist or does not contain valid JSON
290
+ co_return nullptr;
291
+ }
292
+ co_return nullptr;
293
+ }
294
+
295
+ /*static*/ IAsyncOperation<JsonObject> CodePushPackage::GetPreviousPackageAsync()
296
+ {
297
+ auto packageHash{ co_await GetPreviousPackageHashAsync() };
298
+ if (packageHash.empty())
299
+ {
300
+ co_return nullptr;
301
+ }
302
+ co_return co_await GetPackageAsync(packageHash);
303
+ }
304
+
305
+ /*static*/ IAsyncOperation<hstring> CodePushPackage::GetPreviousPackageHashAsync()
306
+ {
307
+ auto info{ co_await GetCurrentPackageInfoAsync() };
308
+ if (info == nullptr)
309
+ {
310
+ co_return L"";
311
+ }
312
+ auto previousHash{ info.TryLookup(L"previousPackage") };
313
+ if (previousHash == nullptr)
314
+ {
315
+ co_return L"";
316
+ }
317
+ co_return previousHash.GetString();
318
+ }
319
+
320
+ /*static*/ IAsyncOperation<JsonObject> CodePushPackage::GetPackageAsync(std::wstring_view packageHash)
321
+ {
322
+ auto updateDirectory{ co_await GetPackageFolderAsync(packageHash) };
323
+ if (updateDirectory != nullptr)
324
+ {
325
+ auto updateMetadataFile{ (co_await updateDirectory.TryGetItemAsync(UpdateMetadataFileName)).try_as<StorageFile>() };
326
+ if (updateMetadataFile != nullptr)
327
+ {
328
+ auto updateMetadataString{ co_await FileIO::ReadTextAsync(updateMetadataFile) };
329
+ JsonObject updateMetadata;
330
+ auto success{ JsonObject::TryParse(updateMetadataString, updateMetadata) };
331
+ if (success)
332
+ {
333
+ co_return updateMetadata;
334
+ }
335
+ }
336
+ }
337
+ co_return nullptr;
338
+ }
339
+
340
+ /*static*/ IAsyncOperation<StorageFolder> CodePushPackage::GetPackageFolderAsync(std::wstring_view packageHash)
341
+ {
342
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
343
+ co_return (co_await codePushFolder.TryGetItemAsync(packageHash)).try_as<StorageFolder>();
344
+ }
345
+
346
+ /*static*/ IAsyncOperation<bool> CodePushPackage::InstallPackageAsync(JsonObject updatePackage, bool removePendingUpdate)
347
+ {
348
+ auto packageHash{ updatePackage.GetNamedString(L"packageHash") };
349
+ auto info{ co_await GetCurrentPackageInfoAsync() };
350
+ if (info == nullptr)
351
+ {
352
+ co_return false;
353
+ }
354
+
355
+ if (info.HasKey(L"currentPackage") && packageHash == info.GetNamedString(L"currentPackage"))
356
+ {
357
+ // The current package is already the one being installed, so we should no-op.
358
+ co_return true;
359
+ }
360
+
361
+ if (removePendingUpdate)
362
+ {
363
+ auto currentPackageFolder{ co_await GetCurrentPackageFolderAsync() };
364
+ if (currentPackageFolder != nullptr)
365
+ {
366
+ try
367
+ {
368
+ co_await currentPackageFolder.DeleteAsync();
369
+ }
370
+ catch (...)
371
+ {
372
+ CodePushUtils::Log(L"Error deleting pending package.");
373
+ }
374
+ }
375
+ }
376
+ else
377
+ {
378
+ auto previousPackageHash{ co_await GetPreviousPackageHashAsync() };
379
+ if (!previousPackageHash.empty() && previousPackageHash != packageHash)
380
+ {
381
+ auto previousPackageFolder{ co_await GetPackageFolderAsync(previousPackageHash) };
382
+ try
383
+ {
384
+ co_await previousPackageFolder.DeleteAsync();
385
+ }
386
+ catch (...)
387
+ {
388
+ CodePushUtils::Log(L"Error deleting old package.");
389
+ }
390
+ }
391
+
392
+ IJsonValue currentPackage;
393
+ if (info.HasKey(L"currentPackage"))
394
+ {
395
+ currentPackage = info.Lookup(L"currentPackage");
396
+ }
397
+ else
398
+ {
399
+ currentPackage = JsonValue::CreateStringValue(L"");
400
+ }
401
+ info.Insert(L"previousPackage", currentPackage);
402
+ }
403
+
404
+ info.Insert(L"currentPackage", JsonValue::CreateStringValue(packageHash));
405
+ co_return co_await UpdateCurrentPackageInfoAsync(info);
406
+ }
407
+
408
+ /*static*/ IAsyncAction CodePushPackage::RollbackPackage()
409
+ {
410
+ auto info{ co_await GetCurrentPackageInfoAsync() };
411
+ if (info == nullptr)
412
+ {
413
+ CodePushUtils::Log(L"Error getting current package info.");
414
+ co_return;
415
+ }
416
+
417
+ auto currentPackageFolder{ co_await GetCurrentPackageFolderAsync() };
418
+ if (currentPackageFolder == nullptr)
419
+ {
420
+ CodePushUtils::Log(L"Error getting package folder path.");
421
+ }
422
+
423
+ try
424
+ {
425
+ co_await currentPackageFolder.DeleteAsync();
426
+ }
427
+ catch (...)
428
+ {
429
+ CodePushUtils::Log(L"Error deleting current package contents.");
430
+ }
431
+
432
+ info.Insert(L"currentPackage", info.TryLookup(L"previousPackage"));
433
+ info.Remove(L"previousPackage");
434
+
435
+ co_await UpdateCurrentPackageInfoAsync(info);
436
+ }
437
+
438
+ /*static*/ IAsyncOperation<StorageFile> CodePushPackage::GetStatusFileAsync()
439
+ {
440
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
441
+ co_return (co_await codePushFolder.TryGetItemAsync(CodePushPackage::StatusFile)).try_as<StorageFile>();
442
+ }
443
+
444
+ /*static*/ IAsyncOperation<bool> CodePushPackage::UpdateCurrentPackageInfoAsync(JsonObject packageInfo)
445
+ {
446
+ auto packageInfoString{ packageInfo.Stringify() };
447
+ auto infoFile{ co_await GetStatusFileAsync() };
448
+ if (infoFile == nullptr)
449
+ {
450
+ auto codePushFolder{ co_await GetCodePushFolderAsync() };
451
+ infoFile = co_await codePushFolder.CreateFileAsync(CodePushPackage::StatusFile);
452
+ }
453
+ co_await FileIO::WriteTextAsync(infoFile, packageInfoString);
454
+ co_return true;
455
+ }
456
+ }
@@ -0,0 +1,49 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #pragma once
5
+
6
+ #include <winrt/Windows.Data.Json.h>
7
+ #include <functional>
8
+
9
+ namespace Microsoft::CodePush::ReactNative
10
+ {
11
+ struct CodePushPackage
12
+ {
13
+ static constexpr std::wstring_view DiffManifestFileName{ L"hotcodepush.json" };
14
+ static constexpr std::wstring_view DownloadFileName{ L"download.zip" };
15
+ static constexpr std::wstring_view RelativeBundlePathKey{ L"bundlePath" };
16
+ static constexpr std::wstring_view StatusFile{ L"codepush.json" };
17
+ static constexpr std::wstring_view UpdateBundleFileName{ L"app.jsbundle" };
18
+ static constexpr std::wstring_view UpdateMetadataFileName{ L"app.json" };
19
+ static constexpr std::wstring_view UnzippedFolderName{ L"unzipped" };
20
+
21
+ static winrt::Windows::Foundation::IAsyncAction ClearUpdatesAsync();
22
+
23
+ static winrt::Windows::Foundation::IAsyncAction DownloadPackageAsync(
24
+ winrt::Windows::Data::Json::JsonObject& updatePackage,
25
+ std::wstring_view expectedBundleFileName,
26
+ std::wstring_view publicKey,
27
+ std::function<void(int64_t, int64_t)> progressCallback);
28
+
29
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Data::Json::JsonObject> GetCurrentPackageAsync();
30
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Data::Json::JsonObject> GetPreviousPackageAsync();
31
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFolder> GetCurrentPackageFolderAsync();
32
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFile> GetCurrentPackageBundleAsync();
33
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> GetCurrentPackageHashAsync();
34
+
35
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Data::Json::JsonObject> GetPackageAsync(std::wstring_view packageHash);
36
+
37
+ static winrt::Windows::Foundation::IAsyncOperation<bool> InstallPackageAsync(winrt::Windows::Data::Json::JsonObject updatePackage, bool removePendingUpdate);
38
+
39
+ static winrt::Windows::Foundation::IAsyncAction RollbackPackage();
40
+
41
+ private:
42
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFolder> GetCodePushFolderAsync();
43
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Data::Json::JsonObject> GetCurrentPackageInfoAsync();
44
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFolder> GetPackageFolderAsync(std::wstring_view packageHash);
45
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> GetPreviousPackageHashAsync();
46
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFile> GetStatusFileAsync();
47
+ static winrt::Windows::Foundation::IAsyncOperation<bool> UpdateCurrentPackageInfoAsync(winrt::Windows::Data::Json::JsonObject packageInfo);
48
+ };
49
+ }