summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/storage/default_file_source.hpp6
-rw-r--r--include/mbgl/storage/online_file_source.hpp8
-rw-r--r--platform/default/default_file_source.cpp16
-rw-r--r--platform/default/online_file_source.cpp42
-rw-r--r--test/storage/default_file_source.test.cpp25
5 files changed, 67 insertions, 30 deletions
diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp
index 556a8df586..9911e0ce67 100644
--- a/include/mbgl/storage/default_file_source.hpp
+++ b/include/mbgl/storage/default_file_source.hpp
@@ -1,8 +1,10 @@
#pragma once
+#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/offline.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/optional.hpp>
#include <vector>
#include <mutex>
@@ -13,6 +15,8 @@ namespace util {
template <typename T> class Thread;
} // namespace util
+class ResourceTransform;
+
class DefaultFileSource : public FileSource {
public:
/*
@@ -40,7 +44,7 @@ public:
void setAccessToken(const std::string&);
std::string getAccessToken();
- void setResourceTransform(std::function<std::string(Resource::Kind, std::string&&)>);
+ void setResourceTransform(optional<ActorRef<ResourceTransform>>&&);
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
diff --git a/include/mbgl/storage/online_file_source.hpp b/include/mbgl/storage/online_file_source.hpp
index 51cfc5a2a1..ffd75662e6 100644
--- a/include/mbgl/storage/online_file_source.hpp
+++ b/include/mbgl/storage/online_file_source.hpp
@@ -1,10 +1,14 @@
#pragma once
+#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/optional.hpp>
namespace mbgl {
+class ResourceTransform;
+
class OnlineFileSource : public FileSource {
public:
OnlineFileSource();
@@ -16,9 +20,7 @@ public:
void setAccessToken(const std::string& t) { accessToken = t; }
std::string getAccessToken() const { return accessToken; }
- using ResourceTransform =
- std::function<std::unique_ptr<AsyncRequest>(Resource::Kind, std::string&&, std::function<void(std::string&&)>)>;
- void setResourceTransform(ResourceTransform&& cb);
+ void setResourceTransform(optional<ActorRef<ResourceTransform>>&&);
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index dc3e71b0c0..bf8d7b6348 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -5,6 +5,7 @@
#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/offline_download.hpp>
+#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/platform.hpp>
#include <mbgl/util/url.hpp>
@@ -49,7 +50,7 @@ public:
return onlineFileSource.getAccessToken();
}
- void setResourceTransform(OnlineFileSource::ResourceTransform&& transform) {
+ void setResourceTransform(optional<ActorRef<ResourceTransform>>&& transform) {
onlineFileSource.setResourceTransform(std::move(transform));
}
@@ -227,17 +228,8 @@ std::string DefaultFileSource::getAccessToken() {
return cachedAccessToken;
}
-void DefaultFileSource::setResourceTransform(std::function<std::string(Resource::Kind, std::string&&)> transform) {
- if (transform) {
- auto loop = util::RunLoop::Get();
- impl->actor().invoke(&Impl::setResourceTransform, [loop, transform](Resource::Kind kind_, std::string&& url_, auto callback_) {
- return loop->invokeWithCallback([transform](Resource::Kind kind, std::string&& url, auto callback) {
- callback(transform(kind, std::move(url)));
- }, kind_, std::move(url_), callback_);
- });
- } else {
- impl->actor().invoke(&Impl::setResourceTransform, nullptr);
- }
+void DefaultFileSource::setResourceTransform(optional<ActorRef<ResourceTransform>>&& transform) {
+ impl->actor().invoke(&Impl::setResourceTransform, std::move(transform));
}
std::unique_ptr<AsyncRequest> DefaultFileSource::request(const Resource& resource, Callback callback) {
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index 4f5483d794..f10e0f8ffb 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -2,15 +2,18 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
+#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/logging.hpp>
+#include <mbgl/actor/mailbox.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/timer.hpp>
#include <mbgl/util/http_timeout.hpp>
@@ -34,12 +37,17 @@ public:
void schedule(optional<Timestamp> expires);
void completed(Response);
+ void setTransformedURL(const std::string&& url);
+ ActorRef<OnlineFileRequest> actor();
+
OnlineFileSource::Impl& impl;
Resource resource;
std::unique_ptr<AsyncRequest> request;
util::Timer timer;
Callback callback;
+ std::shared_ptr<Mailbox> mailbox;
+
// Counts the number of times a response was already expired when received. We're using
// this to add a delay when making a new request so we don't keep retrying immediately
// in case of a server serving expired tiles.
@@ -65,15 +73,12 @@ public:
void add(OnlineFileRequest* request) {
allRequests.insert(request);
if (resourceTransform) {
- // When there's a Resource transform callback set, replace the resource with the
+ // Request the ResourceTransform actor a new url and replace the resource url with the
// transformed one before proceeding to schedule the request.
- request->request =
- resourceTransform(request->resource.kind, std::move(request->resource.url),
- [request](std::string&& url) {
- request->request.release();
- request->resource.url = std::move(url);
- request->schedule();
- });
+ resourceTransform->invoke(&ResourceTransform::transform, request->resource.kind,
+ std::move(request->resource.url), [ref = request->actor()](const std::string&& url) mutable {
+ ref.invoke(&OnlineFileRequest::setTransformedURL, std::move(url));
+ });
} else {
request->schedule();
}
@@ -144,7 +149,7 @@ public:
return activeRequests.find(request) != activeRequests.end();
}
- void setResourceTransform(ResourceTransform&& transform) {
+ void setResourceTransform(optional<ActorRef<ResourceTransform>>&& transform) {
resourceTransform = std::move(transform);
}
@@ -155,7 +160,7 @@ private:
}
}
- ResourceTransform resourceTransform;
+ optional<ActorRef<ResourceTransform>> resourceTransform;
/**
* The lifetime of a request is:
@@ -216,7 +221,7 @@ std::unique_ptr<AsyncRequest> OnlineFileSource::request(const Resource& resource
return std::make_unique<OnlineFileRequest>(std::move(res), std::move(callback), *impl);
}
-void OnlineFileSource::setResourceTransform(ResourceTransform&& transform) {
+void OnlineFileSource::setResourceTransform(optional<ActorRef<ResourceTransform>>&& transform) {
impl->setResourceTransform(std::move(transform));
}
@@ -361,4 +366,19 @@ void OnlineFileRequest::networkIsReachableAgain() {
}
}
+void OnlineFileRequest::setTransformedURL(const std::string&& url) {
+ resource.url = std::move(url);
+ schedule();
+}
+
+ActorRef<OnlineFileRequest> OnlineFileRequest::actor() {
+ if (!mailbox) {
+ // Lazy constructed because this can be costly and
+ // the ResourceTransform is not used by many apps.
+ mailbox = std::make_shared<Mailbox>(*util::RunLoop::Get());
+ }
+
+ return ActorRef<OnlineFileRequest>(*this, mailbox);
+}
+
} // namespace mbgl
diff --git a/test/storage/default_file_source.test.cpp b/test/storage/default_file_source.test.cpp
index 03f1076559..41e305a692 100644
--- a/test/storage/default_file_source.test.cpp
+++ b/test/storage/default_file_source.test.cpp
@@ -1,5 +1,7 @@
+#include <mbgl/actor/actor.hpp>
#include <mbgl/test/util.hpp>
#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/run_loop.hpp>
using namespace mbgl;
@@ -482,7 +484,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) {
DefaultFileSource fs(":memory:", ".");
// Translates the URL "localhost://test to http://127.0.0.1:3000/test
- fs.setResourceTransform([](Resource::Kind, std::string&& url) -> std::string {
+ Actor<ResourceTransform> transform(loop, [](Resource::Kind, const std::string&& url) -> std::string {
if (url == "localhost://test") {
return "http://127.0.0.1:3000/test";
} else {
@@ -490,10 +492,27 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) {
}
});
- const Resource resource { Resource::Unknown, "localhost://test" };
+ fs.setResourceTransform(transform.self());
+ const Resource resource1 { Resource::Unknown, "localhost://test" };
std::unique_ptr<AsyncRequest> req;
- req = fs.request(resource, [&](Response res) {
+ req = fs.request(resource1, [&](Response res) {
+ req.reset();
+ EXPECT_EQ(nullptr, res.error);
+ ASSERT_TRUE(res.data.get());
+ EXPECT_EQ("Hello World!", *res.data);
+ EXPECT_FALSE(bool(res.expires));
+ EXPECT_FALSE(bool(res.modified));
+ EXPECT_FALSE(bool(res.etag));
+ loop.stop();
+ });
+
+ loop.run();
+
+ fs.setResourceTransform({});
+ const Resource resource2 { Resource::Unknown, "http://127.0.0.1:3000/test" };
+
+ req = fs.request(resource2, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
ASSERT_TRUE(res.data.get());