diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-02-18 03:35:04 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-04-17 00:21:23 -0700 |
commit | f936295b76df6f998f8bf9508e7f370fe92cd0cf (patch) | |
tree | e34e2789329061d0b769131b018dfd174652eeb5 /platform/darwin/src/http_file_source.mm | |
parent | 943c09f1c74123fff480f9a1de075cd63c42c855 (diff) | |
download | qtlocation-mapboxgl-f936295b76df6f998f8bf9508e7f370fe92cd0cf.tar.gz |
[ios, osx] Include app/OS name/version in user agent
Fixes #3997.
Diffstat (limited to 'platform/darwin/src/http_file_source.mm')
-rw-r--r-- | platform/darwin/src/http_file_source.mm | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm index c7fdd2aae9..b888ddcf92 100644 --- a/platform/darwin/src/http_file_source.mm +++ b/platform/darwin/src/http_file_source.mm @@ -5,10 +5,18 @@ #include <mbgl/util/http_header.hpp> #include <mbgl/util/async_task.hpp> +#include "version.hpp" + #import <Foundation/Foundation.h> #include <mutex> +@interface MBGLBundleCanary : NSObject +@end + +@implementation MBGLBundleCanary +@end + namespace mbgl { // Data that is shared between the requesting thread and the thread running the completion handler. @@ -82,8 +90,7 @@ public: session = [NSURLSession sessionWithConfiguration:sessionConfig]; - // Write user agent string - userAgent = @"MapboxGL"; + userAgent = getUserAgent(); accountType = [[NSUserDefaults standardUserDefaults] integerForKey:@"MGLMapboxAccountType"]; } @@ -92,8 +99,93 @@ public: NSURLSession* session = nil; NSString* userAgent = nil; NSInteger accountType = 0; + +private: + NSString* getUserAgent() const; + NSBundle* getSDKBundle() const; }; +NSString *HTTPFileSource::Impl::getUserAgent() const { + NSMutableArray *userAgentComponents = [NSMutableArray array]; + + NSBundle *appBundle = [NSBundle mainBundle]; + if (appBundle) { + NSString *appName = appBundle.infoDictionary[@"CFBundleName"]; + [userAgentComponents addObject:[NSString stringWithFormat:@"%@/%@", + appName.length ? appName : appBundle.infoDictionary[@"CFBundleIdentifier"], + appBundle.infoDictionary[@"CFBundleShortVersionString"]]]; + } else { + [userAgentComponents addObject:[NSProcessInfo processInfo].processName]; + } + + NSBundle *sdkBundle = HTTPFileSource::Impl::getSDKBundle(); + if (sdkBundle) { + NSString *versionString = sdkBundle.infoDictionary[@"MGLSemanticVersionString"]; + if (!versionString) { + versionString = sdkBundle.infoDictionary[@"CFBundleShortVersionString"]; + } + if (versionString) { + [userAgentComponents addObject:[NSString stringWithFormat:@"%@/%@", + sdkBundle.infoDictionary[@"CFBundleName"], versionString]]; + } + } + + // Avoid %s here because it inserts hidden bidirectional markers on OS X when the system + // language is set to a right-to-left language. + [userAgentComponents addObject:[NSString stringWithFormat:@"MapboxGL/%@ (%@)", + CFSTR(MBGL_VERSION_STRING), CFSTR(MBGL_VERSION_REV)]]; + + NSString *systemName = @"Darwin"; +#if TARGET_OS_IPHONE + systemName = @"iOS"; +#elif TARGET_OS_MAC + systemName = @"OS X"; +#elif TARGET_OS_WATCH + systemName = @"watchOS"; +#elif TARGET_OS_TV + systemName = @"tvOS"; +#endif +#if TARGET_OS_SIMULATOR + systemName = [systemName stringByAppendingString:@" Simulator"]; +#endif + NSString *systemVersion = nil; + if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + systemVersion = [NSString stringWithFormat:@"%ld.%ld.%ld", + (long)osVersion.majorVersion, (long)osVersion.minorVersion, (long)osVersion.patchVersion]; + } + if (systemVersion) { + [userAgentComponents addObject:[NSString stringWithFormat:@"%@/%@", systemName, systemVersion]]; + } + + NSString *cpu = nil; +#if TARGET_CPU_X86 + cpu = @"x86"; +#elif TARGET_CPU_X86_64 + cpu = @"x86_64"; +#elif TARGET_CPU_ARM + cpu = @"arm"; +#elif TARGET_CPU_ARM64 + cpu = @"arm64"; +#endif + if (cpu) { + [userAgentComponents addObject:[NSString stringWithFormat:@"(%@)", cpu]]; + } + + return [userAgentComponents componentsJoinedByString:@" "]; +} + +NSBundle *HTTPFileSource::Impl::getSDKBundle() const { + NSBundle *bundle = [NSBundle bundleForClass:[MBGLBundleCanary class]]; + if (bundle && ![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"]) { + // For static frameworks, the class is contained in the application bundle rather than the + // framework bundle. + bundle = [NSBundle bundleWithPath:[bundle.privateFrameworksPath + stringByAppendingPathComponent:@"Mapbox.framework"]]; + } + return bundle; +} + HTTPFileSource::HTTPFileSource() : impl(std::make_unique<Impl>()) { } |