InAppPurchase thread safety

Hi,

It seems some InAppPurchase listener callback happen on threads that are not the juce message thread. For example, I was trying to call ‘restoreProductsBoughtList’ on a device with no internet access. At that point, ‘purchasesListRestored’ is called for my InAppPurchases::Listener with the ‘Product query failed’ error, but not from the message thread ( JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED asserts).

It can be silenced by replacing:

                       case PendingProductInfoRequest::Type::query:
                            t.owner.listeners.call ([&] (Listener& l)
                            {
                                l.purchasesListRestored ({}, false, NEEDS_TRANS ("Product query failed") + errorDetails);
                            });
                        break;

with

                       case PendingProductInfoRequest::Type::query:
                          MessageManager::callAsync ([&t, errorDetails]
                          {
                            t.owner.listeners.call ([errorDetails] (Listener& l)
                            {
                                l.purchasesListRestored ({}, false, NEEDS_TRANS ("Product query failed") + errorDetails);
                            });
                          });
                            break;

Maybe the other places where listeners are called should be reviewed in order to ensure that we stay on the message thread.

probably related: the red warning in SKProductsRequestDelegate | Apple Developer Documentation

Responses received by the SKProductsRequestDelegate may not be returned on a specific thread. If you make assumptions about which queue will handle delegate responses, you may encounter unintended performance and compatibility issues in the future.

(bump)