/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. /// </param> /// <param name="retryAttempts"> /// The number of attempts a failed operation should be retried. /// </param> /// <param name="ownClient"> /// A boolean flag indicating whether or not the resilient client takes ownership of /// <paramref name="client" /> and disposes it when the resilient client itself is disposed. If the /// resilient client takes ownership of <paramref name="client" /> and you reference or dispose /// <paramref name="client" /> after you create the resilient client, the behavior of the resilient client /// and <paramref name="client" /> is undefined. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown if <paramref name="retryAttempts" /> is less than or equal to <c>0</c>. /// </exception> public static ResilientBrowsingClient Create(IBrowsingClient client, int retryAttempts, bool ownClient) { // ... // // Throws an exception if the operation fails. return(client is ResilientBrowsingClient resilientClient ? resilientClient : new ResilientBrowsingClient(client, retryAttempts, ownClient)); }
/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. /// </param> /// <param name="retryAttempts"> /// The number of attempts a failed operation should be retried. /// </param> /// <param name="ownClient"> /// A boolean flag indicating whether or not the resilient client takes ownership of /// <paramref name="client" /> and disposes it when the resilient client itself is disposed. If the /// resilient client takes ownership of <paramref name="client" /> and you reference or dispose /// <paramref name="client" /> after you create the resilient client, the behavior of the resilient client /// and <paramref name="client" /> is undefined. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown if <paramref name="retryAttempts" /> is less than or equal to <c>0</c>. /// </exception> public ResilientBrowsingClient(IBrowsingClient client, int retryAttempts, bool ownClient) { Guard.ThrowIf(nameof(retryAttempts), retryAttempts).LessThanOrEqualTo(0); this._client = BrowsingClientProxy.Create(client); this._disposed = false; this._ownClient = ownClient; this._retryAttempts = retryAttempts; // ... // // ... this._resiliencyPolicy = CreateResiliencyPolicy(this); // <summary> // Create Resiliency Policy. // </summary> IAsyncPolicy CreateResiliencyPolicy(ResilientBrowsingClient @this) { var cPolicyBuilder = Policy.Handle <TimeoutException>(); var cPolicy = cPolicyBuilder.WaitAndRetryAsync(@this._retryAttempts, CreateRetryPolicyTimeout); return(cPolicy); } // <summary> // Create Retry Policy Timeout. // </summary> TimeSpan CreateRetryPolicyTimeout(int cRetryAttempt) { var cDelaySeconds = Math.Pow(2, cRetryAttempt); var cDelay = TimeSpan.FromSeconds(cDelaySeconds); return(cDelay); } }
internal static BrowsingClientProxy Create(IBrowsingClient client) { // ... // // Throws an exception if the operation fails. return(client is BrowsingClientProxy clientProxy ? clientProxy : new BrowsingClientProxy(client)); }
/// <summary> /// Create a Client Proxy. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. The client proxy takes ownership of /// <paramref name="client" /> and will dispose it when the client proxy itself is disposed. If you /// reference or dispose <paramref name="client" /> after you create the client proxy, the behavior of the /// client proxy and <paramref name="client" /> is undefined. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> private BrowsingClientProxy(IBrowsingClient client) { Guard.ThrowIf(nameof(client), client).Null(); this._client = client; this._disposed = false; }
/// <summary> /// Set Client. /// </summary> /// <param name="value"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="ownClient"> /// A boolean flag indicating whether or not the <see cref="BaseBrowsingService" /> takes ownership of the /// client and disposes it when the service itself is disposed. If the service takes ownership of the /// client and you reference or dispose the client after you create the service, the behavior of the /// service and the client is undefined. /// </param> /// <returns> /// This service builder. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="value" /> is a null reference. /// </exception> public T SetClient(IBrowsingClient value, bool ownClient) { Guard.ThrowIf(nameof(value), value).Null(); this.Client = value; this.OwnClient = ownClient; return((T)this); }
/// <summary> /// Set Client. /// </summary> /// <param name="value"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="ownClient"> /// A boolean flag indicating whether or not the <see cref="BrowsingDatabaseManager" /> takes ownership of /// the client and disposes it when the database manager itself is disposed. If the database manager takes /// ownership of the client and you reference or dispose the client after you create the database manager, /// the behavior of the database manager and the client is undefined. /// </param> /// <returns> /// This database manager builder. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="value" /> is a null reference. /// </exception> public BrowsingDatabaseManagerBuilder SetClient(IBrowsingClient value, bool ownClient) { Guard.ThrowIf(nameof(value), value).Null(); this.Client = value; this.OwnClient = ownClient; return(this); }
/// <summary> /// Get Threat List Updates Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="request"> /// A <see cref="ThreatListUpdateRequest" />. /// </param> /// <returns> /// A <see cref="ThreatListUpdateResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="request" /> is a null /// reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <ThreatListUpdateResponse> GetThreatListUpdatesAsync(this IBrowsingClient @this, ThreatListUpdateRequest request) { Guard.ThrowIf(nameof(@this), @this).Null(); // ... // // Throws an exception if the operation fails. var getThreatListUpdatesTask = @this.GetThreatListUpdatesAsync(request, CancellationToken.None); return(getThreatListUpdatesTask); }
/// <summary> /// Find Full Hashes Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="request"> /// A <see cref="FullHashRequest" />. /// </param> /// <returns> /// A <see cref="FullHashResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="request" /> is a null /// reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <FullHashResponse> FindFullHashesAsync(this IBrowsingClient @this, FullHashRequest request) { Guard.ThrowIf(nameof(@this), @this).Null(); // ... // // Throws an exception if the operation fails. var findFullHashesTask = @this.FindFullHashesAsync(request, CancellationToken.None); return(findFullHashesTask); }
/// <summary> /// Get Threat List Updates Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="threatList"> /// A <see cref="ThreatList" /> to retrieve. /// </param> /// <param name="updateConstraints"> /// The <see cref="ThreatListUpdateConstraints" /> to apply when <paramref name="threatList" /> is /// retrieved. A null reference indicates no <see cref="ThreatListUpdateConstraints" /> should be applied. /// </param> /// <param name="cancellationToken"> /// A cancellation token to cancel the asynchronous operation with. /// </param> /// <returns> /// A <see cref="ThreatListUpdateResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="threatList" /> is a /// null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if the <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.OperationCanceledException"> /// Thrown if the asynchronous operation is cancelled. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <ThreatListUpdateResponse> GetThreatListUpdatesAsync(this IBrowsingClient @this, ThreatList threatList, ThreatListUpdateConstraints updateConstraints, CancellationToken cancellationToken) { Guard.ThrowIf(nameof(@this), @this).Null(); Guard.ThrowIf(nameof(threatList), threatList).Null(); var threatListUpdateRequestBuilder = ThreatListUpdateRequest.Build(); threatListUpdateRequestBuilder.AddQuery(b => { b.SetThreatListDescriptor(threatList.Descriptor); b.SetThreatListState(threatList.State); b.SetUpdateConstraints(updateConstraints); return(b.Build()); }); // ... // // Throws an exception if the operation fails. var threatListUpdateRequest = threatListUpdateRequestBuilder.Build(); var getThreatListUpdatesTask = @this.GetThreatListUpdatesAsync(threatListUpdateRequest, cancellationToken); return(getThreatListUpdatesTask); }
public static Task <FullHashResponse> FindFullHashesAsync(this IBrowsingClient @this, string sha256HashPrefix, IEnumerable <ThreatList> threatLists, CancellationToken cancellationToken) { Guard.ThrowIf(nameof(@this), @this).Null(); Guard.ThrowIf(nameof(threatLists), threatLists).Null(); // ... // // Throws an exception if the operation fails. var fullHashRequestBuilder = FullHashRequest.Build(); fullHashRequestBuilder.AddSha256HashPrefix(sha256HashPrefix); foreach (var threatList in threatLists) { fullHashRequestBuilder.AddQuery(threatList.Descriptor, threatList.State); } // ... // // Throws an exception if the operation fails. var fullHashRequest = fullHashRequestBuilder.Build(); var findFullHashesTask = @this.FindFullHashesAsync(fullHashRequest, cancellationToken); return(findFullHashesTask); }
/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. The resilient client takes ownership of /// <paramref name="client" /> and will dispose it when the resilient cache itself is disposed. If you /// reference or dispose <paramref name="client" /> after you create the resilient cache, the behavior of /// the resilient cache and <paramref name="client" /> is undefined. /// </param> /// <param name="retryAttempts"> /// The number of attempts a failed operation should be retried. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown if <paramref name="retryAttempts" /> is less than or equal to <c>0</c>. /// </exception> public static ResilientBrowsingClient Create(IBrowsingClient client, int retryAttempts) => ResilientBrowsingClient.Create(client, retryAttempts, true);
/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. The resilient client takes ownership of /// <paramref name="client" /> and will dispose it when the resilient cache itself is disposed. If you /// reference or dispose <paramref name="client" /> after you create the resilient cache, the behavior of /// the resilient cache and <paramref name="client" /> is undefined. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> public ResilientBrowsingClient(IBrowsingClient client) : this(client, 5) { }
/// <summary> /// Lookup a URL. /// </summary> /// <param name="cache"> /// A <see cref="IBrowsingCache" />. /// </param> /// <param name="client"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="database"> /// An <see cref="IUnmanagedBrowsingDatabase" />. /// </param> /// <param name="url"> /// A <see cref="Url" /> to lookup. /// </param> /// <param name="cancellationToken"> /// A cancellation token to cancel the asynchronous operation with. /// </param> /// <returns> /// A <see cref="UrlLookupResult" /> indicating whether <paramref name="url" /> is /// <see cref="UrlLookupResultCode.Safe" /> or <see cref="UrlLookupResultCode.Unsafe" />. /// </returns> /// <exception cref="Gee.External.Browsing.Cache.BrowsingCacheException"> /// Thrown if a caching error occurs. If you're not interested in handling this exception, catch /// <see cref="BrowsingException" /> instead. /// </exception> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. If you're not interested /// in handling this exception, catch <see cref="BrowsingException" /> instead. /// </exception> /// <exception cref="Gee.External.Browsing.Databases.BrowsingDatabaseException"> /// Thrown if a database error occurs. If you're not interested in handling this exception, catch /// <see cref="BrowsingException" /> instead. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="url" /> is a null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if <paramref name="cache" /> is disposed, or if <paramref name="client" /> is disposed, or if /// <paramref name="database" /> is disposed. /// </exception> /// <exception cref="System.OperationCanceledException"> /// Thrown if the asynchronous operation is cancelled. /// </exception> private protected async Task <UrlLookupResult> LookupAsync(IBrowsingCache cache, IBrowsingClient client, IUnmanagedBrowsingDatabase database, Url url, CancellationToken cancellationToken) { // ... // // First, lookup the URL in the local database. Throws an exception if the operation fails. var urlLookupDate = DateTime.UtcNow; UrlLookupResult urlLookupResult; var databaseLookupTask = database.LookupAsync(url); var databaseLookResult = await databaseLookupTask.ConfigureAwait(false); if (databaseLookResult.IsDatabaseMiss) { // ... // // If the URL does not exist in the local database, indicate the URL is safe. urlLookupResult = UrlLookupResult.Safe(url, urlLookupDate); } else if (databaseLookResult.IsDatabaseStale) { // ... // // If the local database is expired/out-of-date/stale, indicate the nature of the URL cannot // be determined as a result. urlLookupResult = UrlLookupResult.DatabaseStale(url, urlLookupDate); } else { // ... // // If the URL exists in the local database, look it up in the cache. Throws an exception if // the operation fails. var sha256Hash = databaseLookResult.Sha256Hash; var sha256HashPrefix = databaseLookResult.Sha256HashPrefix; var cacheLookupTask = cache.LookupAsync(sha256Hash, sha256HashPrefix, cancellationToken); var cacheLookupResult = await cacheLookupTask.ConfigureAwait(false); if (cacheLookupResult.IsCacheSafeHit) { // ... // // If we get a cache safe hit, indicate the URL is safe. urlLookupResult = UrlLookupResult.Safe(url, urlLookupDate); } else if (cacheLookupResult.IsCacheUnsafeHit) { // ... // // If we get a cache unsafe hit, indicate the URL is unsafe. If we get a cache unsafe hit, // it is guaranteed we find a URL expression for the threat, since it is essentially the // URL expression that is cached. var unsafeThreatListDescriptors = cacheLookupResult.UnsafeThreatListDescriptors; url.TryGetExpressionForSha256Hash(sha256Hash, out var unsafeUrlExpression); urlLookupResult = UrlLookupResult.Unsafe(url, urlLookupDate, unsafeUrlExpression, unsafeThreatListDescriptors); } else { // ... // // If we get a cache miss, verify the URL with the Google Safe Browsing API. Throws an // exception if the operation fails. var threatLists = databaseLookResult.ThreatLists; var findFullHashesTask = client.FindFullHashesAsync(sha256HashPrefix, threatLists, cancellationToken); var fullHashResponse = await findFullHashesTask.ConfigureAwait(false); // ... // // Throws an exception if the operation fails. var safeCacheEntryExpirationDate = fullHashResponse.SafeThreatsExpirationDate; var putSafeCacheEntryTask = cache.PutSafeCacheEntryAsync(sha256HashPrefix, safeCacheEntryExpirationDate, cancellationToken); await putSafeCacheEntryTask.ConfigureAwait(false); var unsafeThreats = fullHashResponse.UnsafeThreats; if (unsafeThreats.Count != 0) { var unsafeThreatGroups = unsafeThreats.GroupBy(ut => ut.Sha256Hash); foreach (var unsafeThreatGroup in unsafeThreatGroups) { // ... // // Throws an exception if the operation fails. var unsafeThreatSha256Hash = unsafeThreatGroup.Key; var putUnsafeCacheEntryTask = cache.PutUnsafeCacheEntryAsync(unsafeThreatSha256Hash, unsafeThreatGroup, cancellationToken); await putUnsafeCacheEntryTask.ConfigureAwait(false); } } // ... // // Lookup the URL in the cache again. Throws an exception if the operation fails. cacheLookupTask = cache.LookupAsync(sha256Hash, sha256HashPrefix, cancellationToken); cacheLookupResult = await cacheLookupTask.ConfigureAwait(false); if (cacheLookupResult.IsCacheSafeHit) { // ... // // If we get a cache safe hit, indicate the URL is safe. urlLookupResult = UrlLookupResult.Safe(url, urlLookupDate); } else if (cacheLookupResult.IsCacheUnsafeHit) { // ... // // If we get a cache unsafe hit, indicate the URL is unsafe. If we get a cache unsafe hit, // it is guaranteed we find a URL expression for the threat, since it is essentially the // URL expression that is cached. var unsafeThreatListDescriptors = cacheLookupResult.UnsafeThreatListDescriptors; url.TryGetExpressionForSha256Hash(sha256Hash, out var unsafeUrlExpression); urlLookupResult = UrlLookupResult.Unsafe(url, urlLookupDate, unsafeUrlExpression, unsafeThreatListDescriptors); } else { urlLookupResult = UrlLookupResult.DatabaseStale(url, urlLookupDate); } } } return(urlLookupResult); }
/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. The resilient client takes ownership of /// <paramref name="client" /> and will dispose it when the resilient cache itself is disposed. If you /// reference or dispose <paramref name="client" /> after you create the resilient cache, the behavior of /// the resilient cache and <paramref name="client" /> is undefined. /// </param> /// <param name="retryAttempts"> /// The number of attempts a failed operation should be retried. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown if <paramref name="retryAttempts" /> is less than or equal to <c>0</c>. /// </exception> public ResilientBrowsingClient(IBrowsingClient client, int retryAttempts) : this(client, retryAttempts, true) { }
/// <summary> /// Find Full Hashes Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="sha256HashPrefix"> /// A SHA256 hash prefix, formatted as a hexadecimal encoded string, identifying a threat to query. /// </param> /// <param name="threatLists"> /// A collection of <see cref="ThreatList" /> the threat identified by <paramref name="sha256HashPrefix" /> /// is associated with. /// </param> /// <returns> /// A <see cref="FullHashResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="sha256HashPrefix" /> is a /// null reference, or if <paramref name="threatLists" /> is a null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if the <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <FullHashResponse> FindFullHashesAsync(this IBrowsingClient @this, string sha256HashPrefix, IEnumerable <ThreatList> threatLists) => @this.FindFullHashesAsync(sha256HashPrefix, threatLists, CancellationToken.None);
/// <summary> /// Get Threat List Updates Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="threatList"> /// A <see cref="ThreatList" /> to retrieve. /// </param> /// <param name="updateConstraints"> /// The <see cref="ThreatListUpdateConstraints" /> to apply when <paramref name="threatList" /> is /// retrieved. A null reference indicates no <see cref="ThreatListUpdateConstraints" /> should be applied. /// </param> /// <returns> /// A <see cref="ThreatListUpdateResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="threatList" /> is a /// null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if the <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <ThreatListUpdateResponse> GetThreatListUpdatesAsync(this IBrowsingClient @this, ThreatList threatList, ThreatListUpdateConstraints updateConstraints) => @this.GetThreatListUpdatesAsync(threatList, updateConstraints, CancellationToken.None);
/// <summary> /// Get Threat List Updates Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <param name="threatLists"> /// A collection of <see cref="ThreatList" /> to retrieve. /// </param> /// <returns> /// A <see cref="ThreatListUpdateResponse" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference, or if <paramref name="threatLists" /> is a /// null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if the <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <ThreatListUpdateResponse> GetThreatListUpdatesAsync(this IBrowsingClient @this, IEnumerable <ThreatList> threatLists) => @this.GetThreatListUpdatesAsync(threatLists, CancellationToken.None);
/// <summary> /// Create a Resilient Client. /// </summary> /// <param name="client"> /// A <see cref="IBrowsingClient" /> to proxy to. The resilient client takes ownership of /// <paramref name="client" /> and will dispose it when the resilient cache itself is disposed. If you /// reference or dispose <paramref name="client" /> after you create the resilient cache, the behavior of /// the resilient cache and <paramref name="client" /> is undefined. /// </param> /// <returns> /// A resilient client. /// </returns> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="client" /> is a null reference. /// </exception> public static ResilientBrowsingClient Create(IBrowsingClient client) => ResilientBrowsingClient.Create(client, 5);
/// <summary> /// Get Threat List Descriptors Asynchronously. /// </summary> /// <param name="this"> /// A <see cref="IBrowsingClient" />. /// </param> /// <returns> /// A collection of <see cref="ThreatListDescriptor" />. /// </returns> /// <exception cref="Gee.External.Browsing.Clients.BrowsingClientException"> /// Thrown if an error communicating with the Google Safe Browsing API occurs. /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if <paramref name="this" /> is a null reference. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// Thrown if <paramref name="this" /> is disposed. /// </exception> /// <exception cref="System.TimeoutException"> /// Thrown if communication with the Google Safe Browsing API times out. /// </exception> public static Task <IEnumerable <ThreatListDescriptor> > GetThreatListDescriptorsAsync(this IBrowsingClient @this) { Guard.ThrowIf(nameof(@this), @this).Null(); // ... // // Throws an exception if the operation fails. var getThreatListDescriptorsTask = @this.GetThreatListDescriptorsAsync(CancellationToken.None); return(getThreatListDescriptorsTask); }