Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove LocalStorage synchronization on storage events in Safari #8408

Merged
merged 4 commits into from
Aug 6, 2024

Conversation

dlarocque
Copy link
Contributor

@dlarocque dlarocque commented Aug 6, 2024

This PR removes a localStorage synchronization fix introduced in 2016 to address an issue in Safari 9 (Important: b/28330893). The fix, while necessary at the time, is now causing several Auth tests to fail in Safari. After removing this fix, all tests pass.

The Safari tests are failing because they assume that a storage event without a change to the underlying storage will not trigger callbacks that we attach. With this fix, if we dispatch a storage event without a change to the underlying storage, a manual synchronization will take place, which will then cause the callbacks to be called.
See: local_storage.test.ts.

Testing:
I tested localStorage behaviour in the latest Safari version with an app hosted at 127.0.0.1 that contains an iframe hosted at localhost. I opened the app in two tabs and triggered localStorage events by signing in with Google in a popup, and observed that changes to localStorage are synchronized correctly across the iframes in both tabs.
I created a repro with instructions to help others test this behaviour: https://github.com/dlarocque/safari-iframe-localstorage.

@dlarocque dlarocque requested review from sam-gc and hsubox76 August 6, 2024 15:44
@dlarocque dlarocque requested review from lisajian, Xiaoshouzi-gh and a team as code owners August 6, 2024 15:44
Copy link

changeset-bot bot commented Aug 6, 2024

🦋 Changeset detected

Latest commit: 7d069bc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@firebase/auth Patch
@firebase/auth-compat Patch
firebase Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Aug 6, 2024

Size Report 1

Affected Products

  • @firebase/auth

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    browser182 kB182 kB-529 B (-0.3%)
    cordova210 kB209 kB-530 B (-0.3%)
    esm5236 kB236 kB-530 B (-0.2%)
    main179 kB179 kB-152 B (-0.1%)
    module182 kB182 kB-529 B (-0.3%)
    react-native199 kB199 kB-120 B (-0.1%)
  • @firebase/auth-cordova

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    browser210 kB209 kB-530 B (-0.3%)
    module210 kB209 kB-530 B (-0.3%)
  • @firebase/auth-web-extension

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    main152 kB152 kB-123 B (-0.1%)
  • @firebase/auth/internal

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    browser193 kB193 kB-529 B (-0.3%)
    esm5250 kB249 kB-530 B (-0.2%)
    main215 kB214 kB-616 B (-0.3%)
    module193 kB193 kB-529 B (-0.3%)
  • bundle

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    auth (GoogleFBTwitterGitHubPopup)103 kB103 kB-400 B (-0.4%)
    auth (GooglePopup)100 kB100 kB-400 B (-0.4%)
    auth (GoogleRedirect)101 kB100 kB-400 B (-0.4%)
  • firebase

    TypeBase (b4c5ef3)Merge (fcd0448)Diff
    firebase-auth-compat.js140 kB139 kB-358 B (-0.3%)
    firebase-auth-cordova.js177 kB177 kB-432 B (-0.2%)
    firebase-auth.js151 kB151 kB-426 B (-0.3%)
    firebase-compat.js787 kB787 kB-358 B (-0.0%)

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/mhuemER5XC.html
@dlarocque dlarocque requested a review from NhienLam August 6, 2024 16:02
@google-oss-bot
Copy link
Contributor

google-oss-bot commented Aug 6, 2024

Size Analysis Report 1

