@@ -19,9 +19,24 @@ interface NavigationState {
1919 /**
2020 * If the user is requesting content addressed data (instead of service worker gateway UI), this will be true.
2121 *
22- * e.g. sw-gateway landing page, ipfs-sw-config view, ipfs-sw-origin-isolation-warning view, etc.
22+ * e.g. NOT the sw-gateway landing page, ipfs-sw-config view, ipfs-sw-origin-isolation-warning view, etc.
2323 */
2424 requestForContentAddressedData : boolean
25+
26+ /**
27+ * If the user is requesting content addressed data, the current URL is an isolated subdomain, and we already have the config,
28+ * this will be true iff navigator.serviceWorker.controller is null.
29+ *
30+ * In this case, we need to reload the page to ensure the service worker captures the request.
31+ *
32+ * @see https://www.w3.org/TR/service-workers/#dom-serviceworkercontainer-controller
33+ */
34+ isHardRefresh : boolean
35+
36+ /**
37+ * If the user is requesting the config, this will be true.
38+ */
39+ isConfigRequest : boolean
2540}
2641
2742const log = uiLogger . forComponent ( 'first-hit-helpers' )
@@ -135,11 +150,6 @@ function isRequestForContentAddressedData (url: URL): boolean {
135150 // query param request
136151 return true
137152 }
138- if ( url . hash . includes ( '/ipfs-sw-config' ) ) {
139- // hash request for UI page, with no path/subdomain/query indicating request for content addressed data
140- // we need to do this after the path/subdomain/query check because we need to ensure the config is properly loaded from the root domain
141- return false
142- }
143153 return false
144154}
145155
@@ -154,10 +164,28 @@ export async function getStateFromUrl (url: URL): Promise<NavigationState> {
154164 const urlHasSubdomainConfigRequest = hasHashFragment ( url , HASH_FRAGMENTS . IPFS_SW_SUBDOMAIN_REQUEST ) && url . searchParams . get ( QUERY_PARAMS . HELIA_SW ) != null
155165 let hasConfig = false
156166 const supportsSubdomains = await checkSubdomainSupport ( url )
167+ let isHardRefresh = false
168+ let isConfigRequest = false
157169
158170 if ( isIsolatedOrigin ) {
159171 // check if indexedDb has config
160172 hasConfig = await isConfigSet ( uiLogger )
173+ if ( hasConfig ) {
174+ // Check service worker state
175+ const registration = await navigator . serviceWorker . getRegistration ( )
176+ const hasActiveWorker = registration ?. active != null
177+ const hasControllingWorker = navigator . serviceWorker . controller != null
178+
179+ if ( hasActiveWorker && ! hasControllingWorker ) {
180+ // this is a hard refresh
181+ isHardRefresh = true
182+ }
183+ }
184+ }
185+
186+ // check if url.hash matches exactly
187+ if ( url . hash === `#/${ HASH_FRAGMENTS . IPFS_SW_CONFIG_UI } ` ) {
188+ isConfigRequest = true
161189 }
162190
163191 return {
@@ -168,7 +196,9 @@ export async function getStateFromUrl (url: URL): Promise<NavigationState> {
168196 subdomainParts : { parentDomain, id, protocol } ,
169197 compressedConfig : getHashFragment ( url , HASH_FRAGMENTS . IPFS_SW_CFG ) ,
170198 supportsSubdomains,
171- requestForContentAddressedData : isRequestForContentAddressedData ( url )
199+ requestForContentAddressedData : isRequestForContentAddressedData ( url ) ,
200+ isHardRefresh,
201+ isConfigRequest
172202 } satisfies NavigationState
173203}
174204
0 commit comments