diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp index a15ee9a29b2..7e9bcdfacb7 100644 --- a/include/mbgl/storage/default_file_source.hpp +++ b/include/mbgl/storage/default_file_source.hpp @@ -12,6 +12,11 @@ namespace util { template class Thread; } // namespace util +enum class DefaultFileSourceRevalidationState { + Active, + Inactive +}; + class DefaultFileSource : public FileSource { public: /* @@ -38,6 +43,16 @@ class DefaultFileSource : public FileSource { void setResourceTransform(std::function); + /* + * Pause or resume revalidation requests. + * + * If the revalidation state is set to inactive, then attempts to + * call request will call the callback immediately with a request + * with an error indicating that the file source is inactive. + */ + void setRevalidationState(DefaultFileSourceRevalidationState state); + DefaultFileSourceRevalidationState getRevalidationState() const; + std::unique_ptr request(const Resource&, Callback) override; /* diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index 3742414f3d3..b9b24c50596 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -50,6 +50,14 @@ class DefaultFileSource::Impl { onlineFileSource.setResourceTransform(std::move(transform)); } + void setRevalidationState(DefaultFileSourceRevalidationState state) { + revalidationState = state; + } + + DefaultFileSourceRevalidationState getRevalidationState() const { + return revalidationState; + } + void listRegions(std::function>)> callback) { try { callback({}, offlineDatabase.listRegions()); @@ -105,6 +113,15 @@ class DefaultFileSource::Impl { } void request(AsyncRequest* req, Resource resource, Callback callback) { + + if (revalidationState == DefaultFileSourceRevalidationState::Inactive) { + Response inactiveResponse; + inactiveResponse.error = std::make_unique( + Response::Error::Reason::Other, "File source is inactive"); + callback(inactiveResponse); + return; + } + Resource revalidation = resource; const bool hasPrior = resource.priorEtag || resource.priorModified || resource.priorExpires; @@ -162,6 +179,7 @@ class DefaultFileSource::Impl { OnlineFileSource onlineFileSource; std::unordered_map> tasks; std::unordered_map> downloads; + DefaultFileSourceRevalidationState revalidationState; }; DefaultFileSource::DefaultFileSource(const std::string& cachePath, @@ -200,6 +218,14 @@ void DefaultFileSource::setResourceTransform(std::functioninvokeSync(&Impl::setRevalidationState, state); +} + +DefaultFileSourceRevalidationState DefaultFileSource::getRevalidationState() const { + return thread->invokeSync(&Impl::getRevalidationState); +} + std::unique_ptr DefaultFileSource::request(const Resource& resource, Callback callback) { class DefaultFileRequest : public AsyncRequest { public: diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 7ff327c237c..3238539114a 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1070,6 +1070,8 @@ - (void)sleepGL:(__unused NSNotification *)notification { self.dormant = YES; + [MGLOfflineStorage sharedOfflineStorage].mbglFileSource->setRevalidationState(mbgl::DefaultFileSourceRevalidationState::Inactive); + [self validateLocationServices]; [MGLMapboxEvents flush]; @@ -1107,6 +1109,8 @@ - (void)wakeGL:(__unused NSNotification *)notification { self.dormant = NO; + [MGLOfflineStorage sharedOfflineStorage].mbglFileSource->setRevalidationState(mbgl::DefaultFileSourceRevalidationState::Active); + [self createGLView]; self.glSnapshotView.hidden = YES; diff --git a/test/storage/default_file_source.test.cpp b/test/storage/default_file_source.test.cpp index ffbeea10961..aa4aceb03a4 100644 --- a/test/storage/default_file_source.test.cpp +++ b/test/storage/default_file_source.test.cpp @@ -490,3 +490,32 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) { loop.run(); } + +// Test that if we make a request when the file source is inactive, no +// invalidation occurs and not request is actually made +TEST(DefaultFileSource, NoInvalidationIfInactive) { + util::RunLoop loop; + DefaultFileSource fs(":memory:", "."); + + fs.setRevalidationState(DefaultFileSourceRevalidationState::Inactive); + EXPECT_EQ(fs.getRevalidationState(), DefaultFileSourceRevalidationState::Inactive); + + const Resource optionalResource { Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::Optional }; + + using namespace std::chrono_literals; + + std::unique_ptr req; + req = fs.request(optionalResource, [&](Response res) { + req.reset(); + ASSERT_TRUE(res.error.get()); + EXPECT_EQ(Response::Error::Reason::Other, res.error->reason); + EXPECT_EQ("File source is inactive", res.error->message); + EXPECT_FALSE(res.data); + EXPECT_FALSE(bool(res.expires)); + EXPECT_FALSE(bool(res.modified)); + EXPECT_FALSE(bool(res.etag)); + loop.stop(); + }); + + loop.run(); +}