commit c255b68a652c59370a2ee9348a9ef36aa18ea1d3
parent 804c1252382cd0435f9fde68b192d2012516c3d0
Author: JohnMcPMS <johnmcp@microsoft.com>
Date: Tue, 26 Sep 2023 08:15:01 -0700
Enable COM API access to correlate with the tracking database only (#3670)
This change adds a flag that lets the caller specify that they are only interested in the installed tracking data, not the available packages. With it set, one can correlate to the catalog via the tracking database without ever needing to access the remote source information.
Diffstat:
6 files changed, 129 insertions(+), 30 deletions(-)
diff --git a/src/AppInstallerRepositoryCore/CompositeSource.cpp b/src/AppInstallerRepositoryCore/CompositeSource.cpp
@@ -1412,15 +1412,12 @@ namespace AppInstaller::Repository
}
}
- bool addedAvailablePackage = false;
-
// Directly search for the available package from tracking information.
if (trackingPackage)
{
auto availablePackage = GetTrackedPackageFromAvailableSource(result, trackedSource, trackingPackage->GetProperty(PackageProperty::Id));
if (availablePackage)
{
- addedAvailablePackage = true;
compositePackage->AddAvailablePackage(std::move(availablePackage));
}
compositePackage->SetTracking(std::move(trackedSource), std::move(trackingPackage), std::move(trackingPackageVersion));
@@ -1453,7 +1450,6 @@ namespace AppInstaller::Repository
});
// For non pinning cases. We found some matching packages here, don't keep going.
- addedAvailablePackage = true;
compositePackage->AddAvailablePackage(std::move(availablePackage));
}
}
diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h
@@ -225,6 +225,10 @@ namespace AppInstaller::Repository
// Set background update check interval.
void SetBackgroundUpdateInterval(TimeSpan interval);
+ // Indicates that we are only interested in the PackageTrackingCatalog for the source.
+ // Must be set before Open to have effect, and will prevent the underlying source from being updated or opened.
+ void InstalledPackageInformationOnly(bool value);
+
// Execute a search on the source.
SearchResult Search(const SearchRequest& request) const;
@@ -287,6 +291,7 @@ namespace AppInstaller::Repository
bool m_isSourceToBeAdded = false;
bool m_isComposite = false;
std::optional<TimeSpan> m_backgroundUpdateInterval;
+ bool m_installedPackageInformationOnly = false;
mutable PackageTrackingCatalog m_trackingCatalog;
};
}
diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp
@@ -202,6 +202,53 @@ namespace AppInstaller::Repository
SourceDetails m_details;
std::exception_ptr m_exception;
};
+
+ // A wrapper that doesn't actually forward the search requests.
+ struct TrackingOnlySourceWrapper : public ISource
+ {
+ TrackingOnlySourceWrapper(std::shared_ptr<ISourceReference> wrapped) : m_wrapped(std::move(wrapped))
+ {
+ m_identifier = m_wrapped->GetIdentifier();
+ }
+
+ const std::string& GetIdentifier() const override { return m_identifier; }
+
+ SourceDetails& GetDetails() const override { return m_wrapped->GetDetails(); }
+
+ SourceInformation GetInformation() const override { return m_wrapped->GetInformation(); }
+
+ SearchResult Search(const SearchRequest&) const override { return {}; }
+
+ void* CastTo(ISourceType) override { return nullptr; }
+
+ private:
+ std::shared_ptr<ISourceReference> m_wrapped;
+ std::string m_identifier;
+ };
+
+ // A wrapper to create another wrapper.
+ struct TrackingOnlyReferenceWrapper : public ISourceReference
+ {
+ TrackingOnlyReferenceWrapper(std::shared_ptr<ISourceReference> wrapped) : m_wrapped(std::move(wrapped)) {}
+
+ std::string GetIdentifier() override { return m_wrapped->GetIdentifier(); }
+
+ SourceDetails& GetDetails() override { return m_wrapped->GetDetails(); }
+
+ SourceInformation GetInformation() override { return m_wrapped->GetInformation(); }
+
+ bool SetCustomHeader(std::optional<std::string>) override { return false; }
+
+ void SetCaller(std::string caller) override { m_wrapped->SetCaller(std::move(caller)); }
+
+ std::shared_ptr<ISource> Open(IProgressCallback&) override
+ {
+ return std::make_shared<TrackingOnlySourceWrapper>(m_wrapped);
+ }
+
+ private:
+ std::shared_ptr<ISourceReference> m_wrapped;
+ };
}
std::unique_ptr<ISourceFactory> ISourceFactory::GetForType(std::string_view type)
@@ -475,6 +522,11 @@ namespace AppInstaller::Repository
m_backgroundUpdateInterval = interval;
}
+ void Source::InstalledPackageInformationOnly(bool value)
+ {
+ m_installedPackageInformationOnly = value;
+ }
+
SearchResult Source::Search(const SearchRequest& request) const
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !m_source);
@@ -554,51 +606,68 @@ namespace AppInstaller::Repository
if (!m_source)
{
+ std::vector<std::shared_ptr<ISourceReference>>* sourceReferencesToOpen = nullptr;
+ std::vector<std::shared_ptr<ISourceReference>> sourceReferencesForTrackingOnly;
std::unique_ptr<SourceList> sourceList;
- // Check for updates before opening.
- for (auto& sourceReference : m_sourceReferences)
+ if (m_installedPackageInformationOnly)
{
- auto& details = sourceReference->GetDetails();
- if (ShouldUpdateBeforeOpen(details, m_backgroundUpdateInterval))
+ sourceReferencesToOpen = &sourceReferencesForTrackingOnly;
+
+ // Create a wrapper for each reference
+ for (auto& sourceReference : m_sourceReferences)
{
- try
+ sourceReferencesForTrackingOnly.emplace_back(std::make_shared<TrackingOnlyReferenceWrapper>(sourceReference));
+ }
+ }
+ else
+ {
+ // Check for updates before opening.
+ for (auto& sourceReference : m_sourceReferences)
+ {
+ auto& details = sourceReference->GetDetails();
+ if (ShouldUpdateBeforeOpen(details, m_backgroundUpdateInterval))
{
- // TODO: Consider adding a context callback to indicate we are doing the same action
- // to avoid the progress bar fill up multiple times.
- if (BackgroundUpdateSourceFromDetails(details, progress))
+ try
{
- if (sourceList == nullptr)
+ // TODO: Consider adding a context callback to indicate we are doing the same action
+ // to avoid the progress bar fill up multiple times.
+ if (BackgroundUpdateSourceFromDetails(details, progress))
{
- sourceList = std::make_unique<SourceList>();
+ if (sourceList == nullptr)
+ {
+ sourceList = std::make_unique<SourceList>();
+ }
+
+ auto detailsInternal = sourceList->GetSource(details.Name);
+ detailsInternal->LastUpdateTime = details.LastUpdateTime;
+ sourceList->SaveMetadata(*detailsInternal);
+ }
+ else
+ {
+ AICLI_LOG(Repo, Error, << "Failed to update source: " << details.Name);
+ result.emplace_back(details);
}
-
- auto detailsInternal = sourceList->GetSource(details.Name);
- detailsInternal->LastUpdateTime = details.LastUpdateTime;
- sourceList->SaveMetadata(*detailsInternal);
}
- else
+ catch (...)
{
- AICLI_LOG(Repo, Error, << "Failed to update source: " << details.Name);
+ LOG_CAUGHT_EXCEPTION();
+ AICLI_LOG(Repo, Warning, << "Failed to update source: " << details.Name);
result.emplace_back(details);
}
}
- catch (...)
- {
- LOG_CAUGHT_EXCEPTION();
- AICLI_LOG(Repo, Warning, << "Failed to update source: " << details.Name);
- result.emplace_back(details);
- }
}
+
+ sourceReferencesToOpen = &m_sourceReferences;
}
- if (m_sourceReferences.size() > 1)
+ if (sourceReferencesToOpen->size() > 1)
{
AICLI_LOG(Repo, Info, << "Multiple sources available, creating aggregated source.");
auto aggregatedSource = std::make_shared<CompositeSource>("*DefaultSource");
std::vector<std::shared_ptr<OpenExceptionProxy>> openExceptionProxies;
- for (auto& sourceReference : m_sourceReferences)
+ for (auto& sourceReference : *sourceReferencesToOpen)
{
AICLI_LOG(Repo, Info, << "Adding to aggregated source: " << sourceReference->GetDetails().Name);
@@ -628,7 +697,7 @@ namespace AppInstaller::Repository
}
else
{
- m_source = m_sourceReferences[0]->Open(progress);
+ m_source = (*sourceReferencesToOpen)[0]->Open(progress);
}
}
diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp
@@ -28,6 +28,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
if (IsBackgroundProcessForPolicy())
{
+ // Delay the default update interval for these background processes
static constexpr winrt::Windows::Foundation::TimeSpan s_PackageCatalogUpdateIntervalDelay_Base = 168h; //1 week
// Add a bit of randomness to the default interval time
@@ -35,6 +36,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation
std::uniform_int_distribution<long long> distribution(0, 604800);
m_packageCatalogBackgroundUpdateInterval = s_PackageCatalogUpdateIntervalDelay_Base + std::chrono::seconds(distribution(randomEngine));
+
+ // Prevent any update / data processing by default for these background processes
+ m_installedPackageInformationOnly = true;
}
}
void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions options)
@@ -95,6 +99,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
auto copy = catalogImpl->m_sourceReference;
copy.SetCaller(callerName);
copy.SetBackgroundUpdateInterval(catalog.PackageCatalogBackgroundUpdateInterval());
+ copy.InstalledPackageInformationOnly(catalog.InstalledPackageInformationOnly());
copy.Open(progress);
remoteSources.emplace_back(std::move(copy));
}
@@ -137,6 +142,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
source = m_sourceReference;
source.SetCaller(callerName);
source.SetBackgroundUpdateInterval(PackageCatalogBackgroundUpdateInterval());
+ source.InstalledPackageInformationOnly(m_installedPackageInformationOnly);
source.Open(progress);
}
@@ -216,6 +222,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
return m_acceptSourceAgreements;
}
+
void PackageCatalogReference::PackageCatalogBackgroundUpdateInterval(winrt::Windows::Foundation::TimeSpan const& value)
{
if (IsComposite())
@@ -229,4 +236,19 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
return m_packageCatalogBackgroundUpdateInterval;
}
+
+ bool PackageCatalogReference::InstalledPackageInformationOnly()
+ {
+ return m_installedPackageInformationOnly;
+ }
+
+ void PackageCatalogReference::InstalledPackageInformationOnly(bool value)
+ {
+ if (IsComposite())
+ {
+ throw winrt::hresult_illegal_state_change();
+ }
+
+ m_installedPackageInformationOnly = value;
+ }
}
diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h
@@ -22,12 +22,14 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::SourceAgreement> SourceAgreements();
hstring AdditionalPackageCatalogArguments();
void AdditionalPackageCatalogArguments(hstring const& value);
- // Contract 6.0
+ // Contract 6
bool AcceptSourceAgreements();
void AcceptSourceAgreements(bool value);
// Contract 8.0
winrt::Windows::Foundation::TimeSpan PackageCatalogBackgroundUpdateInterval();
void PackageCatalogBackgroundUpdateInterval(winrt::Windows::Foundation::TimeSpan const& value);
+ bool InstalledPackageInformationOnly();
+ void InstalledPackageInformationOnly(bool value);
#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
@@ -37,6 +39,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
::AppInstaller::Repository::Source m_sourceReference;
std::optional<std::string> m_additionalPackageCatalogArguments;
bool m_acceptSourceAgreements = true;
+ bool m_installedPackageInformationOnly = false;
std::once_flag m_sourceAgreementsOnceFlag;
winrt::Windows::Foundation::TimeSpan m_packageCatalogBackgroundUpdateInterval = winrt::Windows::Foundation::TimeSpan::zero();
#endif
diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl
@@ -754,6 +754,10 @@ namespace Microsoft.Management.Deployment
{
/// Time interval for package catalog to check for an update. Setting to zero will disable the check for update.
Windows.Foundation.TimeSpan PackageCatalogBackgroundUpdateInterval;
+
+ // When set to true, the opened catalog will only provide the information regarding packages installed from this catalog.
+ // In this mode, no external resources should be required.
+ Boolean InstalledPackageInformationOnly;
}
}