summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-01-11 12:52:41 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-01-13 13:40:31 -0800
commit86c8446d3a4390ff6577d070ac8b5fa3ad3c5cd1 (patch)
treeef10190d3fca34ff72b2473816901088b0b85ac2 /platform
parent2126e34e52dc5dd94c5a3907b240e62ee17d1e70 (diff)
downloadqtlocation-mapboxgl-86c8446d3a4390ff6577d070ac8b5fa3ad3c5cd1.tar.gz
[core] Simplify asset:// implementation
* Move asset:// URL handling to DefaultFileSource. * AssetFileSource implements FileSource interface and follows familiar implementation patterns. * Move default implementation to platform/default, zip implementation to platform/android. * Don't bother with modified / expires / etag -- assets are not cached so it doesn't matter. * Don't bother with interleaving individual IO calls on the implementation thread. That adds a lot of complexity for very little benefit.
Diffstat (limited to 'platform')
-rw-r--r--platform/android/src/asset_file_source.cpp111
-rw-r--r--platform/default/asset_file_source.cpp79
-rw-r--r--platform/default/asset_request_fs.cpp234
-rw-r--r--platform/default/asset_request_zip.cpp319
-rw-r--r--platform/default/default_file_source.cpp28
-rw-r--r--platform/default/online_file_source.cpp26
6 files changed, 221 insertions, 576 deletions
diff --git a/platform/android/src/asset_file_source.cpp b/platform/android/src/asset_file_source.cpp
new file mode 100644
index 0000000000..1f02f9cf4a
--- /dev/null
+++ b/platform/android/src/asset_file_source.cpp
@@ -0,0 +1,111 @@
+#include <mbgl/storage/asset_file_source.hpp>
+#include <mbgl/storage/response.hpp>
+#include <mbgl/util/util.hpp>
+#include <mbgl/util/thread.hpp>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <zip.h>
+#pragma GCC diagnostic pop
+
+namespace {
+
+struct ZipHolder {
+ ZipHolder(struct zip* archive_) : archive(archive_) {}
+
+ ~ZipHolder() {
+ if (archive) ::zip_close(archive);
+ }
+
+ struct zip* archive;
+};
+
+struct ZipFileHolder {
+ ZipFileHolder(struct zip_file* file_) : file(file_) {}
+
+ ~ZipFileHolder() {
+ if (file) ::zip_fclose(file);
+ }
+
+ struct zip_file* file;
+};
+
+}
+
+namespace mbgl {
+
+class AssetFileRequest : public FileRequest {
+public:
+ AssetFileRequest(std::unique_ptr<WorkRequest> workRequest_)
+ : workRequest(std::move(workRequest_)) {
+ }
+
+ std::unique_ptr<WorkRequest> workRequest;
+};
+
+class AssetFileSource::Impl {
+public:
+ Impl(const std::string& root_)
+ : root(root_) {
+ }
+
+ void request(const std::string& url, FileSource::Callback callback) {
+ ZipHolder archive = ::zip_open(root.c_str(), 0, nullptr);
+ if (!archive.archive) {
+ reportError(Response::Error::Reason::Other, "Could not open zip archive", callback);
+ return;
+ }
+
+ struct zip_stat stat;
+ ::zip_stat_init(&stat);
+
+ std::string path = std::string("assets/") + url.substr(8);
+ int ret = ::zip_stat(archive.archive, path.c_str(), 0, &stat);
+ if (ret < 0 || !(stat.valid & ZIP_STAT_SIZE)) {
+ reportError(Response::Error::Reason::NotFound, "Could not stat file in zip archive", callback);
+ return;
+ }
+
+ ZipFileHolder file = ::zip_fopen(archive.archive, path.c_str(), 0);
+ if (!file.file) {
+ reportError(Response::Error::Reason::NotFound, "Could not open file in zip archive", callback);
+ return;
+ }
+
+ std::shared_ptr<std::string> buf = std::make_shared<std::string>();
+ buf->resize(stat.size);
+
+ ret = ::zip_fread(file.file, &buf->front(), stat.size);
+ if (ret < 0) {
+ reportError(Response::Error::Reason::Other, "Could not read file in zip archive", callback);
+ return;
+ }
+
+ Response response;
+ response.data = buf;
+ callback(response);
+ }
+
+ void reportError(Response::Error::Reason reason, const char * message, FileSource::Callback callback) {
+ Response response;
+ response.error = std::make_unique<Response::Error>(reason, message);
+ callback(response);
+ }
+
+private:
+ std::string root;
+};
+
+AssetFileSource::AssetFileSource(const std::string& root)
+ : thread(std::make_unique<util::Thread<Impl>>(
+ util::ThreadContext{"AssetFileSource", util::ThreadType::Worker, util::ThreadPriority::Regular},
+ root.empty() ? platform::assetRoot() : root)) {
+}
+
+AssetFileSource::~AssetFileSource() = default;
+
+std::unique_ptr<FileRequest> AssetFileSource::request(const Resource& resource, Callback callback) {
+ return std::make_unique<AssetFileRequest>(thread->invokeWithCallback(&Impl::request, callback, resource.url));
+}
+
+}
diff --git a/platform/default/asset_file_source.cpp b/platform/default/asset_file_source.cpp
new file mode 100644
index 0000000000..5aa5730c94
--- /dev/null
+++ b/platform/default/asset_file_source.cpp
@@ -0,0 +1,79 @@
+#include <mbgl/storage/asset_file_source.hpp>
+#include <mbgl/storage/response.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/util/thread.hpp>
+#include <mbgl/util/url.hpp>
+#include <mbgl/util/util.hpp>
+#include <mbgl/util/io.hpp>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace mbgl {
+
+class AssetFileRequest : public FileRequest {
+public:
+ AssetFileRequest(std::unique_ptr<WorkRequest> workRequest_)
+ : workRequest(std::move(workRequest_)) {
+ }
+
+ std::unique_ptr<WorkRequest> workRequest;
+};
+
+class AssetFileSource::Impl {
+public:
+ Impl(const std::string& root_)
+ : root(root_) {
+ }
+
+ void request(const std::string& url, FileSource::Callback callback) {
+ std::string path;
+
+ if (url.size() <= 8 || url[8] == '/') {
+ // This is an empty or absolute path.
+ path = mbgl::util::percentDecode(url.substr(8));
+ } else {
+ // This is a relative path. Prefix with the application root.
+ path = root + "/" + mbgl::util::percentDecode(url.substr(8));
+ }
+
+ Response response;
+
+ struct stat buf;
+ int result = stat(path.c_str(), &buf);
+
+ if (result == 0 && S_ISDIR(buf.st_mode)) {
+ response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound);
+ } else if (result == -1 && errno == ENOENT) {
+ response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound);
+ } else {
+ try {
+ response.data = std::make_shared<std::string>(util::read_file(path));
+ } catch (...) {
+ response.error = std::make_unique<Response::Error>(
+ Response::Error::Reason::Other,
+ util::toString(std::current_exception()));
+ }
+ }
+
+ callback(response);
+ }
+
+private:
+ std::string root;
+};
+
+AssetFileSource::AssetFileSource(const std::string& root)
+ : thread(std::make_unique<util::Thread<Impl>>(
+ util::ThreadContext{"AssetFileSource", util::ThreadType::Worker, util::ThreadPriority::Regular},
+ root.empty() ? platform::assetRoot() : root)) {
+}
+
+AssetFileSource::~AssetFileSource() = default;
+
+std::unique_ptr<FileRequest> AssetFileSource::request(const Resource& resource, Callback callback) {
+ return std::make_unique<AssetFileRequest>(thread->invokeWithCallback(&Impl::request, callback, resource.url));
+}
+
+} // namespace mbgl
diff --git a/platform/default/asset_request_fs.cpp b/platform/default/asset_request_fs.cpp
deleted file mode 100644
index 2ef22f9586..0000000000
--- a/platform/default/asset_request_fs.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-#include <mbgl/storage/asset_context_base.hpp>
-#include <mbgl/storage/response.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/util/thread.hpp>
-#include <mbgl/util/url.hpp>
-#include <mbgl/util/util.hpp>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace {
-
-struct FDHolder {
- FDHolder(int fd_) : fd(fd_) {}
-
- ~FDHolder() {
- if (fd >= 0) ::close(fd);
- }
-
- int fd;
-};
-
-class FileIOWorker {
-public:
- FileIOWorker() = default;
-
- void open(const std::string& path, int flags, mode_t mode,
- std::function<void(std::unique_ptr<FDHolder>)> cb) {
- // FDHolder is needed because if the request gets canceled
- // we would otherwise end up with a fd leaking.
- int ret = ::open(path.c_str(), flags, mode);
- cb(std::make_unique<FDHolder>(ret < 0 ? -errno : ret));
- }
-
- void fstat(int fd, std::function<void (int, std::unique_ptr<struct stat>)> cb) {
- std::unique_ptr<struct stat> buf = std::make_unique<struct stat>();
- int ret = ::fstat(fd, buf.get());
- cb(ret < 0 ? -errno : ret, std::move(buf));
- }
-
- void read(int fd, size_t size,
- std::function<void (ssize_t, std::shared_ptr<std::string>)> cb) {
- std::shared_ptr<std::string> buf = std::make_shared<std::string>();
- buf->resize(size);
-
- ssize_t ret = ::read(fd, &buf->front(), size);
- cb(ret < 0 ? -errno : ret, std::move(buf));
- }
-
- void close(int fd, std::function<void (void)> cb) {
- ::close(fd);
- cb();
- }
-};
-
-} // namespace
-
-namespace mbgl {
-
-using namespace std::placeholders;
-
-class AssetRequest : public RequestBase {
- MBGL_STORE_THREAD(tid)
-
-public:
- AssetRequest(const std::string& url, Callback, const std::string& assetRoot,
- util::Thread<FileIOWorker> *worker);
- ~AssetRequest();
-
- // RequestBase implementation.
- void cancel() final;
-
-private:
- void fileOpened(std::unique_ptr<FDHolder>);
- void fileStated(int result, std::unique_ptr<struct stat>);
- void fileRead(int result, std::shared_ptr<std::string>);
- void fileClosed();
-
- void notifyError(int result);
-
- void close();
- void cleanup();
-
- std::string assetRoot;
- std::unique_ptr<Response> response;
-
- int fd = -1;
-
- util::Thread<FileIOWorker> *worker;
- std::unique_ptr<WorkRequest> request;
-};
-
-class AssetFSContext : public AssetContextBase {
-public:
- AssetFSContext()
- : worker({"FileIOWorker", util::ThreadType::Worker, util::ThreadPriority::Regular}) {}
-
-private:
- RequestBase* createRequest(const std::string& url,
- RequestBase::Callback callback,
- const std::string& assetRoot) final {
- return new AssetRequest(url, callback, assetRoot, &worker);
- }
-
- util::Thread<FileIOWorker> worker;
-};
-
-AssetRequest::~AssetRequest() {
- MBGL_VERIFY_THREAD(tid);
-}
-
-AssetRequest::AssetRequest(const std::string& url_, Callback callback_,
- const std::string& assetRoot_, util::Thread<FileIOWorker> *worker_)
- : RequestBase(url_, callback_),
- assetRoot(assetRoot_),
- worker(worker_) {
- std::string path;
- if (url.size() <= 8 || url[8] == '/') {
- // This is an empty or absolute path.
- path = mbgl::util::percentDecode(url.substr(8));
- } else {
- // This is a relative path. Prefix with the application root.
- path = assetRoot + "/" + mbgl::util::percentDecode(url.substr(8));
- }
-
- request = worker->invokeWithCallback(&FileIOWorker::open,
- std::bind(&AssetRequest::fileOpened, this, _1), path, O_RDONLY, S_IRUSR);
-}
-
-void AssetRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
- request.reset();
- close();
-}
-
-void AssetRequest::fileOpened(std::unique_ptr<FDHolder> holder) {
- MBGL_VERIFY_THREAD(tid);
-
- std::swap(fd, holder->fd);
-
- if (fd < 0) {
- // Opening failed. There isn't much left we can do.
- notifyError(fd);
- cleanup();
-
- return;
- }
-
- request = worker->invokeWithCallback(&FileIOWorker::fstat,
- std::bind(&AssetRequest::fileStated, this, _1, _2), fd);
-}
-
-void AssetRequest::fileStated(int result, std::unique_ptr<struct stat> stat) {
- MBGL_VERIFY_THREAD(tid);
-
- if (result != 0) {
- // Stating failed. We already have an open file handle
- // though, which we'll have to close.
- notifyError(result);
- close();
- } else {
- response = std::make_unique<Response>();
- response->modified = Seconds(stat->st_mtime);
- response->etag = util::toString(stat->st_ino);
-
- request = worker->invokeWithCallback(&FileIOWorker::read,
- std::bind(&AssetRequest::fileRead, this, _1, _2), fd, stat->st_size);
- }
-}
-
-void AssetRequest::fileRead(int result, std::shared_ptr<std::string> data) {
- MBGL_VERIFY_THREAD(tid);
-
- if (result < 0) {
- // Reading failed. We already have an open file handle
- // though, which we'll have to close.
- notifyError(result);
- } else {
- response->data = data;
- notify(std::move(response));
- }
-
- close();
-}
-
-void AssetRequest::fileClosed() {
- MBGL_VERIFY_THREAD(tid);
-
- cleanup();
-}
-
-void AssetRequest::close() {
- MBGL_VERIFY_THREAD(tid);
-
- if (fd >= 0) {
- request = worker->invokeWithCallback(&FileIOWorker::close,
- std::bind(&AssetRequest::fileClosed, this), fd);
- fd = -1;
- } else {
- cleanup();
- }
-}
-
-void AssetRequest::cleanup() {
- MBGL_VERIFY_THREAD(tid);
-
- delete this;
-}
-
-void AssetRequest::notifyError(int result) {
- MBGL_VERIFY_THREAD(tid);
-
- result = std::abs(result);
- Response::Error::Reason reason = Response::Error::Reason::Other;
-
- if (result == ENOENT || result == EISDIR) {
- reason = Response::Error::Reason::NotFound;
- }
-
- response = std::make_unique<Response>();
- response->error = std::make_unique<Response::Error>(reason, ::strerror(result));
-
- notify(std::move(response));
-}
-
-std::unique_ptr<AssetContextBase> AssetContextBase::createContext() {
- return std::make_unique<AssetFSContext>();
-}
-
-} // namespace mbgl
diff --git a/platform/default/asset_request_zip.cpp b/platform/default/asset_request_zip.cpp
deleted file mode 100644
index 76bf8bba14..0000000000
--- a/platform/default/asset_request_zip.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-#include <mbgl/storage/asset_context_base.hpp>
-#include <mbgl/storage/response.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/util.hpp>
-#include <mbgl/util/thread.hpp>
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wshadow"
-#include <zip.h>
-#pragma GCC diagnostic pop
-
-#include <cassert>
-#include <forward_list>
-#include <map>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-namespace {
-
-struct ZipHolder {
- ZipHolder(struct zip* archive_) : archive(archive_) {}
-
- ~ZipHolder() {
- if (archive) ::zip_discard(archive);
- }
-
- struct zip* archive;
-};
-
-struct ZipFileHolder {
- ZipFileHolder(struct zip_file* file_) : file(file_) {}
-
- ~ZipFileHolder() {
- if (file) ::zip_fclose(file);
- }
-
- struct zip_file* file;
-};
-
-class ZipIOWorker {
-public:
- ZipIOWorker() = default;
-
- void zip_fdopen(const std::string& path,
- std::function<void(std::unique_ptr<ZipHolder>)> cb) {
- int fd = ::open(path.c_str(), O_RDONLY, S_IRUSR);
- if (fd < 0) {
- cb(std::make_unique<ZipHolder>(nullptr));
- } else {
- int errorp;
- struct zip* archive = ::zip_fdopen(fd, 0, &errorp);
- cb(std::make_unique<ZipHolder>(archive));
- }
- }
-
- void zip_stat(struct zip* archive, const std::string& path,
- std::function<void (int, std::unique_ptr<struct zip_stat>)> cb) {
- std::unique_ptr<struct zip_stat> buf = std::make_unique<struct zip_stat>();
- ::zip_stat_init(buf.get());
-
- int ret = ::zip_stat(archive, path.c_str(), 0, buf.get());
- cb(ret, std::move(buf));
- }
-
- void zip_fopen(struct zip* archive, const std::string& path,
- std::function<void (std::unique_ptr<ZipFileHolder>)> cb) {
- struct zip_file* file = ::zip_fopen(archive, path.c_str(), 0);
- cb(std::make_unique<ZipFileHolder>(file));
- }
-
- void zip_fread(struct zip_file* file, size_t size,
- std::function<void (int, std::shared_ptr<std::string>)> cb) {
- std::shared_ptr<std::string> buf = std::make_shared<std::string>();
- buf->resize(size);
-
- int ret = ::zip_fread(file, &buf->front(), size);
- cb(ret, std::move(buf));
- }
-
- void zip_fclose(struct zip_file* file, std::function<void (int)> cb) {
- cb(::zip_fclose(file));
- }
-};
-
-}
-
-namespace mbgl {
-
-using namespace std::placeholders;
-
-class AssetZipContext;
-
-class AssetRequest : public RequestBase {
- MBGL_STORE_THREAD(tid)
-
-public:
- AssetRequest(const std::string& url, Callback, const std::string& assetRoot,
- AssetZipContext* context, util::Thread<ZipIOWorker>* worker);
- ~AssetRequest();
-
- // RequestBase implementation.
- void cancel() final;
-
-private:
- void openArchive();
- void archiveOpened(std::unique_ptr<ZipHolder>);
- void fileStated(int result, std::unique_ptr<struct zip_stat>);
- void fileOpened(std::unique_ptr<ZipFileHolder>);
- void fileRead(int result, std::shared_ptr<std::string>);
- void fileClosed();
-
- void close();
- void cleanup();
-
- void notifyError(Response::Error::Reason, const char *message);
-
- const std::string root;
- const std::string path;
- std::unique_ptr<Response> response;
-
- struct zip* archive = nullptr;
- struct zip_file* file = nullptr;
- size_t size = 0;
-
- AssetZipContext *context;
-
- util::Thread<ZipIOWorker> *worker;
- std::unique_ptr<WorkRequest> request;
-};
-
-class AssetZipContext : public AssetContextBase {
-public:
- AssetZipContext();
- ~AssetZipContext();
-
- RequestBase* createRequest(const std::string& url,
- RequestBase::Callback callback,
- const std::string& assetRoot) final {
- return new AssetRequest(url, callback, assetRoot, this, &worker);
- }
-
- struct zip *getHandle(const std::string &path);
- void returnHandle(const std::string &path, struct zip *zip);
-
- // A list of resuable zip handles to avoid creating
- // and destroying them all the time.
- std::map<std::string, std::forward_list<struct zip*>> handles;
-
- util::Thread<ZipIOWorker> worker;
- std::unique_ptr<WorkRequest> request;
-};
-
-AssetZipContext::AssetZipContext()
- : worker({"ZipIOWorker", util::ThreadType::Worker, util::ThreadPriority::Regular}) {}
-
-AssetZipContext::~AssetZipContext() {
- // Close all zip handles
- for (auto &list : handles) {
- for (auto archive : list.second) {
- zip_discard(archive);
- }
- }
-
- handles.clear();
-}
-
-struct zip* AssetZipContext::getHandle(const std::string &path) {
- auto &list = handles[path];
- if (!list.empty()) {
- auto archive = list.front();
- list.pop_front();
- return archive;
- } else {
- return nullptr;
- }
-}
-
-void AssetZipContext::returnHandle(const std::string &path, struct zip* archive) {
- handles[path].push_front(archive);
-}
-
-AssetRequest::AssetRequest(const std::string& url_, Callback callback_,
- const std::string& assetRoot, AssetZipContext* context_, util::Thread<ZipIOWorker>* worker_)
- : RequestBase(url_, callback_),
- root(assetRoot),
- path(std::string("assets/") + url.substr(8)),
- context(context_),
- worker(worker_) {
- archive = context->getHandle(root);
- if (archive) {
- request = worker->invokeWithCallback(&ZipIOWorker::zip_stat,
- std::bind(&AssetRequest::fileStated, this, _1, _2), archive, path);
- } else {
- request = worker->invokeWithCallback(&ZipIOWorker::zip_fdopen,
- std::bind(&AssetRequest::archiveOpened, this, _1), root);
- }
-}
-
-AssetRequest::~AssetRequest() {
- MBGL_VERIFY_THREAD(tid);
-}
-
-void AssetRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
- request.reset();
- close();
-}
-
-void AssetRequest::archiveOpened(std::unique_ptr<ZipHolder> holder) {
- MBGL_VERIFY_THREAD(tid);
-
- std::swap(archive, holder->archive);
-
- if (!archive) {
- notifyError(Response::Error::Reason::Other, "Could not open zip archive");
- cleanup();
- } else {
- request = worker->invokeWithCallback(&ZipIOWorker::zip_stat,
- std::bind(&AssetRequest::fileStated, this, _1, _2), archive, path);
- }
-}
-
-void AssetRequest::fileStated(int result, std::unique_ptr<struct zip_stat> stat) {
- MBGL_VERIFY_THREAD(tid);
-
- if (result < 0 || !(stat->valid & ZIP_STAT_SIZE)) {
- notifyError(Response::Error::Reason::NotFound, "Could not stat file in zip archive");
- cleanup();
- } else {
- response = std::make_unique<Response>();
-
- if (stat->valid & ZIP_STAT_MTIME) {
- response->modified = Seconds(stat->mtime);
- }
-
- if (stat->valid & ZIP_STAT_INDEX) {
- response->etag = std::to_string(stat->index);
- }
-
- size = stat->size;
-
- request = worker->invokeWithCallback(&ZipIOWorker::zip_fopen,
- std::bind(&AssetRequest::fileOpened, this, _1), archive, path);
- }
-}
-
-void AssetRequest::fileOpened(std::unique_ptr<ZipFileHolder> holder) {
- MBGL_VERIFY_THREAD(tid);
-
- std::swap(file, holder->file);
-
- if (!file) {
- notifyError(Response::Error::Reason::NotFound, "Could not open file in zip archive"),
- cleanup();
- } else {
- request = worker->invokeWithCallback(&ZipIOWorker::zip_fread,
- std::bind(&AssetRequest::fileRead, this, _1, _2), file, size);
- }
-}
-
-void AssetRequest::fileRead(int result, std::shared_ptr<std::string> data) {
- MBGL_VERIFY_THREAD(tid);
-
- if (result < 0) {
- notifyError(Response::Error::Reason::Other, "Could not read file in zip archive");
- } else {
- response->data = data;
- notify(std::move(response));
- }
-
- close();
-}
-
-void AssetRequest::fileClosed() {
- MBGL_VERIFY_THREAD(tid);
-
- cleanup();
-}
-
-
-void AssetRequest::close() {
- MBGL_VERIFY_THREAD(tid);
-
- if (file) {
- request = worker->invokeWithCallback(&ZipIOWorker::zip_fclose,
- std::bind(&AssetRequest::fileClosed, this), file);
- file = nullptr;
- } else {
- cleanup();
- }
-}
-
-void AssetRequest::cleanup() {
- MBGL_VERIFY_THREAD(tid);
-
- if (archive) {
- context->returnHandle(root, archive);
- }
-
- delete this;
-}
-
-void AssetRequest::notifyError(Response::Error::Reason reason, const char *message) {
- MBGL_VERIFY_THREAD(tid);
-
- response = std::make_unique<Response>();
- response->error = std::make_unique<Response::Error>(reason, message);
-
- notify(std::move(response));
-}
-
-std::unique_ptr<AssetContextBase> AssetContextBase::createContext() {
- return std::make_unique<AssetZipContext>();
-}
-
-}
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index d2bbce6002..8f2f024a11 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -1,16 +1,32 @@
#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/asset_file_source.hpp>
#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/storage/sqlite_cache.hpp>
+#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/url.hpp>
+
+namespace {
+
+const std::string assetProtocol = "asset://";
+
+bool isAssetURL(const std::string& url) {
+ return std::equal(assetProtocol.begin(), assetProtocol.end(), url.begin());
+}
+
+} // namespace
+
namespace mbgl {
class DefaultFileSource::Impl {
public:
- Impl(const std::string& cachePath, const std::string& root)
- : cache(SharedSQLiteCache::get(cachePath)),
- onlineFileSource(cache.get(), root) {
+ Impl(const std::string& cachePath, const std::string& assetRoot)
+ : assetFileSource(assetRoot),
+ cache(SharedSQLiteCache::get(cachePath)),
+ onlineFileSource(cache.get()) {
}
+ AssetFileSource assetFileSource;
std::shared_ptr<SQLiteCache> cache;
OnlineFileSource onlineFileSource;
};
@@ -38,7 +54,11 @@ void DefaultFileSource::setMaximumCacheEntrySize(uint64_t size) {
}
std::unique_ptr<FileRequest> DefaultFileSource::request(const Resource& resource, Callback callback) {
- return impl->onlineFileSource.request(resource, callback);
+ if (isAssetURL(resource.url)) {
+ return impl->assetFileSource.request(resource, callback);
+ } else {
+ return impl->onlineFileSource.request(resource, callback);
+ }
}
} // namespace mbgl
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index 480d2a8276..84be64a22f 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -1,10 +1,8 @@
#include <mbgl/storage/online_file_source.hpp>
-#include <mbgl/storage/asset_context_base.hpp>
#include <mbgl/storage/http_context_base.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/platform.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/thread.hpp>
@@ -14,7 +12,6 @@
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/timer.hpp>
-#include <mbgl/util/url.hpp>
#include <algorithm>
#include <cassert>
@@ -83,7 +80,7 @@ class OnlineFileSource::Impl {
public:
using Callback = std::function<void (Response)>;
- Impl(FileCache*, const std::string& = "");
+ Impl(FileCache*);
~Impl();
void networkIsReachableAgain();
@@ -96,17 +93,14 @@ private:
std::unordered_map<Resource, std::unique_ptr<OnlineFileRequestImpl>, Resource::Hash> pending;
FileCache* const cache;
- const std::string assetRoot;
- const std::unique_ptr<AssetContextBase> assetContext;
const std::unique_ptr<HTTPContextBase> httpContext;
util::AsyncTask reachability;
};
-OnlineFileSource::OnlineFileSource(FileCache* cache, const std::string& root)
+OnlineFileSource::OnlineFileSource(FileCache* cache)
: thread(std::make_unique<util::Thread<Impl>>(
util::ThreadContext{ "OnlineFileSource", util::ThreadType::Unknown, util::ThreadPriority::Low },
- cache,
- root)) {
+ cache)) {
}
OnlineFileSource::~OnlineFileSource() = default;
@@ -152,10 +146,8 @@ void OnlineFileSource::cancel(const Resource& res, FileRequest* req) {
// ----- Impl -----
-OnlineFileSource::Impl::Impl(FileCache* cache_, const std::string& root)
+OnlineFileSource::Impl::Impl(FileCache* cache_)
: cache(cache_),
- assetRoot(root.empty() ? platform::assetRoot() : root),
- assetContext(AssetContextBase::createContext()),
httpContext(HTTPContextBase::createContext()),
reachability(std::bind(&Impl::networkIsReachableAgain, this)) {
// Subscribe to network status changes, but make sure that this async handle doesn't keep the
@@ -242,7 +234,7 @@ void OnlineFileRequestImpl::addObserver(FileRequest* req, Callback callback, Onl
} else if (!cacheRequest && !realRequest) {
// There is no request in progress, and we don't have a response yet. This means we'll have
// to start the request ourselves.
- if (impl.cache && !util::isAssetURL(resource.url)) {
+ if (impl.cache) {
scheduleCacheRequest(impl);
} else {
scheduleRealRequest(impl);
@@ -330,7 +322,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo
// In particular, we don't want to write a Canceled request, or one that failed due to
// connection errors to the cache. Server errors are hopefully also temporary, so we're not
// caching them either.
- if (impl.cache && !util::isAssetURL(resource.url) &&
+ if (impl.cache &&
(!response_->error || (response_->error->reason == Response::Error::Reason::NotFound))) {
// Store response in database. Make sure we only refresh the expires column if the data
// didn't change.
@@ -357,11 +349,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo
scheduleRealRequest(impl);
};
- if (util::isAssetURL(resource.url)) {
- realRequest = impl.assetContext->createRequest(resource.url, callback, impl.assetRoot);
- } else {
- realRequest = impl.httpContext->createRequest(resource.url, callback, response);
- }
+ realRequest = impl.httpContext->createRequest(resource.url, callback, response);
});
}