summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorM.Stephen <truestyle2005@163.com>2019-12-10 00:19:50 +0800
committerM.Stephen <truestyle2005@163.com>2019-12-10 00:19:50 +0800
commitca723845be6fffacb66874fdacf4308cf14af71b (patch)
tree27146a8e772c35ebd4d11d70a4b24366c36dc5c7
parentbc3fb0b1393e4c4bbbf8baa0b4fc1f7045e1b5ca (diff)
downloadqtlocation-mapboxgl-ca723845be6fffacb66874fdacf4308cf14af71b.tar.gz
http_file_source
-rw-r--r--platform/darwin/src/http_file_source.mm264
1 files changed, 128 insertions, 136 deletions
diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm
index dbf92aa462..43b832633a 100644
--- a/platform/darwin/src/http_file_source.mm
+++ b/platform/darwin/src/http_file_source.mm
@@ -8,12 +8,7 @@
#import <Foundation/Foundation.h>
-#import "MGLLoggingConfiguration_Private.h"
-#import "MGLNetworkConfiguration_Private.h"
-
-#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
-#import "MGLAccountManager_Private.h"
-#endif
+#import <mbgl/interface/native_apple_interface.h>
#include <mutex>
#include <chrono>
@@ -30,10 +25,10 @@ namespace mbgl {
class HTTPRequestShared {
public:
HTTPRequestShared(Response& response_, util::AsyncTask& async_)
- : response(response_),
- async(async_) {
+ : response(response_),
+ async(async_) {
}
-
+
void notify(const Response& response_) {
std::lock_guard<std::mutex> lock(mutex);
if (!cancelled) {
@@ -41,16 +36,16 @@ public:
async.send();
}
}
-
+
void cancel() {
std::lock_guard<std::mutex> lock(mutex);
cancelled = true;
}
-
+
private:
std::mutex mutex;
bool cancelled = false;
-
+
Response& response;
util::AsyncTask& async;
};
@@ -58,24 +53,24 @@ private:
class HTTPRequest : public AsyncRequest {
public:
HTTPRequest(FileSource::Callback callback_)
- : shared(std::make_shared<HTTPRequestShared>(response, async)),
- callback(callback_) {
+ : shared(std::make_shared<HTTPRequestShared>(response, async)),
+ callback(callback_) {
}
-
+
~HTTPRequest() override {
shared->cancel();
if (task) {
[task cancel];
}
}
-
+
std::shared_ptr<HTTPRequestShared> shared;
NSURLSessionDataTask* task = nil;
-
+
private:
FileSource::Callback callback;
Response response;
-
+
util::AsyncTask async { [this] {
// Calling `callback` may result in deleting `this`. Copy data to temporaries first.
auto callback_ = callback;
@@ -88,21 +83,21 @@ class HTTPFileSource::Impl {
public:
Impl() {
@autoreleasepool {
- NSURLSessionConfiguration *sessionConfig = [MGLNetworkConfiguration sharedManager].sessionConfiguration;
+ NSURLSessionConfiguration *sessionConfig = MGLNativeAppleInterfaceTransmitter.shared.sessionConfiguration;
session = [NSURLSession sessionWithConfiguration:sessionConfig];
-
+
userAgent = getUserAgent();
-
+
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
- accountType = [[NSUserDefaults standardUserDefaults] integerForKey:MGLMapboxAccountTypeKey];
+ accountType = [[NSUserDefaults standardUserDefaults] integerForKey:MGLNativeAppleInterfaceTransmitter.shared.accountTypeKey];
#endif
}
}
-
+
NSURLSession* session = nil;
NSString* userAgent = nil;
NSInteger accountType = 0;
-
+
private:
NSString* getUserAgent() const;
NSBundle* getSDKBundle() const;
@@ -110,7 +105,7 @@ private:
NSString *HTTPFileSource::Impl::getUserAgent() const {
NSMutableArray *userAgentComponents = [NSMutableArray array];
-
+
NSBundle *appBundle = [NSBundle mainBundle];
if (appBundle) {
NSString *appName = appBundle.infoDictionary[@"CFBundleName"];
@@ -120,7 +115,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
} else {
[userAgentComponents addObject:[NSProcessInfo processInfo].processName];
}
-
+
NSBundle *sdkBundle = HTTPFileSource::Impl::getSDKBundle();
if (sdkBundle) {
NSString *versionString = sdkBundle.infoDictionary[@"MGLSemanticVersionString"];
@@ -132,12 +127,12 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
sdkBundle.infoDictionary[@"CFBundleName"], versionString]];
}
}
-
+
// Avoid %s here because it inserts hidden bidirectional markers on macOS when the system
// language is set to a right-to-left language.
[userAgentComponents addObject:[NSString stringWithFormat:@"MapboxGL/0.0.0 (%@)",
@(mbgl::version::revision)]];
-
+
NSString *systemName = @"Darwin";
#if TARGET_OS_IPHONE
systemName = @"iOS";
@@ -160,7 +155,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
if (systemVersion) {
[userAgentComponents addObject:[NSString stringWithFormat:@"%@/%@", systemName, systemVersion]];
}
-
+
NSString *cpu = nil;
#if TARGET_CPU_X86
cpu = @"x86";
@@ -174,7 +169,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
if (cpu) {
[userAgentComponents addObject:[NSString stringWithFormat:@"(%@)", cpu]];
}
-
+
return [userAgentComponents componentsJoinedByString:@" "];
}
@@ -190,12 +185,12 @@ NSBundle *HTTPFileSource::Impl::getSDKBundle() const {
}
HTTPFileSource::HTTPFileSource()
- : impl(std::make_unique<Impl>()) {
+: impl(std::make_unique<Impl>()) {
}
HTTPFileSource::~HTTPFileSource() = default;
-MGL_EXPORT
+__attribute__((visibility ("default")))
BOOL isValidMapboxEndpoint(NSURL *url) {
return ([url.host isEqualToString:@"mapbox.com"] ||
[url.host hasSuffix:@".mapbox.com"] ||
@@ -203,7 +198,7 @@ BOOL isValidMapboxEndpoint(NSURL *url) {
[url.host hasSuffix:@".mapbox.cn"]);
}
-MGL_EXPORT
+__attribute__((visibility ("default")))
NSURL *resourceURLWithAccountType(const Resource& resource, NSInteger accountType) {
NSURL *url = [NSURL URLWithString:@(resource.url.c_str())];
@@ -212,12 +207,12 @@ NSURL *resourceURLWithAccountType(const Resource& resource, NSInteger accountTyp
if (accountType == 0 && isValidMapboxEndpoint(url)) {
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
NSMutableArray *queryItems = [NSMutableArray array];
-
+
if (resource.usage == Resource::Usage::Offline) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:@"offline" value:@"true"]];
} else {
// Only add SKU token to requests not tagged as "offline" usage.
- [queryItems addObject:[NSURLQueryItem queryItemWithName:@"sku" value:MGLAccountManager.skuToken]];
+ [queryItems addObject:[NSURLQueryItem queryItemWithName:@"sku" value:MGLNativeAppleInterfaceTransmitter.shared.skuToken]];
}
if (components.queryItems) {
@@ -232,57 +227,55 @@ NSURL *resourceURLWithAccountType(const Resource& resource, NSInteger accountTyp
#endif
return url;
}
-
+
std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
auto request = std::make_unique<HTTPRequest>(callback);
auto shared = request->shared; // Explicit copy so that it also gets copied into the completion handler block below.
-
+
@autoreleasepool {
NSURL *url = resourceURLWithAccountType(resource, impl->accountType);
- MGLLogDebug(@"Requesting URI: %@", url.relativePath);
-
+
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
if (resource.priorEtag) {
[req addValue:@(resource.priorEtag->c_str())
- forHTTPHeaderField:@"If-None-Match"];
+ forHTTPHeaderField:@"If-None-Match"];
} else if (resource.priorModified) {
[req addValue:@(util::rfc1123(*resource.priorModified).c_str())
- forHTTPHeaderField:@"If-Modified-Since"];
+ forHTTPHeaderField:@"If-Modified-Since"];
}
-
+
[req addValue:impl->userAgent forHTTPHeaderField:@"User-Agent"];
-
+
const bool isTile = resource.kind == mbgl::Resource::Kind::Tile;
-
+
if (isTile) {
- [[MGLNetworkConfiguration sharedManager] startDownloadEvent:url.relativePath type:@"tile"];
+ [MGLNativeAppleInterfaceTransmitter.shared startDownloadEvent:url.relativePath type:@"tile"];
}
request->task = [impl->session
- dataTaskWithRequest:req
- completionHandler:^(NSData* data, NSURLResponse* res, NSError* error) {
- if (error && [error code] == NSURLErrorCancelled) {
- [[MGLNetworkConfiguration sharedManager] cancelDownloadEventForResponse:res];
- return;
+ dataTaskWithRequest:req
+ completionHandler:^(NSData* data, NSURLResponse* res, NSError* error) {
+ if (error && [error code] == NSURLErrorCancelled) {
+ [MGLNativeAppleInterfaceTransmitter.shared cancelDownloadEventForResponse:res];
+ return;
+ }
+ [MGLNativeAppleInterfaceTransmitter.shared stopDownloadEventForResponse:res];
+ Response response;
+ using Error = Response::Error;
+
+ if (error) {
+
+ if (data) {
+ response.data =
+ std::make_shared<std::string>((const char*)[data bytes], [data length]);
}
- [[MGLNetworkConfiguration sharedManager] stopDownloadEventForResponse:res];
- Response response;
- using Error = Response::Error;
-
- if (error) {
- MGLLogError(@"Requesting: %@ failed with error: %@", res.URL.relativePath, error);
-
- if (data) {
- response.data =
- std::make_shared<std::string>((const char*)[data bytes], [data length]);
- }
-
- switch ([error code]) {
+
+ switch ([error code]) {
case NSURLErrorBadServerResponse: // 5xx errors
response.error = std::make_unique<Error>(
- Error::Reason::Server, [[error localizedDescription] UTF8String]);
+ Error::Reason::Server, [[error localizedDescription] UTF8String]);
break;
-
+
case NSURLErrorNetworkConnectionLost:
case NSURLErrorCannotFindHost:
case NSURLErrorCannotConnectToHost:
@@ -293,87 +286,86 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource,
case NSURLErrorDataNotAllowed:
case NSURLErrorTimedOut:
response.error = std::make_unique<Error>(
- Error::Reason::Connection, [[error localizedDescription] UTF8String]);
+ Error::Reason::Connection, [[error localizedDescription] UTF8String]);
break;
-
+
default:
response.error = std::make_unique<Error>(
- Error::Reason::Other, [[error localizedDescription] UTF8String]);
+ Error::Reason::Other, [[error localizedDescription] UTF8String]);
break;
+ }
+ } else if ([res isKindOfClass:[NSHTTPURLResponse class]]) {
+ const long responseCode = [(NSHTTPURLResponse *)res statusCode];
+
+ NSDictionary *headers = [(NSHTTPURLResponse *)res allHeaderFields];
+ NSString *cache_control = [headers objectForKey:@"Cache-Control"];
+ if (cache_control) {
+ const auto cc = http::CacheControl::parse([cache_control UTF8String]);
+ response.expires = cc.toTimePoint();
+ response.mustRevalidate = cc.mustRevalidate;
+ }
+
+ NSString *expires = [headers objectForKey:@"Expires"];
+ if (expires) {
+ response.expires = util::parseTimestamp([expires UTF8String]);
+ }
+
+ NSString *last_modified = [headers objectForKey:@"Last-Modified"];
+ if (last_modified) {
+ response.modified = util::parseTimestamp([last_modified UTF8String]);
+ }
+
+ NSString *etag = [headers objectForKey:@"ETag"];
+ if (etag) {
+ response.etag = std::string([etag UTF8String]);
+ }
+
+ if (responseCode == 200) {
+ response.data = std::make_shared<std::string>((const char *)[data bytes], [data length]);
+ } else if (responseCode == 204 || (responseCode == 404 && isTile)) {
+ response.noContent = true;
+ } else if (responseCode == 304) {
+ response.notModified = true;
+ } else if (responseCode == 404) {
+ response.error =
+ std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
+ } else if (responseCode == 429) {
+ // Get the standard header
+ optional<std::string> retryAfter;
+ NSString *retryAfterHeader = headers[@"Retry-After"];
+ if (retryAfterHeader) {
+ retryAfter = std::string([retryAfterHeader UTF8String]);
}
- } else if ([res isKindOfClass:[NSHTTPURLResponse class]]) {
- const long responseCode = [(NSHTTPURLResponse *)res statusCode];
- MGLLogDebug(@"Requesting %@ returned responseCode: %lu", res.URL.relativePath, responseCode);
-
- NSDictionary *headers = [(NSHTTPURLResponse *)res allHeaderFields];
- NSString *cache_control = [headers objectForKey:@"Cache-Control"];
- if (cache_control) {
- const auto cc = http::CacheControl::parse([cache_control UTF8String]);
- response.expires = cc.toTimePoint();
- response.mustRevalidate = cc.mustRevalidate;
- }
-
- NSString *expires = [headers objectForKey:@"Expires"];
- if (expires) {
- response.expires = util::parseTimestamp([expires UTF8String]);
- }
-
- NSString *last_modified = [headers objectForKey:@"Last-Modified"];
- if (last_modified) {
- response.modified = util::parseTimestamp([last_modified UTF8String]);
- }
-
- NSString *etag = [headers objectForKey:@"ETag"];
- if (etag) {
- response.etag = std::string([etag UTF8String]);
- }
-
- if (responseCode == 200) {
- response.data = std::make_shared<std::string>((const char *)[data bytes], [data length]);
- } else if (responseCode == 204 || (responseCode == 404 && isTile)) {
- response.noContent = true;
- } else if (responseCode == 304) {
- response.notModified = true;
- } else if (responseCode == 404) {
- response.error =
- std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
- } else if (responseCode == 429) {
- // Get the standard header
- optional<std::string> retryAfter;
- NSString *retryAfterHeader = headers[@"Retry-After"];
- if (retryAfterHeader) {
- retryAfter = std::string([retryAfterHeader UTF8String]);
- }
-
- // Fallback mapbox specific header
- optional<std::string> xRateLimitReset;
- NSString *xReset = headers[@"x-rate-limit-reset"];
- if (xReset) {
- xRateLimitReset = std::string([xReset UTF8String]);
- }
-
- response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
- } else if (responseCode >= 500 && responseCode < 600) {
- response.error =
- std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } +
- std::to_string(responseCode));
- } else {
- response.error =
- std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } +
- std::to_string(responseCode));
+
+ // Fallback mapbox specific header
+ optional<std::string> xRateLimitReset;
+ NSString *xReset = headers[@"x-rate-limit-reset"];
+ if (xReset) {
+ xRateLimitReset = std::string([xReset UTF8String]);
}
+
+ response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
+ } else if (responseCode >= 500 && responseCode < 600) {
+ response.error =
+ std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } +
+ std::to_string(responseCode));
} else {
- // This should never happen.
- response.error = std::make_unique<Error>(Error::Reason::Other,
- "Response class is not NSHTTPURLResponse");
+ response.error =
+ std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } +
+ std::to_string(responseCode));
}
-
- shared->notify(response);
- }];
-
+ } else {
+ // This should never happen.
+ response.error = std::make_unique<Error>(Error::Reason::Other,
+ "Response class is not NSHTTPURLResponse");
+ }
+
+ shared->notify(response);
+ }];
+
[request->task resume];
}
-
+
return std::move(request);
}