winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

InstallerMetadataCollectionContext.h (7806B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 
      5 #include <AppInstallerVersions.h>
      6 #include <winget/Manifest.h>
      7 #include <winget/JsonUtil.h>
      8 #include <winget/ThreadGlobals.h>
      9 #include <winget/ARPCorrelation.h>
     10 #include <winget/InstalledFilesCorrelation.h>
     11 #include <winget/IconExtraction.h>
     12 
     13 #include <filesystem>
     14 #include <map>
     15 #include <memory>
     16 #include <optional>
     17 #include <ostream>
     18 #include <string>
     19 #include <string_view>
     20 
     21 namespace AppInstaller::Repository::Metadata
     22 {
     23     // The overall metadata that we collect.
     24     struct ProductMetadata
     25     {
     26         ProductMetadata() = default;
     27 
     28         // Removes all stored data.
     29         void Clear();
     30 
     31         // Load the metadata from an existing JSON blob.
     32         void FromJson(const web::json::value& json);
     33 
     34         // Create a JSON value for the metadata using the given schema version.
     35         web::json::value ToJson(const Utility::Version& schemaVersion, size_t maximumSizeInBytes);
     36 
     37         // Copies the metadata from the source. If the given submission identifier does not match
     38         // the source, it's data is moved to historical.
     39         void CopyFrom(const ProductMetadata& source, std::string_view submissionIdentifier);
     40 
     41         // The installer specific metadata that we collect.
     42         struct InstallerMetadata
     43         {
     44             friend ProductMetadata;
     45 
     46             // 1.0
     47             std::string SubmissionIdentifier;
     48             std::vector<Manifest::AppsAndFeaturesEntry> AppsAndFeaturesEntries;
     49 
     50             // 1.1
     51             // If Scope value is empty, the value is not set before. If the value is Unknown, a conflicting value is encountered.
     52             std::string Scope;
     53 
     54             // 1.2
     55             // If std::nullopt, the value is not set before. If the value is empty(i.e. !HasData()), a conflicting value is encountered.
     56             std::optional<Manifest::InstallationMetadataInfo> InstalledFiles;
     57             // If std::nullopt, the value is not set before. If the vector is empty, conflicting values are encountered.
     58             std::optional<std::vector<Correlation::InstalledStartupLinkFile>> StartupLinkFiles;
     59             // Extracted icons
     60             std::vector<ExtractedIconInfo> Icons;
     61         };
     62 
     63         // Metadata from previous product revisions.
     64         struct HistoricalMetadata
     65         {
     66             // 1.0
     67             Utility::Version ProductVersionMin;
     68             Utility::Version ProductVersionMax;
     69             std::set<std::string> Names;
     70             std::set<std::string> Publishers;
     71             std::set<std::string> ProductCodes;
     72             std::set<std::string> UpgradeCodes;
     73         };
     74 
     75         // 1.0
     76         Utility::Version SchemaVersion;
     77         Utility::Version ProductVersionMin;
     78         Utility::Version ProductVersionMax;
     79         // Map from installer hash to metadata
     80         std::map<std::string, InstallerMetadata> InstallerMetadataMap;
     81         std::vector<HistoricalMetadata> HistoricalMetadataList;
     82 
     83     private:
     84         void FromJson_1_N(const web::json::value& json);
     85         web::json::value ToJson_1_N();
     86 
     87         // Removes the historical data with the oldest version.
     88         // Returns true if something was removed; false it not.
     89         bool DropOldestHistoricalData();
     90     };
     91 
     92     // Contains the functions and data used for collecting metadata from installers.
     93     struct InstallerMetadataCollectionContext
     94     {
     95         InstallerMetadataCollectionContext();
     96         InstallerMetadataCollectionContext(
     97             std::unique_ptr<Correlation::ARPCorrelationData> correlationData,
     98             std::unique_ptr<Correlation::InstalledFilesCorrelation> installedFilesCorrelation,
     99             const std::wstring& json);
    100 
    101         InstallerMetadataCollectionContext(const InstallerMetadataCollectionContext&) = delete;
    102         InstallerMetadataCollectionContext& operator=(const InstallerMetadataCollectionContext&) = delete;
    103 
    104         InstallerMetadataCollectionContext(InstallerMetadataCollectionContext&&) = default;
    105         InstallerMetadataCollectionContext& operator=(InstallerMetadataCollectionContext&&) = default;
    106 
    107         // Create from various forms of JSON input to prevent type collisions on constructor.
    108         static std::unique_ptr<InstallerMetadataCollectionContext> FromFile(const std::filesystem::path& file, const std::filesystem::path& logFile);
    109         static std::unique_ptr<InstallerMetadataCollectionContext> FromURI(std::wstring_view uri, const std::filesystem::path& logFile);
    110         static std::unique_ptr<InstallerMetadataCollectionContext> FromJSON(const std::wstring& json, const std::filesystem::path& logFile);
    111 
    112         // Completes the collection, writing to the given location.
    113         void Complete(const std::filesystem::path& output);
    114 
    115         // Completes the collection, writing to the given location.
    116         void Complete(std::ostream& output);
    117 
    118         static std::wstring Merge(const std::wstring& json, size_t maximumSizeInBytes, const std::filesystem::path& logFile);
    119 
    120     private:
    121         // Initializes the context runtime, including the log file if provided.
    122         static std::unique_ptr<ThreadLocalStorage::PreviousThreadGlobals> InitializeLogging(ThreadLocalStorage::WingetThreadGlobals& threadGlobals, const std::filesystem::path& logFile);
    123         std::unique_ptr<ThreadLocalStorage::PreviousThreadGlobals> InitializeLogging(const std::filesystem::path& logFile);
    124 
    125         // Sets the collection context input and the preinstall state.
    126         void InitializePreinstallState(const std::wstring& json);
    127 
    128         // Creates the output ProductMetadata and diagnostics objects for output
    129         void ComputeOutputData();
    130 
    131         // Callers should set the thread globals before calling this.
    132         void CompleteWithThreadGlobalsSet(std::ostream& output);
    133 
    134         // Parse version 1.0 of input JSON
    135         void ParseInputJson_1_0(web::json::value& input);
    136 
    137         // Create version 1.0 of output JSON
    138         web::json::value CreateOutputJson_1_0();
    139 
    140         // Determines whether an error has occurred in the context.
    141         bool ContainsError() const;
    142 
    143         // Collects information from the exception for error reporting.
    144         void CollectErrorDataFromException(std::exception_ptr exception);
    145 
    146         // Create version 1.0 of error JSON
    147         web::json::value CreateErrorJson_1_0();
    148 
    149         // Merge using merge input version 1.0
    150         static web::json::value Merge_1_0(web::json::value& input, size_t maximumSizeInBytes);
    151 
    152         ThreadLocalStorage::WingetThreadGlobals m_threadGlobals;
    153 
    154         // Parsed input
    155         Utility::Version m_inputVersion;
    156         Utility::Version m_supportedMetadataVersion;
    157         ProductMetadata m_currentMetadata;
    158         web::json::value m_submissionData;
    159         std::string m_submissionIdentifier;
    160         std::string m_installerHash;
    161         Manifest::Manifest m_incomingManifest;
    162 
    163         std::unique_ptr<Correlation::ARPCorrelationData> m_correlationData;
    164         std::unique_ptr<Correlation::InstalledFilesCorrelation> m_installedFilesCorrelation;
    165 
    166         // Output data
    167         enum class OutputStatus
    168         {
    169             // Version 1.0 status values
    170             Unknown,
    171             Success,
    172             Error,
    173             LowConfidence,
    174         };
    175 
    176         // Convert status to a JSON string value
    177         static utility::string_t ToString(OutputStatus status);
    178 
    179         OutputStatus m_outputStatus = OutputStatus::Unknown;
    180         ProductMetadata m_outputMetadata;
    181         web::json::value m_outputDiagnostics;
    182 
    183         // Error data storage
    184         HRESULT m_errorHR = S_OK;
    185         std::string m_errorText;
    186     };
    187 }