private async Task <ServiceWorkerDetectionResult> RunCore(Uri uri) { var(pageHtml, canonicalUri) = await GetPageHtml(uri); var htmlDoc = GetDocument(pageHtml); // Find the service worker inside the HTML of the page. var swUrl = await GetServiceWorkerUrlFromDoc(canonicalUri, htmlDoc) ?? await GetServiceWorkerUrlFromScripts(canonicalUri, htmlDoc); // Can't find sw reg in the HTML doc? Search its scripts. // If we found a service worker registration, but couldn't find the real name of the service worker, // see if we can tease it out from common names. // NOTE: we can do this ONLY if we find a registration. Otherwise, we get false positives, e.g. https://msn.com/service-worker.js - even though MSN has no service worker registration. if (swUrl == serviceWorkerNameFallback) { await GetServiceWorkerUrlFromCommonFileNames(canonicalUri); // Still can't find sw reg? Take a guess at some common SW URLs. } var swUri = GetAbsoluteUri(canonicalUri, swUrl); var swScript = await TryGetScriptContents(swUri, CancellationToken.None) ?? string.Empty; return(new ServiceWorkerDetectionResult { HasPushRegistration = swAnalyzer.CheckPushNotification(swScript), HasBackgroundSync = swAnalyzer.CheckBackgroundSync(swScript), HasPeriodicBackgroundSync = swAnalyzer.CheckPeriodicSync(swScript), NoServiceWorkerFoundDetails = swUrl == null ? "Couldn't find a service worker registration via HTML parsing" : string.Empty, Scope = swUrl != null ? canonicalUri : null, ServiceWorkerDetectionTimedOut = false, Url = swUri }); }
/// <summary> /// Runs all service works checks. /// </summary> /// <param name="uri"></param> /// <returns></returns> public async Task <ServiceWorkerDetectionResult> Run(Uri uri, bool cacheSuccessfulResults = true) { try { // First, see if we can find a service worker. using var serviceWorkerDetection = await DetectServiceWorker(uri); if (!serviceWorkerDetection.ServiceWorkerDetected) { // No service worker? Punt. return(new ServiceWorkerDetectionResult { ServiceWorkerDetectionTimedOut = serviceWorkerDetection.TimedOut, NoServiceWorkerFoundDetails = serviceWorkerDetection.NoServiceWorkerFoundDetails }); } var swScope = await TryGetScope(serviceWorkerDetection.Page, uri); var swContents = await TryGetScriptContents(serviceWorkerDetection.Worker.Uri, CancellationToken.None); this.logger.LogInformation("Successfully detected service worker for {uri}", uri); return(new ServiceWorkerDetectionResult { Url = serviceWorkerDetection.Worker.Uri, Scope = swScope, HasPushRegistration = await TryCheckPushRegistration(serviceWorkerDetection.Page, uri) || swCodeAnalyzer.CheckPushNotification(swContents), HasBackgroundSync = swCodeAnalyzer.CheckBackgroundSync(swContents), HasPeriodicBackgroundSync = swCodeAnalyzer.CheckPeriodicSync(swContents) }); } catch (Exception error) { logger.LogError(error, "Error running all checks for {url}", uri); var isTimeout = error is TimeoutException || error is Polly.Timeout.TimeoutRejectedException || error.Message.Contains("timeout", StringComparison.OrdinalIgnoreCase); return(new ServiceWorkerDetectionResult { NoServiceWorkerFoundDetails = "Error during Puppeteer service worker detection. " + error.Message, ServiceWorkerDetectionTimedOut = isTimeout }); } }