Affected Products

  • @firebase/auth

    • browserLocalPersistence

      Size

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      size42.6 kB42.2 kB-400 B (-0.9%)
      size-with-ext-deps64.2 kB63.8 kB-400 B (-0.6%)

      Dependency

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      functions

      58 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getUserLanguage
      _iframeCannotSyncWebStorage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIframe
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _persistenceKeyName
      _prodErrorMap
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _tokenExpiresIn
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      extractProviderData
      getAccountInfo
      getIdTokenResult
      getVersionForPlatform
      isUserInvalidated
      mergeProviderData
      registerAuth
      reload
      requestStsToken
      revokeToken
      secondsStringToMilliseconds
      utcTimestampToDateString

      56 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getUserLanguage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _persistenceKeyName
      _prodErrorMap
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _tokenExpiresIn
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      extractProviderData
      getAccountInfo
      getIdTokenResult
      getVersionForPlatform
      isUserInvalidated
      mergeProviderData
      registerAuth
      reload
      requestStsToken
      revokeToken
      secondsStringToMilliseconds
      utcTimestampToDateString

      - _iframeCannotSyncWebStorage
      - _isIframe

    • browserPopupRedirectResolver

      Size

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      size64.1 kB63.7 kB-400 B (-0.6%)
      size-with-ext-deps85.9 kB85.5 kB-400 B (-0.5%)

      Dependency

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      functions

      99 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _gapiScriptUrl
      _generateCallbackName
      _generateEventId
      _getAndClearPendingRedirectStatus
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getCurrentUrl
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getProjectConfig
      _getRedirectResult
      _getRedirectUrl
      _getUserLanguage
      _iframeCannotSyncWebStorage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIOSStandalone
      _isIframe
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _link
      _link$1
      _loadGapi
      _loadJS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _open
      _openIframe
      _overrideRedirectResult
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _performSignInRequest
      _persistenceKeyName
      _processCredentialSavingMfaContextIfNecessary
      _prodErrorMap
      _reauth
      _reauthenticate
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _setExternalJSProvider
      _setWindowLocation
      _signIn
      _signInWithCredential
      _tokenExpiresIn
      _validateOrigin
      _window
      _withDefaultResolver
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      eventUid
      extractProviderData
      getAccountInfo
      getHandlerBase
      getIdTokenResult
      getIframeUrl
      getScriptParentElement
      getVersionForPlatform
      isNullRedirectEvent
      isRedirectEvent
      isUserInvalidated
      loadGapi
      matchDomain
      mergeProviderData
      openAsNewWindowIOS
      pendingRedirectKey
      providerIdForResponse
      registerAuth
      reload
      requestStsToken
      resetUnloadedGapiModules
      resolverPersistence
      revokeToken
      secondsStringToMilliseconds
      signInWithIdp
      utcTimestampToDateString

      97 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _gapiScriptUrl
      _generateCallbackName
      _generateEventId
      _getAndClearPendingRedirectStatus
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getCurrentUrl
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getProjectConfig
      _getRedirectResult
      _getRedirectUrl
      _getUserLanguage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIOSStandalone
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _link
      _link$1
      _loadGapi
      _loadJS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _open
      _openIframe
      _overrideRedirectResult
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _performSignInRequest
      _persistenceKeyName
      _processCredentialSavingMfaContextIfNecessary
      _prodErrorMap
      _reauth
      _reauthenticate
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _setExternalJSProvider
      _setWindowLocation
      _signIn
      _signInWithCredential
      _tokenExpiresIn
      _validateOrigin
      _window
      _withDefaultResolver
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      eventUid
      extractProviderData
      getAccountInfo
      getHandlerBase
      getIdTokenResult
      getIframeUrl
      getScriptParentElement
      getVersionForPlatform
      isNullRedirectEvent
      isRedirectEvent
      isUserInvalidated
      loadGapi
      matchDomain
      mergeProviderData
      openAsNewWindowIOS
      pendingRedirectKey
      providerIdForResponse
      registerAuth
      reload
      requestStsToken
      resetUnloadedGapiModules
      resolverPersistence
      revokeToken
      secondsStringToMilliseconds
      signInWithIdp
      utcTimestampToDateString

      - _iframeCannotSyncWebStorage
      - _isIframe

    • browserSessionPersistence

      Size

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      size42.6 kB42.2 kB-400 B (-0.9%)
      size-with-ext-deps64.2 kB63.8 kB-400 B (-0.6%)

      Dependency

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      functions

      58 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getUserLanguage
      _iframeCannotSyncWebStorage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIframe
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _persistenceKeyName
      _prodErrorMap
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _tokenExpiresIn
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      extractProviderData
      getAccountInfo
      getIdTokenResult
      getVersionForPlatform
      isUserInvalidated
      mergeProviderData
      registerAuth
      reload
      requestStsToken
      revokeToken
      secondsStringToMilliseconds
      utcTimestampToDateString

      56 dependencies

      _addTidIfNecessary
      _assert
      _castAuth
      _createError
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getUserLanguage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _persistenceKeyName
      _prodErrorMap
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _tokenExpiresIn
      assertStringOrUndefined
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      extractProviderData
      getAccountInfo
      getIdTokenResult
      getVersionForPlatform
      isUserInvalidated
      mergeProviderData
      registerAuth
      reload
      requestStsToken
      revokeToken
      secondsStringToMilliseconds
      utcTimestampToDateString

      - _iframeCannotSyncWebStorage
      - _isIframe

    • getAuth

      Size

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      size74.3 kB73.9 kB-400 B (-0.5%)
      size-with-ext-deps103 kB102 kB-400 B (-0.4%)

      Dependency

      TypeBase (b4c5ef3)Merge (fcd0448)Diff
      functions

      119 dependencies

      _addTidIfNecessary
      _allSettled
      _assert
      _castAuth
      _createError
      _deleteDatabase
      _deleteObject
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _gapiScriptUrl
      _generateCallbackName
      _generateEventId
      _getActiveServiceWorker
      _getAndClearPendingRedirectStatus
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getCurrentUrl
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getProjectConfig
      _getRedirectResult
      _getRedirectUrl
      _getServiceWorkerController
      _getUserLanguage
      _getWorkerGlobalScope
      _iframeCannotSyncWebStorage
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIOSStandalone
      _isIframe
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _isWorker
      _link
      _link$1
      _loadGapi
      _loadJS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _open
      _openDatabase
      _openIframe
      _overrideRedirectResult
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _performSignInRequest
      _persistenceKeyName
      _processCredentialSavingMfaContextIfNecessary
      _prodErrorMap
      _putObject
      _reauth
      _reauthenticate
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _setExternalJSProvider
      _setWindowLocation
      _signIn
      _signInWithCredential
      _tokenExpiresIn
      _validateOrigin
      _window
      _withDefaultResolver
      assertStringOrUndefined
      beforeAuthStateChanged
      connectAuthEmulator
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      emitEmulatorWarning
      eventUid
      extractHostAndPort
      extractProtocol
      extractProviderData
      getAccountInfo
      getAuth
      getHandlerBase
      getIdTokenResult
      getIframeUrl
      getObject
      getObjectStore
      getScriptParentElement
      getVersionForPlatform
      initializeAuth
      isNullRedirectEvent
      isRedirectEvent
      isUserInvalidated
      loadGapi
      matchDomain
      mergeProviderData
      onIdTokenChanged
      openAsNewWindowIOS
      parsePort
      pendingRedirectKey
      providerIdForResponse
      registerAuth
      reload
      requestStsToken
      resetUnloadedGapiModules
      resolverPersistence
      revokeToken
      secondsStringToMilliseconds
      signInWithIdp
      utcTimestampToDateString

      117 dependencies

      _addTidIfNecessary
      _allSettled
      _assert
      _castAuth
      _createError
      _deleteDatabase
      _deleteObject
      _emulatorUrl
      _errorWithCustomMessage
      _fail
      _gapiScriptUrl
      _generateCallbackName
      _generateEventId
      _getActiveServiceWorker
      _getAndClearPendingRedirectStatus
      _getBrowserName
      _getClientVersion
      _getCurrentScheme
      _getCurrentUrl
      _getFinalTarget
      _getInstance
      _getPasswordPolicy
      _getProjectConfig
      _getRedirectResult
      _getRedirectUrl
      _getServiceWorkerController
      _getUserLanguage
      _getWorkerGlobalScope
      _initializeAuthInstance
      _isAndroid
      _isBlackBerry
      _isChromeIOS
      _isFirefox
      _isHttpOrHttps
      _isIE10
      _isIEMobile
      _isIOS
      _isIOSStandalone
      _isMobileBrowser
      _isOnline
      _isSafari
      _isWebOS
      _isWorker
      _link
      _link$1
      _loadGapi
      _loadJS
      _logError
      _logWarn
      _logoutIfInvalidated
      _makeTaggedError
      _open
      _openDatabase
      _openIframe
      _overrideRedirectResult
      _parseToken
      _performApiRequest
      _performFetchWithErrorHandling
      _performSignInRequest
      _persistenceKeyName
      _processCredentialSavingMfaContextIfNecessary
      _prodErrorMap
      _putObject
      _reauth
      _reauthenticate
      _reloadWithoutSaving
      _serverAppCurrentUserOperationNotSupportedError
      _setExternalJSProvider
      _setWindowLocation
      _signIn
      _signInWithCredential
      _tokenExpiresIn
      _validateOrigin
      _window
      _withDefaultResolver
      assertStringOrUndefined
      beforeAuthStateChanged
      connectAuthEmulator
      createErrorInternal
      debugAssert
      debugFail
      deleteAccount
      emitEmulatorWarning
      eventUid
      extractHostAndPort
      extractProtocol
      extractProviderData
      getAccountInfo
      getAuth
      getHandlerBase
      getIdTokenResult
      getIframeUrl
      getObject
      getObjectStore
      getScriptParentElement
      getVersionForPlatform
      initializeAuth
      isNullRedirectEvent
      isRedirectEvent
      isUserInvalidated
      loadGapi
      matchDomain
      mergeProviderData
      onIdTokenChanged
      openAsNewWindowIOS
      parsePort
      pendingRedirectKey
      providerIdForResponse
      registerAuth
      reload
      requestStsToken
      resetUnloadedGapiModules
      resolverPersistence
      revokeToken
      secondsStringToMilliseconds
      signInWithIdp
      utcTimestampToDateString

      - _iframeCannotSyncWebStorage
      - _isIframe

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/W2eGzBWATS.html
@dlarocque dlarocque requested review from a team as code owners August 6, 2024 18:51
'@firebase/auth': patch
---

Remove localStorage synchronization on storage events in Safari iframes. See [GitHub PR #8408](https://github.com/firebase/firebase-js-sdk/pull/8408).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the changeset tool automatically links to the PR that the changeset was added in when creating the Version Packages PR, but this does make the copy-paste into release notes easier.

@dlarocque dlarocque merged commit 2ddbd4e into main Aug 6, 2024
43 checks passed
@dlarocque dlarocque deleted the dlarocque/auth-safari-localstorage branch August 6, 2024 20:16
This was referenced Aug 13, 2024
@firebase firebase locked and limited conversation to collaborators Sep 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
5 participants