diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18ddb70..91f06ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,8 +51,8 @@ jobs: - name: đź“ť Code Coverage report run: | - dotnet tool install --global dotnet-reportgenerator-globaltool --version 5.1.23 - reportgenerator -reports:${{github.workspace}}/coverage.cobertura.xml -targetdir:${{github.workspace}}/report -reporttypes:MarkdownSummaryGithub -filefilters:-*.g.cs "-classfilters:-WixSharp.*;-WingetIntune.Os.*;-WingetIntune.Internal.MsStore.*" -verbosity:Warning + dotnet tool install --global dotnet-reportgenerator-globaltool --version 5.2.5 + reportgenerator -reports:${{github.workspace}}/coverage.cobertura.xml -targetdir:${{github.workspace}}/report -reporttypes:MarkdownSummaryGithub -filefilters:-*.g.cs "-classfilters:-WixSharp.*;-WingetIntune.Os.*;-WingetIntune.Internal.MsStore.Models.*" -verbosity:Warning sed -i 's/# Summary/## đź“ť Code Coverage/g' ${{github.workspace}}/report/SummaryGithub.md sed -i 's/## Coverage/### đź“ť Code Coverage details/g' ${{github.workspace}}/report/SummaryGithub.md cat ${{github.workspace}}/report/*.md >> $GITHUB_STEP_SUMMARY diff --git a/WingetIntune.sln b/WingetIntune.sln index 6819253..508ad97 100644 --- a/WingetIntune.sln +++ b/WingetIntune.sln @@ -29,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svrooij.WinTuner.CmdLets", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4E745B8F-95AD-42CC-A462-EBA6896413E2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Winget.CommunityRepository.Ef", "src\Winget.CommunityRepository.Ef\Winget.CommunityRepository.Ef.csproj", "{516169B3-872B-443B-8736-27E2A08E7091}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Winget.CommunityRepository.Ef", "src\Winget.CommunityRepository.Ef\Winget.CommunityRepository.Ef.csproj", "{516169B3-872B-443B-8736-27E2A08E7091}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{4D1367F6-2076-481E-A7BD-0BFA6BEFCA3D}" EndProject diff --git a/src/Svrooij.WinTuner.CmdLets/Commands/DeployWtMsStoreApp.cs b/src/Svrooij.WinTuner.CmdLets/Commands/DeployWtMsStoreApp.cs new file mode 100644 index 0000000..928ded0 --- /dev/null +++ b/src/Svrooij.WinTuner.CmdLets/Commands/DeployWtMsStoreApp.cs @@ -0,0 +1,93 @@ +using Microsoft.Extensions.Logging; +using Svrooij.PowerShell.DependencyInjection; +using System; +using System.Management.Automation; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using WingetIntune.Graph; +using GraphModels = Microsoft.Graph.Beta.Models; + +namespace Svrooij.WinTuner.CmdLets.Commands; +/// +/// Create a MsStore app in Intune +/// Use this command to create an Microsoft Store app in Microsoft Intune +/// Documentation +/// +/// +/// Add Firefox to Intune, using interactive authentication +/// Deploy-WtMsStoreApp -PackageId 9NZVDKPMR9RD -Username admin@myofficetenant.onmicrosoft.com +/// +[Cmdlet(VerbsLifecycle.Deploy, "WtMsStoreApp", DefaultParameterSetName = nameof(PackageId))] +[OutputType(typeof(GraphModels.WinGetApp))] +public class DeployWtMsStoreApp : BaseIntuneCmdlet +{ + /// + /// The package id to upload to Intune. + /// + [Parameter( + Mandatory = true, + Position = 0, + ParameterSetName = nameof(PackageId), + ValueFromPipeline = false, + ValueFromPipelineByPropertyName = false, + HelpMessage = "The package id to upload to Intune.")] + public string? PackageId { get; set; } + + /// + /// Name of the app to look for, first match will be created. + /// + [Parameter( + Mandatory = true, + Position = 0, + ParameterSetName = nameof(SearchQuery), + ValueFromPipeline = false, + ValueFromPipelineByPropertyName = false, + HelpMessage = "Name of the app to look for, first match will be created.")] + public string? SearchQuery { get; set; } + + [ServiceDependency] + private ILogger? logger; + + [ServiceDependency] + private GraphStoreAppUploader? graphStoreAppUploader; + + [ServiceDependency] + private HttpClient? httpClient; + + /// + public override async Task ProcessRecordAsync(CancellationToken cancellationToken) + { + ValidateAuthenticationParameters(); + if (ParameterSetName == nameof(SearchQuery)) + { + ArgumentException.ThrowIfNullOrWhiteSpace(SearchQuery); + logger!.LogInformation("Searching package id for {searchQuery}", SearchQuery); + PackageId = await graphStoreAppUploader!.GetStoreIdForNameAsync(SearchQuery!, cancellationToken); + if (string.IsNullOrEmpty(PackageId)) + { + logger!.LogError("No package found for {searchQuery}", SearchQuery); + return; + } + } + + // At this moment the package ID should always be filled. + ArgumentException.ThrowIfNullOrWhiteSpace(PackageId); + + logger!.LogInformation("Uploading MSStore app {PackageId} to Intune", PackageId); + var graphServiceClient = CreateGraphServiceClient(httpClient!); + try + { + var app = await graphStoreAppUploader!.CreateStoreAppAsync(graphServiceClient, PackageId, cancellationToken); + + logger!.LogInformation("Created MSStore app {PackageId} with id {appId}", PackageId, app!.Id); + WriteObject(app); + } + catch (Exception ex) + { + logger!.LogError(ex, "Error creating MSStore app {PackageId}", PackageId); + } + + + } +} diff --git a/src/Svrooij.WinTuner.CmdLets/Commands/Update-WtIntuneApp.cs b/src/Svrooij.WinTuner.CmdLets/Commands/Update-WtIntuneApp.cs index 789c9e6..ac4238a 100644 --- a/src/Svrooij.WinTuner.CmdLets/Commands/Update-WtIntuneApp.cs +++ b/src/Svrooij.WinTuner.CmdLets/Commands/Update-WtIntuneApp.cs @@ -82,7 +82,7 @@ public override async Task ProcessRecordAsync(CancellationToken cancellationToke if (Categories is not null && Categories.Any()) { logger?.LogInformation("Adding categories to app {appId}", AppId); - await graphServiceClient.AddIntuneCategoriesToApp(AppId!, Categories, cancellationToken); + await graphServiceClient.AddIntuneCategoriesToAppAsync(AppId!, Categories, cancellationToken); } if ((AvailableFor is not null && AvailableFor.Any()) || diff --git a/src/WingetIntune/Graph/GraphAppUploader.cs b/src/WingetIntune/Graph/GraphAppUploader.cs index 0512cd2..b4d68e1 100644 --- a/src/WingetIntune/Graph/GraphAppUploader.cs +++ b/src/WingetIntune/Graph/GraphAppUploader.cs @@ -2,11 +2,6 @@ using Microsoft.Graph.Beta; using Microsoft.Graph.Beta.Models; using Microsoft.Graph.Beta.Models.ODataErrors; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using WingetIntune.Intune; using WingetIntune.Models; diff --git a/src/WingetIntune/Graph/GraphStoreAppUploader.cs b/src/WingetIntune/Graph/GraphStoreAppUploader.cs new file mode 100644 index 0000000..7f05919 --- /dev/null +++ b/src/WingetIntune/Graph/GraphStoreAppUploader.cs @@ -0,0 +1,96 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Graph.Beta; +using Microsoft.Graph.Beta.Models; +using Microsoft.Graph.Beta.Models.ODataErrors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WingetIntune.Models; + +namespace WingetIntune.Graph; +public class GraphStoreAppUploader +{ + private readonly ILogger logger; + private readonly IFileManager fileManager; + private readonly Internal.MsStore.MicrosoftStoreClient microsoftStoreClient; + private readonly Mapper mapper = new(); + + public GraphStoreAppUploader(ILogger logger, IFileManager fileManager, Internal.MsStore.MicrosoftStoreClient microsoftStoreClient) + { + ArgumentNullException.ThrowIfNull(logger); + ArgumentNullException.ThrowIfNull(fileManager); + ArgumentNullException.ThrowIfNull(microsoftStoreClient); + this.logger = logger; + this.fileManager = fileManager; + this.microsoftStoreClient = microsoftStoreClient; + } + + public Task GetStoreIdForNameAsync(string searchstring, CancellationToken cancellationToken) + { + ArgumentException.ThrowIfNullOrEmpty(searchstring); + return microsoftStoreClient.GetPackageIdForFirstMatchAsync(searchstring, cancellationToken); + } + + public async Task CreateStoreAppAsync(GraphServiceClient graphServiceClient, string packageId, CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(graphServiceClient); + ArgumentException.ThrowIfNullOrEmpty(packageId); + ArgumentNullException.ThrowIfNull(cancellationToken); + + var catalog = await microsoftStoreClient.GetDisplayCatalogAsync(packageId!, cancellationToken); + ArgumentNullException.ThrowIfNull(catalog); + if (!(catalog.Products?.Count() > 0)) + { + logger.LogError("No products found for {packageId}", packageId); + return null; + } + + var app = mapper.ToWinGetApp(catalog!); + + try + { + var imagePath = Path.GetTempFileName(); + var uriPart = catalog.Products.First()?.LocalizedProperties.FirstOrDefault()?.Images?.FirstOrDefault(i => i.Height == 300 && i.Width == 300)?.Uri; // && i.ImagePurpose.Equals("Tile", StringComparison.OrdinalIgnoreCase) + if (uriPart is null) + { + logger.LogWarning("No image found for {packageId}", packageId); + } + else + { + var imageUrl = $"http:{uriPart}"; + await fileManager.DownloadFileAsync(imageUrl, imagePath, overrideFile: true, cancellationToken: cancellationToken); + app.LargeIcon = new MimeContent + { + Type = "image/png", + Value = await fileManager.ReadAllBytesAsync(imagePath, cancellationToken) + }; + } + + } + catch (Exception ex) + { + logger.LogError(ex, "Error downloading image for {packageId}", packageId); + } + + logger.LogInformation("Creating new WinGetApp (MsStore) for {packageId}", packageId); + + try + { + var createdApp = await graphServiceClient.DeviceAppManagement.MobileApps.PostAsync(app, cancellationToken); + logger.LogInformation("MsStore app {packageIdentifier} created in Intune {appId}", createdApp?.PackageIdentifier, createdApp?.Id); + return createdApp; + } + catch (ODataError ex) + { + logger.LogError(ex, "Error publishing app {message}", ex.Error?.Message); + throw; + } + catch (Exception ex) + { + logger.LogError(ex, "Error publishing app"); + throw; + } + } +} diff --git a/src/WingetIntune/Graph/GraphWorkflows.cs b/src/WingetIntune/Graph/GraphWorkflows.cs index 9a9c3dc..5e5ca00 100644 --- a/src/WingetIntune/Graph/GraphWorkflows.cs +++ b/src/WingetIntune/Graph/GraphWorkflows.cs @@ -8,7 +8,7 @@ namespace WingetIntune.Graph; public static class GraphWorkflows { - public static async Task AddIntuneCategoriesToApp(this GraphServiceClient graphServiceClient, string appId, string[] categories, CancellationToken cancellationToken) + public static async Task AddIntuneCategoriesToAppAsync(this GraphServiceClient graphServiceClient, string appId, string[] categories, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(graphServiceClient); ArgumentException.ThrowIfNullOrEmpty(appId); diff --git a/src/WingetIntune/Internal/MsStore/MicrosoftStoreDetails.cs b/src/WingetIntune/Internal/MsStore/MicrosoftStoreDetails.cs deleted file mode 100644 index 492b198..0000000 --- a/src/WingetIntune/Internal/MsStore/MicrosoftStoreDetails.cs +++ /dev/null @@ -1,223 +0,0 @@ - -namespace WingetIntune.Internal.MsStore; - -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -public class MicrosoftStoreDetails -{ - public object allowedPlatforms { get; set; } - public object skus { get; set; } - public object platforms { get; set; } - public bool accessible { get; set; } - public bool isDeviceCompanionApp { get; set; } - public MicrosoftStoreDetailsSupporturi[] supportUris { get; set; } - public object[] features { get; set; } - public string[] supportedLanguages { get; set; } - public object legalUrl { get; set; } - public object[] notes { get; set; } - public object publisherCopyrightInformation { get; set; } - public object additionalLicenseTerms { get; set; } - public int approximateSizeInBytes { get; set; } - public object appWebsiteUrl { get; set; } - public object permissionsRequired { get; set; } - public object requiredHardware { get; set; } - public object recommendedHardware { get; set; } - public object hardwareWarnings { get; set; } - public string version { get; set; } - public DateTime lastUpdateDateUtc { get; set; } - public object osProductInformation { get; set; } - public string categoryId { get; set; } - public object subcategoryId { get; set; } - public object addOnPriceRange { get; set; } - public object deviceFamilyDisallowedReason { get; set; } - public object builtFor { get; set; } - public object trailers { get; set; } - public object pdpBackgroundColor { get; set; } - public bool containsDownloadPackage { get; set; } - public MicrosoftStoreDetailsSystemrequirements systemRequirements { get; set; } - public object installationTerms { get; set; } - public object warningMessages { get; set; } - public bool isMicrosoftProduct { get; set; } - public bool hasParentBundles { get; set; } - public bool hasAlternateEditions { get; set; } - public int videoProductType { get; set; } - public bool isMsixvc { get; set; } - public object subtitle { get; set; } - public object capabilitiesTable { get; set; } - public bool isDownloadable { get; set; } - public object promoMessage { get; set; } - public object promoEndDateUtc { get; set; } - public object packageFamilyName { get; set; } - public object alternateId { get; set; } - public object curatedBGColor { get; set; } - public object curatedFGColor { get; set; } - public object curatedImageUrl { get; set; } - public object curatedTitle { get; set; } - public object curatedDescription { get; set; } - public object artistName { get; set; } - public object artistId { get; set; } - public object albumTitle { get; set; } - public object albumProductId { get; set; } - public bool isExplicit { get; set; } - public int durationInSecond { get; set; } - public object incompatibleReason { get; set; } - public bool hasThirdPartyAPIs { get; set; } - public object autosuggestSubtitle { get; set; } - public object merchandizedProductType { get; set; } - public string catalogSource { get; set; } - public MicrosoftStoreDetailsScreenshot[] screenshots { get; set; } - public object[] additionalTermLinks { get; set; } - public object promotionDaysLeft { get; set; } - public string[] categories { get; set; } - public MicrosoftStoreDetailsImage[] images { get; set; } - public string productId { get; set; } - public object externalUri { get; set; } - public string title { get; set; } - public string shortTitle { get; set; } - public object titleLayout { get; set; } - public string description { get; set; } - public string publisherName { get; set; } - public string publisherId { get; set; } - public object publisherAddress { get; set; } - public object publisherPhoneNumber { get; set; } - public bool isUniversal { get; set; } - public string language { get; set; } - public object bgColor { get; set; } - public object fgColor { get; set; } - public float averageRating { get; set; } - public string ratingCount { get; set; } - public bool hasFreeTrial { get; set; } - public string productType { get; set; } - public int price { get; set; } - public object currencySymbol { get; set; } - public object currencyCode { get; set; } - public string displayPrice { get; set; } - public object strikethroughPrice { get; set; } - public string developerName { get; set; } - public string productFamilyName { get; set; } - public string mediaType { get; set; } - public object contentIds { get; set; } - public string[] packageFamilyNames { get; set; } - public string subcategoryName { get; set; } - public MicrosoftStoreDetailsAlternateid[] alternateIds { get; set; } - public string collectionItemType { get; set; } - public object numberOfSeasons { get; set; } - public DateTime releaseDateUtc { get; set; } - public int durationInSeconds { get; set; } - public bool isCompatible { get; set; } - public bool isPurchaseEnabled { get; set; } - public object developerOptOutOfSDCardInstall { get; set; } - public bool hasAddOns { get; set; } - public bool hasThirdPartyIAPs { get; set; } - public object voiceTitle { get; set; } - public bool hideFromCollections { get; set; } - public bool hideFromDownloadsAndUpdates { get; set; } - public bool gamingOptionsXboxLive { get; set; } - public string availableDevicesDisplayText { get; set; } - public object availableDevicesNarratorText { get; set; } - public bool isGamingAppOnly { get; set; } - public bool isSoftBlocked { get; set; } - public object tileLayout { get; set; } - public object typeTag { get; set; } - public object longDescription { get; set; } - public object schema { get; set; } - public object[] badges { get; set; } - public MicrosoftStoreDetailsProductrating[] productRatings { get; set; } - public object installer { get; set; } - public string privacyUrl { get; set; } - public string iconUrl { get; set; } - public MicrosoftStoreDetailsLargepromotionimage largePromotionImage { get; set; } - public string iconUrlBackground { get; set; } -} - -public class MicrosoftStoreDetailsSystemrequirements -{ - public MicrosoftStoreDetailsMinimum minimum { get; set; } - public object recomended { get; set; } -} - -public class MicrosoftStoreDetailsMinimum -{ - public string title { get; set; } - public MicrosoftStoreDetailsItem[] items { get; set; } -} - -public class MicrosoftStoreDetailsItem -{ - public string level { get; set; } - public string itemCode { get; set; } - public string name { get; set; } - public string description { get; set; } - public string validationHint { get; set; } - public bool isValidationPassed { get; set; } -} - -public class MicrosoftStoreDetailsLargepromotionimage -{ - public string imageType { get; set; } - public string url { get; set; } - public string caption { get; set; } - public int height { get; set; } - public int width { get; set; } - public string backgroundColor { get; set; } - public string foregroundColor { get; set; } - public string imagePositionInfo { get; set; } -} - -public class MicrosoftStoreDetailsSupporturi -{ - public object uri { get; set; } -} - -public class MicrosoftStoreDetailsScreenshot -{ - public string imageType { get; set; } - public string url { get; set; } - public string caption { get; set; } - public int height { get; set; } - public int width { get; set; } - public string backgroundColor { get; set; } - public string foregroundColor { get; set; } - public string imagePositionInfo { get; set; } -} - -public class MicrosoftStoreDetailsImage -{ - public string imageType { get; set; } - public string url { get; set; } - public string caption { get; set; } - public int height { get; set; } - public int width { get; set; } - public string backgroundColor { get; set; } - public string foregroundColor { get; set; } - public string imagePositionInfo { get; set; } -} - -public class MicrosoftStoreDetailsAlternateid -{ - public object type { get; set; } - public string alternateIdType { get; set; } - public string alternateIdValue { get; set; } - public string alternatedIdTypeString { get; set; } -} - -public class MicrosoftStoreDetailsProductrating -{ - public string ratingSystem { get; set; } - public string ratingSystemShortName { get; set; } - public string ratingSystemId { get; set; } - public string ratingSystemUrl { get; set; } - public string ratingValue { get; set; } - public string ratingValueLogoUrl { get; set; } - public int ratingAge { get; set; } - public bool restrictMetadata { get; set; } - public bool restrictPurchase { get; set; } - public object[] ratingDescriptors { get; set; } - public object[] ratingDescriptorLogoUrls { get; set; } - public object[] ratingDisclaimers { get; set; } - public string[] interactiveElements { get; set; } - public string longName { get; set; } - public string shortName { get; set; } - public string description { get; set; } -} - -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. diff --git a/src/WingetIntune/Internal/MsStore/DisplayCatalog.cs b/src/WingetIntune/Internal/MsStore/Models/DisplayCatalog.cs similarity index 99% rename from src/WingetIntune/Internal/MsStore/DisplayCatalog.cs rename to src/WingetIntune/Internal/MsStore/Models/DisplayCatalog.cs index a8a764d..60d421f 100644 --- a/src/WingetIntune/Internal/MsStore/DisplayCatalog.cs +++ b/src/WingetIntune/Internal/MsStore/Models/DisplayCatalog.cs @@ -1,4 +1,4 @@ -namespace WingetIntune.Internal.MsStore; +namespace WingetIntune.Internal.MsStore.Models; public class DisplayCatalogResponse { @@ -132,6 +132,11 @@ public class Image public string UnscaledImageSHA256Hash { get; set; } public string Uri { get; set; } public int Width { get; set; } + + public override string ToString() + { + return $"{ImagePurpose} ({Width}x{Height})"; + } } public class Marketproperty diff --git a/src/WingetIntune/Internal/MsStore/MicrosoftStoreManifest.cs b/src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreManifest.cs similarity index 97% rename from src/WingetIntune/Internal/MsStore/MicrosoftStoreManifest.cs rename to src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreManifest.cs index 960ca91..727f70b 100644 --- a/src/WingetIntune/Internal/MsStore/MicrosoftStoreManifest.cs +++ b/src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreManifest.cs @@ -1,5 +1,4 @@ - -namespace WingetIntune.Internal.MsStore; +namespace WingetIntune.Internal.MsStore.Models; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public class MicrosoftStoreManifest diff --git a/src/WingetIntune/Internal/MsStore/MicrosoftStoreSearch.cs b/src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreSearch.cs similarity index 86% rename from src/WingetIntune/Internal/MsStore/MicrosoftStoreSearch.cs rename to src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreSearch.cs index d66758e..7abd2aa 100644 --- a/src/WingetIntune/Internal/MsStore/MicrosoftStoreSearch.cs +++ b/src/WingetIntune/Internal/MsStore/Models/MicrosoftStoreSearch.cs @@ -1,4 +1,4 @@ -namespace WingetIntune.Internal.MsStore; +namespace WingetIntune.Internal.MsStore.Models; public class MicrosoftStoreSearchRequest { public required MicrosoftStoreSearchQuery Query { get; set; } @@ -15,6 +15,11 @@ public class MicrosoftStoreSearchResult { public string type { get; set; } public MicrosoftStoreSearchData[] Data { get; set; } + + public override string ToString() + { + return $"[{nameof(MicrosoftStoreSearchResult)}] {Data.Length} results"; + } } public class MicrosoftStoreSearchData diff --git a/src/WingetIntune/Internal/MsStore/StoreClient.cs b/src/WingetIntune/Internal/MsStore/StoreClient.cs index 03f55ee..d648875 100644 --- a/src/WingetIntune/Internal/MsStore/StoreClient.cs +++ b/src/WingetIntune/Internal/MsStore/StoreClient.cs @@ -2,6 +2,7 @@ using System.Net.Http.Headers; using System.Net.Http.Json; using System.Text.Json; +using WingetIntune.Internal.MsStore.Models; namespace WingetIntune.Internal.MsStore; @@ -46,26 +47,7 @@ public MicrosoftStoreClient(HttpClient httpClient, ILogger return await response.Content.ReadFromJsonAsync(cancellationToken: cancellation); } - public async Task GetStoreDetailsAsync(string packageId, CancellationToken cancellation) - { - LogGetDetails(packageId); - var url = $"https://apps.microsoft.com/store/api/ProductsDetails/GetProductDetailsById/{packageId}?hl=en-US&gl=US"; - //var url = $"https://storeedgefd.dsx.mp.microsoft.com/v9.0/productDetails/{packageId}?hl=en-US&gl=US"; - try - { - var response = await _httpClient.GetAsync(url, cancellation); - response.EnsureSuccessStatusCode(); - var text = await response.Content.ReadAsStringAsync(cancellation); - return await response.Content.ReadFromJsonAsync(cancellationToken: cancellation); - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to get details for {packageId} from Microsoft Store", packageId); - return null; - } - } - - private async Task Search(string searchString, CancellationToken cancellationToken) + public async Task Search(string searchString, CancellationToken cancellationToken) { var url = "https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch"; var body = new MicrosoftStoreSearchRequest @@ -94,6 +76,4 @@ public MicrosoftStoreClient(HttpClient httpClient, ILogger [LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Getting manifest for {packageId} from Microsoft Store")] private partial void LogGetManifest(string packageId); - [LoggerMessage(EventId = 3, Level = LogLevel.Information, Message = "Getting details for {packageId} from Microsoft Store")] - private partial void LogGetDetails(string packageId); } diff --git a/src/WingetIntune/Internal/MsStore/store-requests.http b/src/WingetIntune/Internal/MsStore/store-requests.http new file mode 100644 index 0000000..2c7e01b --- /dev/null +++ b/src/WingetIntune/Internal/MsStore/store-requests.http @@ -0,0 +1,21 @@ +# For more info on HTTP files go to https://aka.ms/vs/httpfile + +POST https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch HTTP/1.1 +Content-Type: application/json + +{ + "Query": { + "KeyWord": "FireFox", + "MatchType": "Substring" + } +} + +### + +GET https://displaycatalog.mp.microsoft.com/v7.0/products?bigIds=9NZVDKPMR9RD&market=US&languages=en-us + + +### + +GET https://storeedgefd.dsx.mp.microsoft.com/v9.0/packageManifests/9NZVDKPMR9RD +Accept: application/json diff --git a/src/WingetIntune/Intune/IntuneManager.cs b/src/WingetIntune/Intune/IntuneManager.cs index b6b1840..aba556b 100644 --- a/src/WingetIntune/Intune/IntuneManager.cs +++ b/src/WingetIntune/Intune/IntuneManager.cs @@ -30,8 +30,9 @@ public partial class IntuneManager private readonly Internal.MsStore.MicrosoftStoreClient microsoftStoreClient; private readonly PublicClientAuth publicClient; private readonly GraphAppUploader graphAppUploader; + private readonly GraphStoreAppUploader graphStoreAppUploader; - public IntuneManager(ILoggerFactory? loggerFactory, IFileManager fileManager, IProcessManager processManager, HttpClient httpClient, IAzureFileUploader azureFileUploader, Internal.MsStore.MicrosoftStoreClient microsoftStoreClient, PublicClientAuth publicClient, IIntunePackager intunePackager, IWingetRepository wingetRepository, GraphAppUploader graphAppUploader) + public IntuneManager(ILoggerFactory? loggerFactory, IFileManager fileManager, IProcessManager processManager, HttpClient httpClient, IAzureFileUploader azureFileUploader, Internal.MsStore.MicrosoftStoreClient microsoftStoreClient, PublicClientAuth publicClient, IIntunePackager intunePackager, IWingetRepository wingetRepository, GraphAppUploader graphAppUploader, GraphStoreAppUploader graphStoreAppUploader) { this.loggerFactory = loggerFactory ?? new NullLoggerFactory(); this.logger = this.loggerFactory.CreateLogger(); @@ -44,6 +45,7 @@ public IntuneManager(ILoggerFactory? loggerFactory, IFileManager fileManager, IP this.intunePackager = intunePackager; this.wingetRepository = wingetRepository; this.graphAppUploader = graphAppUploader; + this.graphStoreAppUploader = graphStoreAppUploader; } public async Task GenerateMsiPackage(string tempFolder, string outputFolder, Models.PackageInfo packageInfo, PackageOptions packageOptions, CancellationToken cancellationToken = default) @@ -349,47 +351,26 @@ public async Task PublishStoreAppAsync(IntunePublishOptions options, if (!string.IsNullOrEmpty(searchString)) { - var id = await microsoftStoreClient.GetPackageIdForFirstMatchAsync(searchString, cancellationToken); + var id = await graphStoreAppUploader.GetStoreIdForNameAsync(searchString, cancellationToken); return await PublishStoreAppAsync(options, id, null, cancellationToken); } - var catalog = await microsoftStoreClient.GetDisplayCatalogAsync(packageId!, cancellationToken); - - var app = mapper.ToWinGetApp(catalog!); - - try - { - var imagePath = Path.GetTempFileName(); - var imageUrl = "https:" + catalog!.Products.First().LocalizedProperties.First().Images.First(i => i.Height == 300 && i.Width == 300 && i.ImagePurpose.Equals("Tile", StringComparison.OrdinalIgnoreCase)).Uri; - await fileManager.DownloadFileAsync(imageUrl, imagePath, overrideFile: true, cancellationToken: cancellationToken); - app.LargeIcon = new MimeContent - { - Type = "image/png", - Value = await fileManager.ReadAllBytesAsync(imagePath, cancellationToken) - }; - } - catch (Exception ex) - { - logger.LogError(ex, "Error downloading image for {packageId}", packageId); - } - GraphServiceClient graphServiceClient = CreateGraphClientFromOptions(options); try { - var appCreated = await graphServiceClient.DeviceAppManagement.MobileApps.PostAsync(app, cancellationToken); - logger.LogInformation("Store app published to Intune with id {id}", appCreated!.Id); + var appCreated = await graphStoreAppUploader.CreateStoreAppAsync(graphServiceClient, packageId!, cancellationToken); if (appCreated == null) { throw new Exception("App was not created"); } if (options.Categories != null && options.Categories.Any()) { - await AddCategoriesToApp(graphServiceClient, appCreated.Id!, options.Categories, cancellationToken); + await graphServiceClient.AddIntuneCategoriesToAppAsync(appCreated!.Id!, options.Categories, cancellationToken); } if (options.AvailableFor.Any() || options.RequiredFor.Any() || options.UninstallFor.Any()) { - await AssignAppAsync(graphServiceClient, appCreated.Id!, options.RequiredFor, options.AvailableFor, options.UninstallFor, false, cancellationToken); + await graphServiceClient.AssignAppAsync(appCreated!.Id!, options.RequiredFor, options.AvailableFor, options.UninstallFor, options.AddAutoUpdateSetting, cancellationToken); } return appCreated; } @@ -424,7 +405,7 @@ private async Task AddCategoriesToApp(GraphServiceClient graphServiceClient, str try { - await GraphWorkflows.AddIntuneCategoriesToApp(graphServiceClient, appId, categories, cancellationToken); + await GraphWorkflows.AddIntuneCategoriesToAppAsync(graphServiceClient, appId, categories, cancellationToken); } catch (Exception ex) { diff --git a/src/WingetIntune/Models/Mapper.cs b/src/WingetIntune/Models/Mapper.cs index cc41332..e4b6e1c 100644 --- a/src/WingetIntune/Models/Mapper.cs +++ b/src/WingetIntune/Models/Mapper.cs @@ -1,7 +1,7 @@ using Microsoft.Graph.Beta.Models; using Riok.Mapperly.Abstractions; using System.Text.RegularExpressions; -using WingetIntune.Internal.MsStore; +using WingetIntune.Internal.MsStore.Models; using WingetIntune.Intune; namespace WingetIntune.Models; @@ -121,15 +121,15 @@ public WinGetApp ToWinGetApp(MicrosoftStoreManifest storeManifest) }; app.Developer = app.Publisher; app.Description ??= locale.ShortDescription; - app.Notes = $"Generated by {nameof(WingetIntune)} at {DateTimeOffset.UtcNow} [WingetIntune|store|{storeManifest.Data.PackageIdentifier}]"; + app.Notes = $"Generated by WinTuner at {DateTimeOffset.UtcNow} [WinTuner|store|{storeManifest.Data.PackageIdentifier}]"; return app; } public WinGetApp ToWinGetApp(DisplayCatalogResponse displayCatalogResponse) { var product = displayCatalogResponse.Products.FirstOrDefault(); - var displaySku = product?.DisplaySkuAvailabilities.FirstOrDefault()?.Sku.LocalizedProperties.FirstOrDefault(); - var productProperties = product?.LocalizedProperties.FirstOrDefault(); + var displaySku = product?.DisplaySkuAvailabilities?.FirstOrDefault()?.Sku.LocalizedProperties.FirstOrDefault(); + var productProperties = product?.LocalizedProperties?.FirstOrDefault(); var app = new WinGetApp(); app.DisplayName = displaySku!.SkuTitle; app.PackageIdentifier = product!.ProductId; @@ -142,7 +142,7 @@ public WinGetApp ToWinGetApp(DisplayCatalogResponse displayCatalogResponse) RunAsAccount = RunAsAccountType.System, }; app.Developer = app.Publisher = productProperties.PublisherName; - app.Notes = $"Generated by {nameof(WingetIntune)} at {DateTimeOffset.UtcNow} [WingetIntune|store|{product!.ProductId}]"; + app.Notes = $"Generated by WinTuner at {DateTimeOffset.UtcNow} [WinTuner|store|{product!.ProductId}]"; return app; } diff --git a/src/WingetIntune/WingetServiceCollectionExtension.cs b/src/WingetIntune/WingetServiceCollectionExtension.cs index b1e18a2..95066a6 100644 --- a/src/WingetIntune/WingetServiceCollectionExtension.cs +++ b/src/WingetIntune/WingetServiceCollectionExtension.cs @@ -40,6 +40,7 @@ public static IServiceCollection AddWingetServices(this IServiceCollection servi services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddTransient(); services.AddSingleton(); diff --git a/tests/WingetIntune.Tests/Graph/GraphStoreAppUploaderTests.cs b/tests/WingetIntune.Tests/Graph/GraphStoreAppUploaderTests.cs new file mode 100644 index 0000000..a486aed --- /dev/null +++ b/tests/WingetIntune.Tests/Graph/GraphStoreAppUploaderTests.cs @@ -0,0 +1,119 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Graph.Beta; +using System.Text; +using WingetIntune.Graph; +using WingetIntune.Internal.MsStore; + +namespace WingetIntune.Tests.Graph; + +public class GraphStoreAppUploaderTests +{ + + [Fact] + public async Task CreateStoreAppAsync_WithValidPackageId_CreatesAppSuccessfully() + { + const string packageId = "9NZVDKPMR9RD"; + const string manifestData = @"{""Products"":[{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""DeveloperName"":"""",""DisplayPlatformProperties"":null,""PublisherName"":""Mozilla"",""PublisherAddress"":null,""PublisherWebsiteUri"":""https://www.mozilla.org/firefox/"",""SupportUri"":""https://support.mozilla.org/products/firefox"",""SupportPhone"":null,""EligibilityProperties"":null,""Franchises"":[],""Images"":[{""FileId"":""3071430996971663174"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":14069,""ForegroundColor"":"""",""Height"":100,""ImagePositionInfo"":"""",""ImagePurpose"":""Logo"",""UnscaledImageSHA256Hash"":""NmfuVtG1XGBx/p8HUht9J+giOGcMN5oIea7M4xjN/H8="",""Uri"":""//store-images.s-microsoft.com/image/apps.26422.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.37a70641-3de3-41b1-9c94-3cb0cfc663c2"",""Width"":100},{""FileId"":""3004232197050559163"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":63556,""ForegroundColor"":"""",""Height"":300,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""S5CO1XDVz6JpQlsSlJWWEN45hRkKGDwyapmRK6A66qA="",""Uri"":""//store-images.s-microsoft.com/image/apps.36939.14473293538384797.0ec149d2-d2b5-48a8-afd4-66986d387ec9.820a68fb-12dd-45a1-9a5a-1f141fc93f29"",""Width"":300},{""FileId"":""3008762446945936351"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":7710,""ForegroundColor"":"""",""Height"":88,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""9z/FtCO6NlcynHvQQ6gvOoXTw/h8ZUzdrOxMg+QMt2Q="",""Uri"":""//store-images.s-microsoft.com/image/apps.16375.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.a6fb32ca-2223-41dc-8d73-8395066b1c4f"",""Width"":88},{""FileId"":""3052106644741011285"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":187605,""ForegroundColor"":"""",""Height"":620,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""6gpjyrwSRgQ9Fa4NbghXdgJsrO/cs7vxFM+Y/mkBCDg="",""Uri"":""//store-images.s-microsoft.com/image/apps.2794.14473293538384797.0ec149d2-d2b5-48a8-afd4-66986d387ec9.5a7e12ea-3baa-41de-ae7c-e58c7d22b644"",""Width"":620},{""FileId"":""3031096784199183752"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":8923,""ForegroundColor"":"""",""Height"":142,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""dhSnfnKPaSBBYSgcsMpkSPeuawH/9ZSKTZE3LW+hpNM="",""Uri"":""//store-images.s-microsoft.com/image/apps.5238.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.13c8d648-665d-4185-8b32-beb922c3a9d1"",""Width"":142},{""FileId"":""3028587524167049996"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":17159,""ForegroundColor"":"""",""Height"":300,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""AjdCKOV39U/zZ91jWgO3Uc0gJy8DZ4tNs46DxTrPoPs="",""Uri"":""//store-images.s-microsoft.com/image/apps.14082.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.abebba2b-9232-4dc4-a59c-0ded036614e4"",""Width"":620},{""FileId"":""3000180573878009204"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":2219458,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/0"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""We95BmfhVSMei0EwA/W2IN8vfUIrIE1KxMRNl/bNpu0="",""Uri"":""//store-images.s-microsoft.com/image/apps.61273.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.836cb591-5b2e-480c-abe0-fbef3445148c"",""Width"":3840},{""FileId"":""3001975626805331357"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":1142645,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/1"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""RxzoePoLqML4h7d/kM4yqb0vbQQRd+mK+uOyI5S0814="",""Uri"":""//store-images.s-microsoft.com/image/apps.7239.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.2836ec17-3608-4c59-955b-e33a4ddbe09a"",""Width"":3840},{""FileId"":""3051311566860831267"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":1435423,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/2"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""sf+mRDniEBQEybyQg3H2FJ+YDSdRD79bK2ZjQARm9Tc="",""Uri"":""//store-images.s-microsoft.com/image/apps.65457.14473293538384797.c7c6f980-349e-4aec-8b21-c9a6aba30011.325858ad-e348-4660-95b8-d2f66200e3fc"",""Width"":3840},{""FileId"":""3048171808590640430"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":2744619,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/3"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""NeoziSi4gk+vLi5eIcXPS03Cq1hY5u8xGMAohxBXA54="",""Uri"":""//store-images.s-microsoft.com/image/apps.59957.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.7cf8905f-6469-422f-8aed-c9bc151a97c4"",""Width"":3840},{""FileId"":""3008914828876618251"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":881119,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/4"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""Xt+ESkKx6rAGAqMWPrfv+myQvniyCYFJnWFinDlk6g8="",""Uri"":""//store-images.s-microsoft.com/image/apps.57182.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.b1631027-7eff-4a82-b06f-956df2b0f6f8"",""Width"":3840}],""Videos"":[],""ProductDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""ProductTitle"":""Mozilla Firefox"",""ShortTitle"":""Firefox"",""SortTitle"":"""",""FriendlyTitle"":null,""ShortDescription"":"""",""SearchTitles"":[],""VoiceTitle"":"""",""RenderGroupDetails"":null,""ProductDisplayRanks"":[],""InteractiveModelConfig"":null,""Interactive3DEnabled"":false,""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z"",""OriginalReleaseDateFriendlyName"":"""",""MinimumUserAge"":0,""ContentRatings"":[{""RatingSystem"":""ESRB"",""RatingId"":""ESRB:E"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""ESRB:UnrInt""]},{""RatingSystem"":""PEGI"",""RatingId"":""PEGI:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""PEGI:UnrInt""]},{""RatingSystem"":""DJCTQ"",""RatingId"":""DJCTQ:L"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""DJCTQ:UnrInt""]},{""RatingSystem"":""USK"",""RatingId"":""USK:Everyone"",""RatingDescriptors"":[""USK:ConDifAge""],""RatingDisclaimers"":[],""InteractiveElements"":[""USK:UnrInt""]},{""RatingSystem"":""IARC"",""RatingId"":""IARC:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""IARC:UnrInt""]},{""RatingSystem"":""PCBP"",""RatingId"":""PCBP:0"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""PCBP:UnrInt""]},{""RatingSystem"":""CSRR"",""RatingId"":""CSRR:G"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]},{""RatingSystem"":""CCC"",""RatingId"":""CCC:TE"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]},{""RatingSystem"":""Microsoft"",""RatingId"":""Microsoft:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]}],""RelatedProducts"":[],""UsageData"":[{""AggregateTimeSpan"":""7Days"",""AverageRating"":4.5,""PlayCount"":0,""RatingCount"":199,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""},{""AggregateTimeSpan"":""30Days"",""AverageRating"":4.4,""PlayCount"":0,""RatingCount"":416,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""},{""AggregateTimeSpan"":""AllTime"",""AverageRating"":4.5,""PlayCount"":0,""RatingCount"":20348,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""}],""BundleConfig"":null,""Markets"":[""US""]}],""ProductASchema"":""Product;3"",""ProductBSchema"":""ProductUnifiedApp;3"",""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""Attributes"":[{""Name"":""BroadcastSupport"",""Minimum"":null,""Maximum"":null,""ApplicablePlatforms"":null,""Group"":null}],""CanInstallToSDCard"":false,""Category"":""Productivity"",""SubCategory"":"""",""Categories"":null,""Extensions"":null,""IsAccessible"":false,""IsLineOfBusinessApp"":false,""IsPublishedToLegacyWindowsPhoneStore"":false,""IsPublishedToLegacyWindowsStore"":false,""IsSettingsApp"":false,""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""PackageIdentityName"":""Mozilla.Firefox"",""PublisherCertificateName"":""CN=082E9164-EE6C-4EC8-B62C-441FAE7BEFA1"",""PublisherId"":""77577580"",""XboxLiveTier"":null,""XboxXPA"":null,""XboxCrossGenSetId"":null,""XboxConsoleGenOptimized"":null,""XboxConsoleGenCompatible"":null,""XboxLiveGoldRequired"":false,""XBOX"":{},""ExtendedClientMetadata"":{},""OwnershipType"":null,""PdpBackgroundColor"":""#FFFFFF"",""HasAddOns"":false,""RevisionId"":""2024-04-30T14:41:20.5900076Z""},""AlternateIds"":[{""IdType"":""LegacyWindowsStoreProductId"",""Value"":""70bed52e-e1d3-467f-96b1-f4d474846515""},{""IdType"":""LegacyWindowsPhoneProductId"",""Value"":""60c1b112-072c-4657-b28d-d65f06e9d660""},{""IdType"":""XboxTitleId"",""Value"":""1728623981""}],""DomainDataVersion"":null,""IngestionSource"":""DCE"",""IsMicrosoftProduct"":false,""PreferredSkuId"":""0010"",""ProductType"":""Application"",""ValidationData"":{""PassedValidation"":false,""RevisionId"":""2024-04-30T14:41:20.5900076Z||.||95df8e43-f7a7-43f0-a00b-149bf8a386b1||1152921505697685831||Null||fullrelease"",""ValidationResultUri"":""""},""MerchandizingTags"":[],""PartD"":"""",""ProductFamily"":""Apps"",""SchemaVersion"":""3"",""ProductKind"":""Application"",""ProductPolicies"":{},""DisplaySkuAvailabilities"":[{""Sku"":{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""Contributors"":[],""Features"":[],""MinimumNotes"":"""",""RecommendedNotes"":"""",""ReleaseNotes"":""A faster, more intuitive Firefox now available in the Windows App Store"",""DisplayPlatformProperties"":null,""SkuDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""SkuTitle"":""Mozilla Firefox"",""SkuButtonTitle"":"""",""DeliveryDateOverlay"":null,""SkuDisplayRank"":[],""TextResources"":null,""Images"":[],""LegalText"":{""AdditionalLicenseTerms"":"""",""Copyright"":"""",""CopyrightUri"":"""",""PrivacyPolicy"":"""",""PrivacyPolicyUri"":""https://www.mozilla.org/privacy/firefox/"",""Tou"":"""",""TouUri"":""""},""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""FirstAvailableDate"":""2021-10-05T21:38:45.1973879Z"",""SupportedLanguages"":[""en-us"",""zh-cn"",""zh-tw"",""cs"",""nl"",""en-ca"",""en-gb"",""fi"",""fr"",""el"",""hu"",""id"",""it"",""ja"",""pl"",""pt-br"",""pt-pt"",""ru"",""es-ar"",""es-mx"",""es-es"",""sv-se"",""tr"",""de"",""be"",""ar"",""bs"",""ca"",""cy"",""da"",""es-cl"",""sq"",""gl"",""ka"",""gu-in"",""hi-in"",""is"",""kk"",""ko"",""ms"",""nb-no"",""nn-no"",""pa-in"",""ro"",""si"",""sk"",""sl"",""th"",""uk"",""ur"",""vi""],""PackageIds"":null,""PIFilter"":null,""Markets"":[""US""]}],""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""EarlyAdopterEnrollmentUrl"":null,""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null},""FulfillmentType"":""WindowsUpdate"",""FulfillmentPluginId"":null,""HasThirdPartyIAPs"":false,""LastUpdateDate"":""2024-04-30T14:41:13.0000000Z"",""HardwareProperties"":{""MinimumHardware"":[],""RecommendedHardware"":[],""MinimumProcessor"":"""",""RecommendedProcessor"":"""",""MinimumGraphics"":"""",""RecommendedGraphics"":""""},""HardwareRequirements"":[],""HardwareWarningList"":[],""InstallationTerms"":""InstallationTermsStandard"",""Packages"":[{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x86""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""zrZtsI/8iaERjKU5t10jEMnCC7QWpztt3BhLTsbyJ14="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":146228493,""MaxInstallSizeInBytes"":289435648,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2"",""PackageId"":""08dea409-a13a-9903-2bbc-7f5e541f1d94-X86"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30001,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null}},{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x64""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""m7sF5N88lREGMPNzhM+f3gvbYkMPDD2mwqiFQelHvFU="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":150856555,""MaxInstallSizeInBytes"":305274880,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2"",""PackageId"":""7698ca0e-0912-77ba-3a73-1504a9fef084-X64"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30002,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null}}],""VersionString"":"""",""VisibleToB2BServiceIds"":[],""XboxXPA"":false,""BundledSkus"":[],""IsRepurchasable"":false,""SkuDisplayRank"":0,""DisplayPhysicalStoreInventory"":null,""AdditionalIdentifiers"":[],""IsTrial"":false,""IsPreOrder"":false,""IsBundle"":false},""SkuASchema"":""Sku;3"",""SkuBSchema"":""SkuUnifiedApp;3"",""SkuId"":""0010"",""SkuType"":""full"",""RecurrencePolicy"":null,""SubscriptionPolicyId"":null},""Availabilities"":[{""Actions"":[""Details"",""Fulfill"",""Purchase"",""Browse"",""Curate"",""Redeem""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9RBCP3VR54XC"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""PIFilter"":{""ExclusionProperties"":[],""InclusionProperties"":[]},""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":""TaxesNotIncluded"",""WholesaleCurrencyCode"":""""}},""Properties"":{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z""},""SkuId"":""0010"",""DisplayRank"":0,""RemediationRequired"":false},{""Actions"":[""License"",""Browse"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9TXXNTRLPTLW"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""LicensingData"":{""SatisfyingEntitlementKeys"":[{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0010""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:60c1b112-072c-4657-b28d-d65f06e9d660:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:70bed52e-e1d3-467f-96b1-f4d474846515:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0001""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0002""],""LicensingKeyIds"":[""1""]}]},""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0010"",""DisplayRank"":1,""RemediationRequired"":false},{""Actions"":[""License"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9SH85X02C4KQ"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Mobile""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Team""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Xbox""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Holographic""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Core""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""LicensingData"":{""SatisfyingEntitlementKeys"":[{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0010""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:60c1b112-072c-4657-b28d-d65f06e9d660:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:70bed52e-e1d3-467f-96b1-f4d474846515:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0001""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0002""],""LicensingKeyIds"":[""1""]}]},""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0010"",""DisplayRank"":2,""RemediationRequired"":false}],""HistoricalBestAvailabilities"":[{""Actions"":[""Details"",""Fulfill"",""Purchase"",""Browse"",""Curate"",""Redeem""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9RBCP3VR54XC"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z"",""EligibilityPredicateIds"":[""CannotSeenByChinaClient""],""SupportedCatalogVersion"":6},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""PIFilter"":{""ExclusionProperties"":[],""InclusionProperties"":[]},""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":""TaxesNotIncluded"",""WholesaleCurrencyCode"":""""}},""Properties"":{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z""},""SkuId"":""0010"",""DisplayRank"":0,""ProductASchema"":""Product;3""}]},{""Sku"":{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""Contributors"":[],""Features"":[],""MinimumNotes"":"""",""RecommendedNotes"":"""",""ReleaseNotes"":""A faster, more intuitive Firefox now available in the Windows App Store"",""DisplayPlatformProperties"":null,""SkuDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""SkuTitle"":""Mozilla Firefox"",""SkuButtonTitle"":"""",""DeliveryDateOverlay"":null,""SkuDisplayRank"":[],""TextResources"":null,""Images"":[],""LegalText"":{""AdditionalLicenseTerms"":"""",""Copyright"":"""",""CopyrightUri"":"""",""PrivacyPolicy"":"""",""PrivacyPolicyUri"":""https://www.mozilla.org/privacy/firefox/"",""Tou"":"""",""TouUri"":""""},""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""FirstAvailableDate"":""2021-10-05T21:38:45.1973879Z"",""SupportedLanguages"":[""en-us"",""zh-cn"",""zh-tw"",""cs"",""nl"",""en-ca"",""en-gb"",""fi"",""fr"",""el"",""hu"",""id"",""it"",""ja"",""pl"",""pt-br"",""pt-pt"",""ru"",""es-ar"",""es-mx"",""es-es"",""sv-se"",""tr"",""de"",""be"",""ar"",""bs"",""ca"",""cy"",""da"",""es-cl"",""sq"",""gl"",""ka"",""gu-in"",""hi-in"",""is"",""kk"",""ko"",""ms"",""nb-no"",""nn-no"",""pa-in"",""ro"",""si"",""sk"",""sl"",""th"",""uk"",""ur"",""vi""],""PackageIds"":null,""PIFilter"":null,""Markets"":[""US""]}],""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""EarlyAdopterEnrollmentUrl"":null,""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null},""FulfillmentType"":""WindowsUpdate"",""FulfillmentPluginId"":null,""HasThirdPartyIAPs"":false,""LastUpdateDate"":""2024-04-30T14:41:13.0000000Z"",""HardwareProperties"":{""MinimumHardware"":[],""RecommendedHardware"":[],""MinimumProcessor"":"""",""RecommendedProcessor"":"""",""MinimumGraphics"":"""",""RecommendedGraphics"":""""},""HardwareRequirements"":[],""HardwareWarningList"":[],""InstallationTerms"":""InstallationTermsStandard"",""Packages"":[{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x86""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""zrZtsI/8iaERjKU5t10jEMnCC7QWpztt3BhLTsbyJ14="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":146228493,""MaxInstallSizeInBytes"":289435648,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2"",""PackageId"":""08dea409-a13a-9903-2bbc-7f5e541f1d94-X86"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30001,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null}},{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x64""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""m7sF5N88lREGMPNzhM+f3gvbYkMPDD2mwqiFQelHvFU="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":150856555,""MaxInstallSizeInBytes"":305274880,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2"",""PackageId"":""7698ca0e-0912-77ba-3a73-1504a9fef084-X64"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30002,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null}}],""VersionString"":"""",""VisibleToB2BServiceIds"":[],""XboxXPA"":false,""BundledSkus"":[],""IsRepurchasable"":false,""SkuDisplayRank"":2,""DisplayPhysicalStoreInventory"":null,""AdditionalIdentifiers"":[],""IsTrial"":true,""IsPreOrder"":false,""IsBundle"":false},""SkuASchema"":""Sku;3"",""SkuBSchema"":""SkuUnifiedApp;3"",""SkuId"":""0011"",""SkuType"":""trial"",""RecurrencePolicy"":null,""SubscriptionPolicyId"":null},""Availabilities"":[{""Actions"":[""Details"",""License"",""Fulfill""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9P32GQQH8MSX"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0011"",""DisplayRank"":0,""RemediationRequired"":false},{""Actions"":[""License"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9PT62300SK6S"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Mobile""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Team""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Xbox""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Holographic""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Core""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0011"",""DisplayRank"":1,""RemediationRequired"":false}],""HistoricalBestAvailabilities"":[]}]}]}"; + const string graphResponseData = @"{ ""@odata.type"": ""#microsoft.graph.winGetApp"", ""id"": ""0177548a-548a-0177-8a54-77018a547701"" }"; + var httpClient = Substitute.For(); + var storeLogger = Substitute.For>(); + var graphLogger = Substitute.For>(); + var fileManager = Substitute.For(); + var client = new MicrosoftStoreClient(httpClient, storeLogger); + var storeAppUploader = new GraphStoreAppUploader(graphLogger, fileManager, client); + var cancellationToken = new CancellationToken(); + + var manifestResponse = new HttpResponseMessage + { + Content = new StringContent(manifestData, Encoding.UTF8, "application/json") + }; + + var graphResponse = new HttpResponseMessage + { + Content = new StringContent(graphResponseData, Encoding.UTF8, "application/json") + }; + + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Get + && req.RequestUri == new Uri($"https://displaycatalog.mp.microsoft.com/v7.0/products?bigIds={packageId}&market=US&languages=en-us")), cancellationToken) + .Returns(manifestResponse); + + fileManager.DownloadFileAsync("http://store-images.s-microsoft.com/image/apps.36939.14473293538384797.0ec149d2-d2b5-48a8-afd4-66986d387ec9.820a68fb-12dd-45a1-9a5a-1f141fc93f29", Arg.Any(), expectedHash: null, overrideFile: false, cancellationToken: cancellationToken) + .Returns(Task.CompletedTask); + + fileManager.ReadAllBytesAsync(Arg.Any(), cancellationToken) + .Returns(Encoding.UTF8.GetBytes("fake image")); + + var expectedGraphBody = new Dictionary + { + { "@odata.type", "#microsoft.graph.winGetApp" }, + { "displayName", "Mozilla Firefox" } + }; + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Post + && req.RequestUri.ToString().Equals("https://graph.microsoft.com/beta/deviceAppManagement/mobileApps", StringComparison.OrdinalIgnoreCase) + && req.Content != null + && req.Content.ValidateJsonBody(expectedGraphBody) + ), cancellationToken) + .Returns(graphResponse); + + var graphClient = new GraphServiceClient(httpClient, new Microsoft.Kiota.Abstractions.Authentication.AnonymousAuthenticationProvider()); + + var result = await storeAppUploader.CreateStoreAppAsync(graphClient, packageId, cancellationToken); + + Assert.NotNull(result); + Assert.Equal("0177548a-548a-0177-8a54-77018a547701", result?.Id); + + } + + [Fact] + public async Task GetStoreIdForNameAsync_Returns_ExptectedResult() + { + var httpClient = Substitute.For(); + var storeLogger = Substitute.For>(); + var graphStoreLogger = Substitute.For>(); + var client = new MicrosoftStoreClient(httpClient, storeLogger); + var cancellationToken = new CancellationToken(); + + var graphStoreAppUploader = new GraphStoreAppUploader(graphStoreLogger, Substitute.For(), client); + + var expectedResponse = new HttpResponseMessage + { + Content = new StringContent( + @"{ + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchResponse, StoreEdgeFD"", + ""Data"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchData, StoreEdgeFD"", + ""PackageIdentifier"": ""9NZVDKPMR9RD"", + ""PackageName"": ""Mozilla Firefox"", + ""Publisher"": ""Mozilla"", + ""Versions"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchVersion, StoreEdgeFD"", + ""PackageVersion"": ""Unknown"", + ""PackageFamilyNames"": [ + ""Mozilla.Firefox_n80bbvh6b1yt2"" + ] + } + ] + } + ] + }", Encoding.UTF8, "application/json") + }; + + // Validate the body of the request somehow + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Post + && req.RequestUri == new Uri("https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch") + && req.Content != null + && req.Content.IsJson()), cancellationToken) + .Returns(expectedResponse); + + // Act + var result = await graphStoreAppUploader.GetStoreIdForNameAsync("Mozilla Firefox", cancellationToken); + + // Assert + Assert.Equal("9NZVDKPMR9RD", result); + } +} diff --git a/tests/WingetIntune.Tests/HttpContentExtensions.cs b/tests/WingetIntune.Tests/HttpContentExtensions.cs new file mode 100644 index 0000000..f8f5576 --- /dev/null +++ b/tests/WingetIntune.Tests/HttpContentExtensions.cs @@ -0,0 +1,48 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace WingetIntune.Tests; +internal static class HttpContentExtensions +{ + public static bool IsJson(this HttpContent? content) + { + return content?.Headers.ContentType?.MediaType == "application/json"; + } + + public static bool ValidateJsonBody(this HttpContent? content, Dictionary bodyValues) + { + if (content is null || !content.IsJson()) + { + return false; + } + + var json = content.ReadAsStringAsync().Result; + try + { + var body = JsonSerializer.Deserialize(json); + + if (body is null || body.Data is null) + { + return false; + } + foreach (var kvp in bodyValues) + { + if (!body.Data.ContainsKey(kvp.Key) || !body.Data[kvp.Key].ValueEquals(kvp.Value.ToString())) + { + return false; + } + } + return true; + } + catch (Exception ex) + { + throw new InvalidOperationException($"Failed to deserialize JSON: {json}", ex); + } + } + + public class JsonContentBody + { + [JsonExtensionData] + public Dictionary? Data { get; set; } + } +} diff --git a/tests/WingetIntune.Tests/Intune/IntuneManagerTests.cs b/tests/WingetIntune.Tests/Intune/IntuneManagerTests.cs index 838f767..ce320ea 100644 --- a/tests/WingetIntune.Tests/Intune/IntuneManagerTests.cs +++ b/tests/WingetIntune.Tests/Intune/IntuneManagerTests.cs @@ -11,7 +11,7 @@ public class IntuneManagerTests [Fact] public async Task GenerateMsiPackage_OtherPackage_ThrowsError() { - var intuneManager = new IntuneManager(null, null, null, null, null, null, null, null, null, null); + var intuneManager = new IntuneManager(null, null, null, null, null, null, null, null, null, null, null); var tempFolder = Path.Combine(Path.GetTempPath(), "intunewin"); var outputFolder = Path.Combine(Path.GetTempPath(), "packages"); @@ -80,7 +80,7 @@ public async Task GenerateInstallerPackage_MsiPackage_Returns() var intunePackager = Substitute.For(); - var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, processManager, null, null, null, null, intunePackager, null, null); + var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, processManager, null, null, null, null, intunePackager, null, null, null); await intuneManager.GenerateInstallerPackage(tempFolder, outputFolder, IntuneTestConstants.azureCliPackageInfo, new PackageOptions { Architecture = Models.Architecture.X64, InstallerContext = InstallerContext.User }, CancellationToken.None); @@ -105,7 +105,7 @@ public async Task DownloadLogoAsync_CallsFilemanager() fileManager.DownloadFileAsync($"https://api.winstall.app/icons/{packageId}.png", logoPath, null, false, false, Arg.Any()) .Returns(Task.CompletedTask); - var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, null, null, null, null, null, null, null, null); + var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, null, null, null, null, null, null, null, null, null); await intuneManager.DownloadLogoAsync(folder, packageId, CancellationToken.None); //call.Received(1); @@ -137,7 +137,7 @@ public async Task DownloadInstallerAsync_CallsFilemanager() fileManager.DownloadFileAsync(packageInfo.InstallerUrl.ToString(), installerPath, hash, true, false, Arg.Any()) .Returns(Task.CompletedTask); - var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, null, null, null, null, null, null, null, null); + var intuneManager = new IntuneManager(new NullLoggerFactory(), fileManager, null, null, null, null, null, null, null, null, null); await intuneManager.DownloadInstallerAsync(folder, packageInfo, CancellationToken.None); //call.Received(1); diff --git a/tests/WingetIntune.Tests/MsStore/MicrosoftStoreClientTests.cs b/tests/WingetIntune.Tests/MsStore/MicrosoftStoreClientTests.cs new file mode 100644 index 0000000..4a5706e --- /dev/null +++ b/tests/WingetIntune.Tests/MsStore/MicrosoftStoreClientTests.cs @@ -0,0 +1,171 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WingetIntune.Internal.MsStore; + +namespace WingetIntune.Tests.MsStore; +public class MicrosoftStoreClientTests +{ + [Fact] + public async Task GetDisplayCatalogAsync_ReturnsExpectedResult() + { + const string packageId = "9NZVDKPMR9RD"; + const string responseData = @"{""Products"":[{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""DeveloperName"":"""",""DisplayPlatformProperties"":null,""PublisherName"":""Mozilla"",""PublisherAddress"":null,""PublisherWebsiteUri"":""https://www.mozilla.org/firefox/"",""SupportUri"":""https://support.mozilla.org/products/firefox"",""SupportPhone"":null,""EligibilityProperties"":null,""Franchises"":[],""Images"":[{""FileId"":""3071430996971663174"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":14069,""ForegroundColor"":"""",""Height"":100,""ImagePositionInfo"":"""",""ImagePurpose"":""Logo"",""UnscaledImageSHA256Hash"":""NmfuVtG1XGBx/p8HUht9J+giOGcMN5oIea7M4xjN/H8="",""Uri"":""//store-images.s-microsoft.com/image/apps.26422.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.37a70641-3de3-41b1-9c94-3cb0cfc663c2"",""Width"":100},{""FileId"":""3004232197050559163"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":63556,""ForegroundColor"":"""",""Height"":300,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""S5CO1XDVz6JpQlsSlJWWEN45hRkKGDwyapmRK6A66qA="",""Uri"":""//store-images.s-microsoft.com/image/apps.36939.14473293538384797.0ec149d2-d2b5-48a8-afd4-66986d387ec9.820a68fb-12dd-45a1-9a5a-1f141fc93f29"",""Width"":300},{""FileId"":""3008762446945936351"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":7710,""ForegroundColor"":"""",""Height"":88,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""9z/FtCO6NlcynHvQQ6gvOoXTw/h8ZUzdrOxMg+QMt2Q="",""Uri"":""//store-images.s-microsoft.com/image/apps.16375.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.a6fb32ca-2223-41dc-8d73-8395066b1c4f"",""Width"":88},{""FileId"":""3052106644741011285"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":187605,""ForegroundColor"":"""",""Height"":620,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""6gpjyrwSRgQ9Fa4NbghXdgJsrO/cs7vxFM+Y/mkBCDg="",""Uri"":""//store-images.s-microsoft.com/image/apps.2794.14473293538384797.0ec149d2-d2b5-48a8-afd4-66986d387ec9.5a7e12ea-3baa-41de-ae7c-e58c7d22b644"",""Width"":620},{""FileId"":""3031096784199183752"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":8923,""ForegroundColor"":"""",""Height"":142,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""dhSnfnKPaSBBYSgcsMpkSPeuawH/9ZSKTZE3LW+hpNM="",""Uri"":""//store-images.s-microsoft.com/image/apps.5238.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.13c8d648-665d-4185-8b32-beb922c3a9d1"",""Width"":142},{""FileId"":""3028587524167049996"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":17159,""ForegroundColor"":"""",""Height"":300,""ImagePositionInfo"":"""",""ImagePurpose"":""Tile"",""UnscaledImageSHA256Hash"":""AjdCKOV39U/zZ91jWgO3Uc0gJy8DZ4tNs46DxTrPoPs="",""Uri"":""//store-images.s-microsoft.com/image/apps.14082.14473293538384797.ed62a13f-c9ba-478e-9f33-7fd3515b0820.abebba2b-9232-4dc4-a59c-0ded036614e4"",""Width"":620},{""FileId"":""3000180573878009204"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":2219458,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/0"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""We95BmfhVSMei0EwA/W2IN8vfUIrIE1KxMRNl/bNpu0="",""Uri"":""//store-images.s-microsoft.com/image/apps.61273.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.836cb591-5b2e-480c-abe0-fbef3445148c"",""Width"":3840},{""FileId"":""3001975626805331357"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":1142645,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/1"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""RxzoePoLqML4h7d/kM4yqb0vbQQRd+mK+uOyI5S0814="",""Uri"":""//store-images.s-microsoft.com/image/apps.7239.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.2836ec17-3608-4c59-955b-e33a4ddbe09a"",""Width"":3840},{""FileId"":""3051311566860831267"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":1435423,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/2"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""sf+mRDniEBQEybyQg3H2FJ+YDSdRD79bK2ZjQARm9Tc="",""Uri"":""//store-images.s-microsoft.com/image/apps.65457.14473293538384797.c7c6f980-349e-4aec-8b21-c9a6aba30011.325858ad-e348-4660-95b8-d2f66200e3fc"",""Width"":3840},{""FileId"":""3048171808590640430"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":2744619,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/3"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""NeoziSi4gk+vLi5eIcXPS03Cq1hY5u8xGMAohxBXA54="",""Uri"":""//store-images.s-microsoft.com/image/apps.59957.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.7cf8905f-6469-422f-8aed-c9bc151a97c4"",""Width"":3840},{""FileId"":""3008914828876618251"",""EISListingIdentifier"":null,""BackgroundColor"":""#20123A"",""Caption"":"""",""FileSizeInBytes"":881119,""ForegroundColor"":"""",""Height"":2160,""ImagePositionInfo"":""Desktop/4"",""ImagePurpose"":""Screenshot"",""UnscaledImageSHA256Hash"":""Xt+ESkKx6rAGAqMWPrfv+myQvniyCYFJnWFinDlk6g8="",""Uri"":""//store-images.s-microsoft.com/image/apps.57182.14473293538384797.38906001-683a-40ba-aa5d-ca1c71126f40.b1631027-7eff-4a82-b06f-956df2b0f6f8"",""Width"":3840}],""Videos"":[],""ProductDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""ProductTitle"":""Mozilla Firefox"",""ShortTitle"":""Firefox"",""SortTitle"":"""",""FriendlyTitle"":null,""ShortDescription"":"""",""SearchTitles"":[],""VoiceTitle"":"""",""RenderGroupDetails"":null,""ProductDisplayRanks"":[],""InteractiveModelConfig"":null,""Interactive3DEnabled"":false,""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z"",""OriginalReleaseDateFriendlyName"":"""",""MinimumUserAge"":0,""ContentRatings"":[{""RatingSystem"":""ESRB"",""RatingId"":""ESRB:E"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""ESRB:UnrInt""]},{""RatingSystem"":""PEGI"",""RatingId"":""PEGI:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""PEGI:UnrInt""]},{""RatingSystem"":""DJCTQ"",""RatingId"":""DJCTQ:L"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""DJCTQ:UnrInt""]},{""RatingSystem"":""USK"",""RatingId"":""USK:Everyone"",""RatingDescriptors"":[""USK:ConDifAge""],""RatingDisclaimers"":[],""InteractiveElements"":[""USK:UnrInt""]},{""RatingSystem"":""IARC"",""RatingId"":""IARC:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""IARC:UnrInt""]},{""RatingSystem"":""PCBP"",""RatingId"":""PCBP:0"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[""PCBP:UnrInt""]},{""RatingSystem"":""CSRR"",""RatingId"":""CSRR:G"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]},{""RatingSystem"":""CCC"",""RatingId"":""CCC:TE"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]},{""RatingSystem"":""Microsoft"",""RatingId"":""Microsoft:3"",""RatingDescriptors"":[],""RatingDisclaimers"":[],""InteractiveElements"":[]}],""RelatedProducts"":[],""UsageData"":[{""AggregateTimeSpan"":""7Days"",""AverageRating"":4.5,""PlayCount"":0,""RatingCount"":199,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""},{""AggregateTimeSpan"":""30Days"",""AverageRating"":4.4,""PlayCount"":0,""RatingCount"":416,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""},{""AggregateTimeSpan"":""AllTime"",""AverageRating"":4.5,""PlayCount"":0,""RatingCount"":20348,""RentalCount"":""0"",""TrialCount"":""0"",""PurchaseCount"":""0""}],""BundleConfig"":null,""Markets"":[""US""]}],""ProductASchema"":""Product;3"",""ProductBSchema"":""ProductUnifiedApp;3"",""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""Attributes"":[{""Name"":""BroadcastSupport"",""Minimum"":null,""Maximum"":null,""ApplicablePlatforms"":null,""Group"":null}],""CanInstallToSDCard"":false,""Category"":""Productivity"",""SubCategory"":"""",""Categories"":null,""Extensions"":null,""IsAccessible"":false,""IsLineOfBusinessApp"":false,""IsPublishedToLegacyWindowsPhoneStore"":false,""IsPublishedToLegacyWindowsStore"":false,""IsSettingsApp"":false,""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""PackageIdentityName"":""Mozilla.Firefox"",""PublisherCertificateName"":""CN=082E9164-EE6C-4EC8-B62C-441FAE7BEFA1"",""PublisherId"":""77577580"",""XboxLiveTier"":null,""XboxXPA"":null,""XboxCrossGenSetId"":null,""XboxConsoleGenOptimized"":null,""XboxConsoleGenCompatible"":null,""XboxLiveGoldRequired"":false,""XBOX"":{},""ExtendedClientMetadata"":{},""OwnershipType"":null,""PdpBackgroundColor"":""#FFFFFF"",""HasAddOns"":false,""RevisionId"":""2024-04-30T14:41:20.5900076Z""},""AlternateIds"":[{""IdType"":""LegacyWindowsStoreProductId"",""Value"":""70bed52e-e1d3-467f-96b1-f4d474846515""},{""IdType"":""LegacyWindowsPhoneProductId"",""Value"":""60c1b112-072c-4657-b28d-d65f06e9d660""},{""IdType"":""XboxTitleId"",""Value"":""1728623981""}],""DomainDataVersion"":null,""IngestionSource"":""DCE"",""IsMicrosoftProduct"":false,""PreferredSkuId"":""0010"",""ProductType"":""Application"",""ValidationData"":{""PassedValidation"":false,""RevisionId"":""2024-04-30T14:41:20.5900076Z||.||95df8e43-f7a7-43f0-a00b-149bf8a386b1||1152921505697685831||Null||fullrelease"",""ValidationResultUri"":""""},""MerchandizingTags"":[],""PartD"":"""",""ProductFamily"":""Apps"",""SchemaVersion"":""3"",""ProductKind"":""Application"",""ProductPolicies"":{},""DisplaySkuAvailabilities"":[{""Sku"":{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""Contributors"":[],""Features"":[],""MinimumNotes"":"""",""RecommendedNotes"":"""",""ReleaseNotes"":""A faster, more intuitive Firefox now available in the Windows App Store"",""DisplayPlatformProperties"":null,""SkuDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""SkuTitle"":""Mozilla Firefox"",""SkuButtonTitle"":"""",""DeliveryDateOverlay"":null,""SkuDisplayRank"":[],""TextResources"":null,""Images"":[],""LegalText"":{""AdditionalLicenseTerms"":"""",""Copyright"":"""",""CopyrightUri"":"""",""PrivacyPolicy"":"""",""PrivacyPolicyUri"":""https://www.mozilla.org/privacy/firefox/"",""Tou"":"""",""TouUri"":""""},""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""FirstAvailableDate"":""2021-10-05T21:38:45.1973879Z"",""SupportedLanguages"":[""en-us"",""zh-cn"",""zh-tw"",""cs"",""nl"",""en-ca"",""en-gb"",""fi"",""fr"",""el"",""hu"",""id"",""it"",""ja"",""pl"",""pt-br"",""pt-pt"",""ru"",""es-ar"",""es-mx"",""es-es"",""sv-se"",""tr"",""de"",""be"",""ar"",""bs"",""ca"",""cy"",""da"",""es-cl"",""sq"",""gl"",""ka"",""gu-in"",""hi-in"",""is"",""kk"",""ko"",""ms"",""nb-no"",""nn-no"",""pa-in"",""ro"",""si"",""sk"",""sl"",""th"",""uk"",""ur"",""vi""],""PackageIds"":null,""PIFilter"":null,""Markets"":[""US""]}],""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""EarlyAdopterEnrollmentUrl"":null,""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null},""FulfillmentType"":""WindowsUpdate"",""FulfillmentPluginId"":null,""HasThirdPartyIAPs"":false,""LastUpdateDate"":""2024-04-30T14:41:13.0000000Z"",""HardwareProperties"":{""MinimumHardware"":[],""RecommendedHardware"":[],""MinimumProcessor"":"""",""RecommendedProcessor"":"""",""MinimumGraphics"":"""",""RecommendedGraphics"":""""},""HardwareRequirements"":[],""HardwareWarningList"":[],""InstallationTerms"":""InstallationTermsStandard"",""Packages"":[{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x86""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""zrZtsI/8iaERjKU5t10jEMnCC7QWpztt3BhLTsbyJ14="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":146228493,""MaxInstallSizeInBytes"":289435648,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2"",""PackageId"":""08dea409-a13a-9903-2bbc-7f5e541f1d94-X86"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30001,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null}},{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x64""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""m7sF5N88lREGMPNzhM+f3gvbYkMPDD2mwqiFQelHvFU="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":150856555,""MaxInstallSizeInBytes"":305274880,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2"",""PackageId"":""7698ca0e-0912-77ba-3a73-1504a9fef084-X64"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30002,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0010"",""Content"":null,""PackageFeatures"":null}}],""VersionString"":"""",""VisibleToB2BServiceIds"":[],""XboxXPA"":false,""BundledSkus"":[],""IsRepurchasable"":false,""SkuDisplayRank"":0,""DisplayPhysicalStoreInventory"":null,""AdditionalIdentifiers"":[],""IsTrial"":false,""IsPreOrder"":false,""IsBundle"":false},""SkuASchema"":""Sku;3"",""SkuBSchema"":""SkuUnifiedApp;3"",""SkuId"":""0010"",""SkuType"":""full"",""RecurrencePolicy"":null,""SubscriptionPolicyId"":null},""Availabilities"":[{""Actions"":[""Details"",""Fulfill"",""Purchase"",""Browse"",""Curate"",""Redeem""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9RBCP3VR54XC"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""PIFilter"":{""ExclusionProperties"":[],""InclusionProperties"":[]},""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":""TaxesNotIncluded"",""WholesaleCurrencyCode"":""""}},""Properties"":{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z""},""SkuId"":""0010"",""DisplayRank"":0,""RemediationRequired"":false},{""Actions"":[""License"",""Browse"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9TXXNTRLPTLW"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""LicensingData"":{""SatisfyingEntitlementKeys"":[{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0010""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:60c1b112-072c-4657-b28d-d65f06e9d660:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:70bed52e-e1d3-467f-96b1-f4d474846515:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0001""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0002""],""LicensingKeyIds"":[""1""]}]},""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0010"",""DisplayRank"":1,""RemediationRequired"":false},{""Actions"":[""License"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9SH85X02C4KQ"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Mobile""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Team""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Xbox""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Holographic""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Core""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""LicensingData"":{""SatisfyingEntitlementKeys"":[{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0010""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:60c1b112-072c-4657-b28d-d65f06e9d660:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""wes:App:70bed52e-e1d3-467f-96b1-f4d474846515:Full""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0001""],""LicensingKeyIds"":[""1""]},{""EntitlementKeys"":[""big:9NZVDKPMR9RD:0002""],""LicensingKeyIds"":[""1""]}]},""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0010"",""DisplayRank"":2,""RemediationRequired"":false}],""HistoricalBestAvailabilities"":[{""Actions"":[""Details"",""Fulfill"",""Purchase"",""Browse"",""Curate"",""Redeem""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9RBCP3VR54XC"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z"",""EligibilityPredicateIds"":[""CannotSeenByChinaClient""],""SupportedCatalogVersion"":6},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""PIFilter"":{""ExclusionProperties"":[],""InclusionProperties"":[]},""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":""TaxesNotIncluded"",""WholesaleCurrencyCode"":""""}},""Properties"":{""OriginalReleaseDate"":""2021-10-05T21:38:45.1973879Z""},""SkuId"":""0010"",""DisplayRank"":0,""ProductASchema"":""Product;3""}]},{""Sku"":{""LastModifiedDate"":""2024-04-30T14:41:13.2369856Z"",""LocalizedProperties"":[{""Contributors"":[],""Features"":[],""MinimumNotes"":"""",""RecommendedNotes"":"""",""ReleaseNotes"":""A faster, more intuitive Firefox now available in the Windows App Store"",""DisplayPlatformProperties"":null,""SkuDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""SkuTitle"":""Mozilla Firefox"",""SkuButtonTitle"":"""",""DeliveryDateOverlay"":null,""SkuDisplayRank"":[],""TextResources"":null,""Images"":[],""LegalText"":{""AdditionalLicenseTerms"":"""",""Copyright"":"""",""CopyrightUri"":"""",""PrivacyPolicy"":"""",""PrivacyPolicyUri"":""https://www.mozilla.org/privacy/firefox/"",""Tou"":"""",""TouUri"":""""},""Language"":""en-us"",""Markets"":[""US"",""DZ"",""AR"",""AU"",""AT"",""BH"",""BD"",""BE"",""BR"",""BG"",""CA"",""CL"",""CN"",""CO"",""CR"",""HR"",""CY"",""CZ"",""DK"",""EG"",""EE"",""FI"",""FR"",""DE"",""GR"",""GT"",""HK"",""HU"",""IS"",""IN"",""ID"",""IQ"",""IE"",""IL"",""IT"",""JP"",""JO"",""KZ"",""KE"",""KW"",""LV"",""LB"",""LI"",""LT"",""LU"",""MY"",""MT"",""MR"",""MX"",""MA"",""NL"",""NZ"",""NG"",""NO"",""OM"",""PK"",""PE"",""PH"",""PL"",""PT"",""QA"",""RO"",""RU"",""SA"",""RS"",""SG"",""SK"",""SI"",""ZA"",""KR"",""ES"",""SE"",""CH"",""TW"",""TH"",""TT"",""TN"",""TR"",""UA"",""AE"",""GB"",""VN"",""YE"",""LY"",""LK"",""UY"",""VE"",""AF"",""AX"",""AL"",""AS"",""AO"",""AI"",""AQ"",""AG"",""AM"",""AW"",""BO"",""BQ"",""BA"",""BW"",""BV"",""IO"",""BN"",""BF"",""BI"",""KH"",""CM"",""CV"",""KY"",""CF"",""TD"",""TL"",""DJ"",""DM"",""DO"",""EC"",""SV"",""GQ"",""ER"",""ET"",""FK"",""FO"",""FJ"",""GF"",""PF"",""TF"",""GA"",""GM"",""GE"",""GH"",""GI"",""GL"",""GD"",""GP"",""GU"",""GG"",""GN"",""GW"",""GY"",""HT"",""HM"",""HN"",""AZ"",""BS"",""BB"",""BY"",""BZ"",""BJ"",""BM"",""BT"",""KM"",""CG"",""CD"",""CK"",""CX"",""CC"",""CI"",""CW"",""JM"",""SJ"",""JE"",""KI"",""KG"",""LA"",""LS"",""LR"",""MO"",""MK"",""MG"",""MW"",""IM"",""MH"",""MQ"",""MU"",""YT"",""FM"",""MD"",""MN"",""MS"",""MZ"",""MM"",""NA"",""NR"",""NP"",""MV"",""ML"",""NC"",""NI"",""NE"",""NU"",""NF"",""PW"",""PS"",""PA"",""PG"",""PY"",""RE"",""RW"",""BL"",""MF"",""WS"",""ST"",""SN"",""MP"",""PN"",""SX"",""SB"",""SO"",""SC"",""SL"",""GS"",""SH"",""KN"",""LC"",""PM"",""VC"",""TJ"",""TZ"",""TG"",""TK"",""TO"",""TM"",""TC"",""TV"",""UM"",""UG"",""VI"",""VG"",""WF"",""EH"",""ZM"",""ZW"",""UZ"",""VU"",""SR"",""SZ"",""AD"",""MC"",""SM"",""ME"",""VA"",""NEUTRAL""]}],""MarketProperties"":[{""FirstAvailableDate"":""2021-10-05T21:38:45.1973879Z"",""SupportedLanguages"":[""en-us"",""zh-cn"",""zh-tw"",""cs"",""nl"",""en-ca"",""en-gb"",""fi"",""fr"",""el"",""hu"",""id"",""it"",""ja"",""pl"",""pt-br"",""pt-pt"",""ru"",""es-ar"",""es-mx"",""es-es"",""sv-se"",""tr"",""de"",""be"",""ar"",""bs"",""ca"",""cy"",""da"",""es-cl"",""sq"",""gl"",""ka"",""gu-in"",""hi-in"",""is"",""kk"",""ko"",""ms"",""nb-no"",""nn-no"",""pa-in"",""ro"",""si"",""sk"",""sl"",""th"",""uk"",""ur"",""vi""],""PackageIds"":null,""PIFilter"":null,""Markets"":[""US""]}],""ProductId"":""9NZVDKPMR9RD"",""Properties"":{""EarlyAdopterEnrollmentUrl"":null,""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null},""FulfillmentType"":""WindowsUpdate"",""FulfillmentPluginId"":null,""HasThirdPartyIAPs"":false,""LastUpdateDate"":""2024-04-30T14:41:13.0000000Z"",""HardwareProperties"":{""MinimumHardware"":[],""RecommendedHardware"":[],""MinimumProcessor"":"""",""RecommendedProcessor"":"""",""MinimumGraphics"":"""",""RecommendedGraphics"":""""},""HardwareRequirements"":[],""HardwareWarningList"":[],""InstallationTerms"":""InstallationTermsStandard"",""Packages"":[{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x86""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""zrZtsI/8iaERjKU5t10jEMnCC7QWpztt3BhLTsbyJ14="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":146228493,""MaxInstallSizeInBytes"":289435648,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2"",""PackageId"":""08dea409-a13a-9903-2bbc-7f5e541f1d94-X86"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30001,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x86__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null}},{""Applications"":[{""ApplicationId"":""App"",""DeclarationOrder"":0,""Extensions"":[""appExecutionAlias-appExecutionAlias"",""fileTypeAssociation-.avif"",""fileTypeAssociation-.htm"",""fileTypeAssociation-.html"",""fileTypeAssociation-.pdf"",""fileTypeAssociation-.shtml"",""fileTypeAssociation-.xht"",""fileTypeAssociation-.xhtml"",""fileTypeAssociation-.svg"",""fileTypeAssociation-.webp"",""protocol-http"",""protocol-https"",""protocol-mailto"",""protocol-firefox-bridge"",""protocol-firefox-private-bridge"",""comServer-comServer"",""toastNotificationActivation-toastNotificationActivation""]}],""Architectures"":[""x64""],""Capabilities"":[""runFullTrust"",""Microsoft.storeFilter.core.notSupported_8wekyb3d8bbwe"",""Microsoft.requiresNonSMode_8wekyb3d8bbwe""],""DeviceCapabilities"":[],""ExperienceIds"":[],""FrameworkDependencies"":[],""HardwareDependencies"":[],""HardwareRequirements"":[],""Hash"":""m7sF5N88lREGMPNzhM+f3gvbYkMPDD2mwqiFQelHvFU="",""HashAlgorithm"":""SHA256"",""IsStreamingApp"":false,""Languages"":[""en-us"",""af"",""ar"",""be"",""bg"",""bn"",""bs"",""ca"",""cs"",""cy"",""da"",""de"",""el"",""en-ca"",""en-gb"",""es-ar"",""es-cl"",""es-es"",""es-mx"",""et"",""eu"",""fa"",""fi"",""fr"",""ga-ie"",""gl"",""gu-in"",""he"",""hi-in"",""hr"",""hu"",""hy-am"",""id"",""is"",""it"",""ja"",""ka"",""kk"",""km"",""kn"",""ko"",""lt"",""lv"",""mk"",""mr"",""ms"",""nb-no"",""ne-np"",""nl"",""nn-no"",""pa-in"",""pl"",""pt-br"",""pt-pt"",""ro"",""ru"",""si"",""sk"",""sl"",""sq"",""sv-se"",""ta"",""te"",""th"",""tr"",""uk"",""ur"",""vi"",""xh"",""zh-cn"",""zh-tw""],""MaxDownloadSizeInBytes"":150856555,""MaxInstallSizeInBytes"":305274880,""PackageFormat"":""Msix"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""MainPackageFamilyNameForDlc"":null,""PackageFullName"":""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2"",""PackageId"":""7698ca0e-0912-77ba-3a73-1504a9fef084-X64"",""ContentId"":""642d213e-143d-9470-0528-23c84ddac98c"",""KeyId"":null,""PackageRank"":30002,""PackageUri"":""https://productingestionbin1.blob.core.windows.net"",""PlatformDependencies"":[{""MaxTested"":2814751249597971,""MinVersion"":2814750931222528,""PlatformName"":""Windows.Desktop""}],""PlatformDependencyXmlBlob"":""{\""blob.version\"":1688867040526336,\""content.isMain\"":false,\""content.packageId\"":\""Mozilla.Firefox_125.0.3.0_x64__n80bbvh6b1yt2\"",\""content.productId\"":\""60c1b112-072c-4657-b28d-d65f06e9d660\"",\""content.targetPlatforms\"":[{\""platform.maxVersionTested\"":2814751249597971,\""platform.minVersion\"":2814750931222528,\""platform.target\"":3}],\""content.type\"":7,\""policy\"":{\""category.first\"":\""app\"",\""category.second\"":\""Productivity\"",\""optOut.backupRestore\"":false,\""optOut.removeableMedia\"":true},\""policy2\"":{\""ageRating\"":1,\""optOut.DVR\"":true,\""thirdPartyAppRatings\"":[{\""level\"":7,\""systemId\"":3},{\""level\"":12,\""systemId\"":5},{\""level\"":48,\""systemId\"":12},{\""level\"":27,\""systemId\"":9},{\""level\"":76,\""systemId\"":16},{\""level\"":68,\""systemId\"":15},{\""level\"":54,\""systemId\"":13}]}}"",""ResourceId"":"""",""Version"":""35184372089028608"",""PackageDownloadUris"":null,""DriverDependencies"":[],""FulfillmentData"":{""ProductId"":""9NZVDKPMR9RD"",""WuBundleId"":""f5e8ea9b-4ff6-4b62-99b6-740e683367a7"",""WuCategoryId"":""b234f54f-cf50-4416-9fc0-b9742f96d0a0"",""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""SkuId"":""0011"",""Content"":null,""PackageFeatures"":null}}],""VersionString"":"""",""VisibleToB2BServiceIds"":[],""XboxXPA"":false,""BundledSkus"":[],""IsRepurchasable"":false,""SkuDisplayRank"":2,""DisplayPhysicalStoreInventory"":null,""AdditionalIdentifiers"":[],""IsTrial"":true,""IsPreOrder"":false,""IsBundle"":false},""SkuASchema"":""Sku;3"",""SkuBSchema"":""SkuUnifiedApp;3"",""SkuId"":""0011"",""SkuType"":""trial"",""RecurrencePolicy"":null,""SubscriptionPolicyId"":null},""Availabilities"":[{""Actions"":[""Details"",""License"",""Fulfill""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9P32GQQH8MSX"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Desktop""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.8828080""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0011"",""DisplayRank"":0,""RemediationRequired"":false},{""Actions"":[""License"",""Details""],""AvailabilityASchema"":""Availability;3"",""AvailabilityBSchema"":""AvailabilityUnifiedApp;3"",""AvailabilityId"":""9PT62300SK6S"",""Conditions"":{""ClientConditions"":{""AllowedPlatforms"":[{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Mobile""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Team""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Xbox""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Holographic""},{""MaxVersion"":2147483647,""MinVersion"":0,""PlatformName"":""Windows.Core""}]},""EndDate"":""9998-12-30T00:00:00.0000000Z"",""ResourceSetIds"":[""1""],""StartDate"":""1753-01-01T00:00:00.0000000Z""},""LastModifiedDate"":""2024-04-30T14:39:37.7718031Z"",""Markets"":[""US""],""OrderManagementData"":{""GrantedEntitlementKeys"":[],""Price"":{""CurrencyCode"":""USD"",""IsPIRequired"":false,""ListPrice"":0.0,""MSRP"":0.0,""TaxType"":"""",""WholesaleCurrencyCode"":""""}},""Properties"":{},""SkuId"":""0011"",""DisplayRank"":1,""RemediationRequired"":false}],""HistoricalBestAvailabilities"":[]}]}]}"; + + var httpClient = Substitute.For(); + var logger = Substitute.For>(); + var client = new MicrosoftStoreClient(httpClient, logger); + var cancellationToken = new CancellationToken(); + + var fakeResponse = new HttpResponseMessage + { + Content = new StringContent(responseData, Encoding.UTF8, "application/json") + }; + + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Get + && req.RequestUri == new Uri($"https://displaycatalog.mp.microsoft.com/v7.0/products?bigIds={packageId}&market=US&languages=en-us")), cancellationToken) + .Returns(fakeResponse); + + // Act + var result = await client.GetDisplayCatalogAsync(packageId, cancellationToken); + + // Assert + Assert.NotNull(result); + var product = result?.Products.FirstOrDefault(); + Assert.NotNull(product); + Assert.Equal(packageId, product.ProductId); + Assert.Equal("Mozilla Firefox", product.LocalizedProperties.FirstOrDefault().ProductTitle); + + var image = product.LocalizedProperties.FirstOrDefault().Images.FirstOrDefault(i => i.Height == 300 && i.Width == 300); + Assert.NotNull(image); + } + + [Fact] + public async Task GetManifestAsync_ReturnsExpectedResult() + { + const string packageId = "9NZVDKPMR9RD"; + const string responseData = @"{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.PackageManifestResponse, StoreEdgeFD"",""Data"":{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.PackageManifestData, StoreEdgeFD"",""PackageIdentifier"":""9NZVDKPMR9RD"",""Versions"":[{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.PackageManifestVersion, StoreEdgeFD"",""PackageVersion"":""Unknown"",""DefaultLocale"":{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.DefaultLocale, StoreEdgeFD"",""PackageLocale"":""en-us"",""Publisher"":""Mozilla"",""PublisherUrl"":""https://www.mozilla.org/firefox/"",""PrivacyUrl"":""https://www.mozilla.org/privacy/firefox/"",""PublisherSupportUrl"":""https://support.mozilla.org/products/firefox"",""PackageName"":""Mozilla Firefox"",""License"":""ms-windows-store://pdp/?ProductId=9NZVDKPMR9RD"",""Copyright"":"""",""ShortDescription"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your d..."",""Description"":""Firefox Browser: fast, private & safe web browser\r\n\r\nWhen it comes to your life online, you have a choice: accept the factory settings or put your privacy first. When you choose Firefox for Windows as your default browser, you’re choosing to protect your data while supporting an independent tech company. Firefox is also the only major browser backed by a non-profit fighting to give you more openness, transparency and control of your life online. Join hundreds of millions of people who choose to protect what's important by choosing Firefox - a web browser designed to be fast, easy to use, customizable and private.\r\n\r\nA BROWSER THAT REFLECTS WHO YOU ARE \r\n- You can choose whatever default browser you want. Maybe think about using the only super-fast, ultra-private browser that’s backed by a non-profit? No pressure though.\r\n- Our secret sauce: Firefox Add-ons. They’re like these magical power-ups you can add to your Firefox browser to make it even better.\r\n- From watching a web tutorial to keeping an eye on your favorite team, your video follows you while you multitask with Picture-in-Picture.\r\n\r\nFAST. PRIVATE. SAFE.\r\nFirefox browser gives you effortless privacy protection with lightning-fast page loads. Enhanced Tracking Protection automatically blocks over 2,000 known online trackers from invading your privacy and slowing down your webpages. Firefox browser also introduces a clean new design that makes it easier to get more things done, more quickly. Plus, with smart browsing features built in, Firefox lets you take your privacy, passwords, and bookmarks with you safely wherever you go.\r\n\r\nYOU COME FIRST\r\nAs the internet grows and changes, Firefox continues to focus on your right to privacy — we call it the Personal Data Promise: Take less. Keep it safe. No secrets. Your data, your web activity, your life online is protected with Firefox.\r\n\r\nHOW FIREFOX COMPARES TO OTHER BROWSERS\r\nWhen it comes to all-around performance — speed, design, utility, ease of use, and a steadfast commitment to your privacy — no browser beats Firefox. And being backed by a non-profit means that unlike other browsers, we have no financial stake in following you around the web.\r\n\r\nPICK UP RIGHT WHERE YOU LEFT OFF\r\nStart using Firefox on your phone then switch to the Firefox browser on your computer. With Firefox across your devices you can take your bookmarks, saved logins and browsing history wherever you go. Firefox browser also takes the guesswork out of passwords by remembering your passwords across devices.\r\n\r\nKEEP FACEBOOK OFF YOUR BACK\r\nBuilt for Firefox, the Facebook Container extension helps to stop Facebook from collecting your personal data and web activity when you’re outside of Facebook — yes, they’re actually doing this.\r\n\r\nYOUR SAVE BUTTON FOR THE INTERNET\r\nHit the Pocket button when you come across an interesting article, video, recipe — you know, the good stuff on the internet — but just don’t have the time. Pocket stashes it in your own private, distraction-free space to dive into later.\r\n\r\nMULTITASKING MADE EASY\r\nPlay a video in a separate, scalable window that pins to the front of your desktop with the Picture-in-Picture feature. It stays and plays while you go about your other business on other tabs or do things outside of Firefox. \r\n\r\nEXTENSIONS FOR EVERY INTEREST\r\nFrom security to news to gaming, there’s an extension for everyone. Add as many as you want until your browser is just right.\r\n\r\nCHALLENGING THE STATUS QUO SINCE 1998\r\nFirefox was created by Mozilla as a faster, more private alternative to browsers like Microsoft Edge and Google Chrome. Our mission-driven company and volunteer community continue to put your privacy above all else."",""Tags"":[],""Agreements"":[{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Category"",""Agreement"":""Productivity""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Pricing"",""Agreement"":""Free""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Free Trial"",""Agreement"":""No""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Terms of Transaction"",""AgreementUrl"":""https://aka.ms/microsoft-store-terms-of-transaction""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Seizure Warning"",""AgreementUrl"":""https://aka.ms/microsoft-store-seizure-warning""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.AgreementDetail, StoreEdgeFD"",""AgreementLabel"":""Store License Terms"",""AgreementUrl"":""https://aka.ms/microsoft-store-license""}]},""Installers"":[{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.BigCatInstaller, StoreEdgeFD"",""MSStoreProductIdentifier"":""9NZVDKPMR9RD"",""Architecture"":""x86"",""InstallerType"":""msstore"",""Markets"":{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.Markets, StoreEdgeFD"",""AllowedMarkets"":[""US""]},""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""Scope"":""user""},{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.BigCatInstaller, StoreEdgeFD"",""MSStoreProductIdentifier"":""9NZVDKPMR9RD"",""Architecture"":""x64"",""InstallerType"":""msstore"",""Markets"":{""$type"":""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.PackageManifest.Markets, StoreEdgeFD"",""AllowedMarkets"":[""US""]},""PackageFamilyName"":""Mozilla.Firefox_n80bbvh6b1yt2"",""Scope"":""user""}]}]}}"; + + var httpClient = Substitute.For(); + var logger = Substitute.For>(); + var client = new MicrosoftStoreClient(httpClient, logger); + var cancellationToken = new CancellationToken(); + + var fakeResponse = new HttpResponseMessage + { + Content = new StringContent(responseData, Encoding.UTF8, "application/json") + }; + + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Get + && req.RequestUri == new Uri($"https://storeedgefd.dsx.mp.microsoft.com/v9.0/packageManifests/{packageId}")), cancellationToken) + .Returns(fakeResponse); + + // Act + var result = await client.GetManifestAsync(packageId, cancellationToken); + + // Assert + Assert.NotNull(result); + Assert.Equal(packageId, result.Data.PackageIdentifier); + Assert.Equal("Mozilla Firefox", result.Data.Versions[0].DefaultLocale.PackageName); + } + + [Fact] + public async Task GetPackageIdForFirstMatchAsync_ReturnsExpectedResult() + { + // Arrange + var httpClient = Substitute.For(); + var logger = Substitute.For>(); + var client = new MicrosoftStoreClient(httpClient, logger); + var cancellationToken = new CancellationToken(); + + var expectedResponse = new HttpResponseMessage + { + Content = new StringContent( + @"{ + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchResponse, StoreEdgeFD"", + ""Data"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchData, StoreEdgeFD"", + ""PackageIdentifier"": ""9NZVDKPMR9RD"", + ""PackageName"": ""Mozilla Firefox"", + ""Publisher"": ""Mozilla"", + ""Versions"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchVersion, StoreEdgeFD"", + ""PackageVersion"": ""Unknown"", + ""PackageFamilyNames"": [ + ""Mozilla.Firefox_n80bbvh6b1yt2"" + ] + } + ] + } + ] + }", Encoding.UTF8, "application/json") + }; + + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Post + && req.RequestUri == new Uri("https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch")), cancellationToken) + .Returns(expectedResponse); + + // Act + var result = await client.GetPackageIdForFirstMatchAsync("FireFox", cancellationToken); + + // Assert + Assert.Equal("9NZVDKPMR9RD", result); + } + + [Fact] + public async Task Search_ReturnsExpectedResult() + { + // Arrange + var httpClient = Substitute.For(); + var logger = Substitute.For>(); + var client = new MicrosoftStoreClient(httpClient, logger); + var cancellationToken = new CancellationToken(); + + var expectedResponse = new HttpResponseMessage + { + Content = new StringContent( + @"{ + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchResponse, StoreEdgeFD"", + ""Data"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchData, StoreEdgeFD"", + ""PackageIdentifier"": ""9NZVDKPMR9RD"", + ""PackageName"": ""Mozilla Firefox"", + ""Publisher"": ""Mozilla"", + ""Versions"": [ + { + ""$type"": ""Microsoft.Marketplace.Storefront.StoreEdgeFD.BusinessLogic.Response.ManifestSearch.ManifestSearchVersion, StoreEdgeFD"", + ""PackageVersion"": ""Unknown"", + ""PackageFamilyNames"": [ + ""Mozilla.Firefox_n80bbvh6b1yt2"" + ] + } + ] + } + ] + }", Encoding.UTF8, "application/json") + }; + + httpClient.SendAsync(Arg.Is(req => + req.Method == HttpMethod.Post + && req.RequestUri == new Uri("https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch")), cancellationToken) + .Returns(expectedResponse); + + // Act + var result = await client.Search("FireFox", cancellationToken); + + // Assert + Assert.NotNull(result); + Assert.Equal("Mozilla Firefox", result?.Data.FirstOrDefault()?.PackageName); + Assert.Equal("9NZVDKPMR9RD", result?.Data.FirstOrDefault()?.PackageIdentifier); + } + +}