forked from organicmaps/organicmaps
[iOS] Update pods: Facebook, MoPub
This commit is contained in:
parent
28f5512af6
commit
e60b45759b
969 changed files with 33986 additions and 26168 deletions
|
@ -1,26 +0,0 @@
|
|||
## Changelog
|
||||
|
||||
* 4.28.1.2
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.28.1.
|
||||
* Enables advanced bidding for all adapters and adds FacebookAdvancedBidder.
|
||||
|
||||
* 4.28.1.1
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.28.1.
|
||||
* Rename delegate method rewardedVideoAdComplete to rewardedVideoAdVideoComplete per Facebook Audience Network change.
|
||||
* 4.28.1.0
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.28.1.
|
||||
|
||||
* 4.28.0.1
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.28.0.
|
||||
* Removed star rating from the native ad adapter since it has been deprecated by Facebook.
|
||||
|
||||
* 4.28.0.0
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.28.0.
|
||||
* Updated native adapters to handle the use-case of empty clickable views
|
||||
* Updated Rewarded Video header files to be consistent with the rest of the header files
|
||||
|
||||
* 4.27.0.1
|
||||
* This version of the adapters has been certified with Facebook Audience Network 4.27.0.
|
||||
|
||||
* Initial Commit
|
||||
* Adapters moved from [mopub-iOS-sdk](https://github.com/mopub/mopub-ios-sdk) to [mopub-iOS-mediation](https://github.com/mopub/mopub-iOS-mediation/)
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// FacebookAdvancedBidder.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#if __has_include(<MoPub/MoPub.h>)
|
||||
#import <MoPub/MoPub.h>
|
||||
#else
|
||||
#import "MPAdvancedBidder.h"
|
||||
#endif
|
||||
|
||||
|
||||
@interface FacebookAdvancedBidder : NSObject<MPAdvancedBidder>
|
||||
@property (nonatomic, copy, readonly) NSString * creativeNetworkName;
|
||||
@property (nonatomic, copy, readonly) NSString * token;
|
||||
@end
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// FacebookAdvancedBidder.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FacebookAdvancedBidder.h"
|
||||
#import <FBAudienceNetwork/FBAudienceNetwork.h>
|
||||
|
||||
@implementation FacebookAdvancedBidder
|
||||
|
||||
+ (void)initialize {
|
||||
if (self == [FacebookAdvancedBidder self]) {
|
||||
// Initialize an adview to trigger [FBAdUtility initializeAudienceNetwork]
|
||||
FBAdView * initHackforFacebook = [[FBAdView alloc] initWithPlacementID:@"" adSize:kFBAdSize320x50 rootViewController:[UIViewController new]];
|
||||
if (initHackforFacebook) {
|
||||
NSLog(@"Initialized Facebook Audience Network");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)creativeNetworkName {
|
||||
return @"facebook";
|
||||
}
|
||||
|
||||
- (NSString *)token {
|
||||
return [FBAdSettings bidderToken];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,159 +0,0 @@
|
|||
//
|
||||
// FacebookBannerCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FBAudienceNetwork/FBAudienceNetwork.h>
|
||||
#import "FacebookBannerCustomEvent.h"
|
||||
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
@interface MPInstanceProvider (FacebookBanners)
|
||||
|
||||
- (FBAdView *)buildFBAdViewWithPlacementID:(NSString *)placementID
|
||||
size:(FBAdSize)size
|
||||
rootViewController:(UIViewController *)controller
|
||||
delegate:(id<FBAdViewDelegate>)delegate;
|
||||
@end
|
||||
|
||||
@implementation MPInstanceProvider (FacebookBanners)
|
||||
|
||||
- (FBAdView *)buildFBAdViewWithPlacementID:(NSString *)placementID
|
||||
size:(FBAdSize)size
|
||||
rootViewController:(UIViewController *)controller
|
||||
delegate:(id<FBAdViewDelegate>)delegate
|
||||
{
|
||||
FBAdView *adView = [[FBAdView alloc] initWithPlacementID:placementID
|
||||
adSize:size
|
||||
rootViewController:controller];
|
||||
adView.delegate = delegate;
|
||||
[adView disableAutoRefresh];
|
||||
return adView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FacebookBannerCustomEvent () <FBAdViewDelegate>
|
||||
|
||||
@property (nonatomic, strong) FBAdView *fbAdView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FacebookBannerCustomEvent
|
||||
|
||||
- (BOOL)enableAutomaticImpressionAndClickTracking
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info
|
||||
{
|
||||
[self requestAdWithSize:size customEventInfo:info adMarkup:nil];
|
||||
}
|
||||
|
||||
- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup
|
||||
{
|
||||
/**
|
||||
* Facebook Banner ads can accept arbitrary widths for given heights of 50 and 90. We convert these sizes
|
||||
* to Facebook's constants and set the fbAdView's size to the intended size ("size" passed to this method).
|
||||
*/
|
||||
FBAdSize fbAdSize;
|
||||
if (size.height == kFBAdSizeHeight250Rectangle.size.height) {
|
||||
fbAdSize = kFBAdSizeHeight250Rectangle;
|
||||
} else if (size.height == kFBAdSizeHeight90Banner.size.height) {
|
||||
fbAdSize = kFBAdSizeHeight90Banner;
|
||||
} else if (size.height == kFBAdSizeHeight50Banner.size.height) {
|
||||
fbAdSize = kFBAdSizeHeight50Banner;
|
||||
} else {
|
||||
MPLogError(@"Invalid size for Facebook banner ad");
|
||||
[self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
if (![info objectForKey:@"placement_id"]) {
|
||||
MPLogError(@"Placement ID is required for Facebook banner ad");
|
||||
[self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
MPLogInfo(@"Requesting Facebook banner ad");
|
||||
self.fbAdView =
|
||||
[[MPInstanceProvider sharedProvider] buildFBAdViewWithPlacementID:[info objectForKey:@"placement_id"]
|
||||
size:fbAdSize
|
||||
rootViewController:[self.delegate viewControllerForPresentingModalView]
|
||||
delegate:self];
|
||||
|
||||
if (!self.fbAdView) {
|
||||
[self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Manually resize the frame of the FBAdView due to a bug in the Facebook SDK that sets the ad's width
|
||||
* to the width of the device instead of the width of the container it's placed in.
|
||||
* (Confirmed in email with a FB Solutions Engineer)
|
||||
*/
|
||||
CGRect fbAdFrame = self.fbAdView.frame;
|
||||
fbAdFrame.size = size;
|
||||
self.fbAdView.frame = fbAdFrame;
|
||||
[FBAdSettings setMediationService:[NSString stringWithFormat:@"MOPUB_%@", MP_SDK_VERSION]];
|
||||
|
||||
// Load the advanced bid payload.
|
||||
if (adMarkup != nil) {
|
||||
MPLogInfo(@"Loading Facebook banner ad markup");
|
||||
[self.fbAdView loadAdWithBidPayload:adMarkup];
|
||||
}
|
||||
// Request a banner ad.
|
||||
else {
|
||||
MPLogInfo(@"Requesting Facebook banner ad");
|
||||
[self.fbAdView loadAd];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_fbAdView.delegate = nil;
|
||||
}
|
||||
|
||||
#pragma mark FBAdViewDelegate methods
|
||||
|
||||
- (void)adView:(FBAdView *)adView didFailWithError:(NSError *)error
|
||||
{
|
||||
MPLogInfo(@"Facebook banner failed to load with error: %@", error.localizedDescription);
|
||||
[self.delegate bannerCustomEvent:self didFailToLoadAdWithError:error];
|
||||
}
|
||||
|
||||
- (void)adViewDidLoad:(FBAdView *)adView
|
||||
{
|
||||
MPLogInfo(@"Facebook banner ad did load");
|
||||
[self.delegate bannerCustomEvent:self didLoadAd:adView];
|
||||
}
|
||||
|
||||
- (void)adViewWillLogImpression:(FBAdView *)adView
|
||||
{
|
||||
MPLogInfo(@"Facebook banner ad did log impression");
|
||||
[self.delegate trackImpression];
|
||||
}
|
||||
|
||||
- (void)adViewDidClick:(FBAdView *)adView
|
||||
{
|
||||
MPLogInfo(@"Facebook banner ad was clicked");
|
||||
[self.delegate trackClick];
|
||||
[self.delegate bannerCustomEventWillBeginAction:self];
|
||||
}
|
||||
|
||||
- (void)adViewDidFinishHandlingClick:(FBAdView *)adView
|
||||
{
|
||||
MPLogInfo(@"Facebook banner ad did finish handling click");
|
||||
[self.delegate bannerCustomEventDidFinishAction:self];
|
||||
}
|
||||
|
||||
- (UIViewController *)viewControllerForPresentingModalView
|
||||
{
|
||||
return [self.delegate viewControllerForPresentingModalView];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,154 +0,0 @@
|
|||
//
|
||||
// FacebookInterstitialCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FBAudienceNetwork/FBAudienceNetwork.h>
|
||||
#import "FacebookInterstitialCustomEvent.h"
|
||||
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPRealTimeTimer.h"
|
||||
|
||||
//Timer to record the expiration interval
|
||||
#define FB_ADS_EXPIRATION_INTERVAL 3600
|
||||
|
||||
|
||||
@interface MPInstanceProvider (FacebookInterstitials)
|
||||
|
||||
- (FBInterstitialAd *)buildFBInterstitialAdWithPlacementID:(NSString *)placementID
|
||||
delegate:(id<FBInterstitialAdDelegate>)delegate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPInstanceProvider (FacebookInterstitials)
|
||||
|
||||
- (FBInterstitialAd *)buildFBInterstitialAdWithPlacementID:(NSString *)placementID
|
||||
delegate:(id<FBInterstitialAdDelegate>)delegate
|
||||
{
|
||||
FBInterstitialAd *interstitialAd = [[FBInterstitialAd alloc] initWithPlacementID:placementID];
|
||||
interstitialAd.delegate = delegate;
|
||||
return interstitialAd;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FacebookInterstitialCustomEvent () <FBInterstitialAdDelegate>
|
||||
|
||||
@property (nonatomic, strong) FBInterstitialAd *fbInterstitialAd;
|
||||
@property (nonatomic, strong) MPRealTimeTimer *expirationTimer;
|
||||
@property (nonatomic, assign) BOOL hasTrackedImpression;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FacebookInterstitialCustomEvent
|
||||
|
||||
@synthesize hasTrackedImpression = _hasTrackedImpression;
|
||||
|
||||
- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info
|
||||
{
|
||||
[self requestInterstitialWithCustomEventInfo:info adMarkup:nil];
|
||||
}
|
||||
|
||||
- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup
|
||||
{
|
||||
if (![info objectForKey:@"placement_id"]) {
|
||||
MPLogError(@"Placement ID is required for Facebook interstitial ad");
|
||||
[self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
self.fbInterstitialAd =
|
||||
[[MPInstanceProvider sharedProvider] buildFBInterstitialAdWithPlacementID:[info objectForKey:@"placement_id"]
|
||||
delegate:self];
|
||||
[FBAdSettings setMediationService:[NSString stringWithFormat:@"MOPUB_%@", MP_SDK_VERSION]];
|
||||
|
||||
// Load the advanced bid payload.
|
||||
if (adMarkup != nil) {
|
||||
MPLogInfo(@"Loading Facebook interstitial ad markup");
|
||||
[self.fbInterstitialAd loadAdWithBidPayload:adMarkup];
|
||||
}
|
||||
// Request a interstitial ad.
|
||||
else {
|
||||
MPLogInfo(@"Requesting Facebook interstitial ad");
|
||||
[self.fbInterstitialAd loadAd];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showInterstitialFromRootViewController:(UIViewController *)controller {
|
||||
if (!self.fbInterstitialAd || !self.fbInterstitialAd.isAdValid) {
|
||||
MPLogError(@"Facebook interstitial ad was not loaded");
|
||||
[self.delegate interstitialCustomEventDidExpire:self];
|
||||
} else {
|
||||
MPLogInfo(@"Facebook interstitial ad will be presented");
|
||||
[self.delegate interstitialCustomEventWillAppear:self];
|
||||
[self.fbInterstitialAd showAdFromRootViewController:controller];
|
||||
MPLogInfo(@"Facebook interstitial ad was presented");
|
||||
[self.delegate interstitialCustomEventDidAppear:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_fbInterstitialAd.delegate = nil;
|
||||
}
|
||||
|
||||
#pragma mark FBInterstitialAdDelegate methods
|
||||
|
||||
- (void)interstitialAdDidLoad:(FBInterstitialAd *)interstitialAd
|
||||
{
|
||||
MPLogInfo(@"Facebook intersitital ad was loaded. Can present now");
|
||||
[self.delegate interstitialCustomEvent:self didLoadAd:interstitialAd];
|
||||
|
||||
// introduce timer for 1 hour as per caching logic introduced by FB
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
self.expirationTimer = [[MPRealTimeTimer alloc] initWithInterval:FB_ADS_EXPIRATION_INTERVAL block:^(MPRealTimeTimer *timer){
|
||||
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
||||
if (strongSelf && !strongSelf.hasTrackedImpression) {
|
||||
[self.delegate interstitialCustomEventDidExpire:self];
|
||||
MPLogInfo(@"Facebook intersitital ad expired as per the audience network's caching policy");
|
||||
//Delete the cached objects
|
||||
self.fbInterstitialAd = nil;
|
||||
}
|
||||
[strongSelf.expirationTimer invalidate];
|
||||
}];
|
||||
[self.expirationTimer scheduleNow];
|
||||
|
||||
}
|
||||
|
||||
- (void)interstitialAdWillLogImpression:(FBInterstitialAd *)interstitialAd
|
||||
{
|
||||
MPLogInfo(@"Facebook intersitital ad is logging impressions for interstitials");
|
||||
//set the tracker to true when the ad is shown on the screen. So that the timer is invalidated.
|
||||
_hasTrackedImpression = true;
|
||||
[self.expirationTimer invalidate];
|
||||
}
|
||||
|
||||
- (void)interstitialAd:(FBInterstitialAd *)interstitialAd didFailWithError:(NSError *)error
|
||||
{
|
||||
MPLogInfo(@"Facebook intersitital ad failed to load with error: %@", error.localizedDescription);
|
||||
[self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
}
|
||||
|
||||
- (void)interstitialAdDidClick:(FBInterstitialAd *)interstitialAd
|
||||
{
|
||||
MPLogInfo(@"Facebook interstitial ad was clicked");
|
||||
[self.delegate interstitialCustomEventDidReceiveTapEvent:self];
|
||||
}
|
||||
|
||||
- (void)interstitialAdDidClose:(FBInterstitialAd *)interstitialAd
|
||||
{
|
||||
MPLogInfo(@"Facebook interstitial ad was closed");
|
||||
[self.delegate interstitialCustomEventDidDisappear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialAdWillClose:(FBInterstitialAd *)interstitialAd
|
||||
{
|
||||
MPLogInfo(@"Facebook interstitial ad will close");
|
||||
[self.delegate interstitialCustomEventWillDisappear:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,147 +0,0 @@
|
|||
//
|
||||
// FacebookNativeAdAdapter.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FBAudienceNetwork/FBAudienceNetwork.h>
|
||||
#import "FacebookNativeAdAdapter.h"
|
||||
#import "MPNativeAdConstants.h"
|
||||
#import "MPNativeAdError.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
NSString *const kFBVideoAdsEnabledKey = @"video_enabled";
|
||||
|
||||
@interface FacebookNativeAdAdapter () <FBNativeAdDelegate>
|
||||
|
||||
@property (nonatomic, readonly) FBNativeAd *fbNativeAd;
|
||||
@property (nonatomic, readonly) FBAdChoicesView *adChoicesView;
|
||||
@property (nonatomic, readonly) FBMediaView *mediaView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FacebookNativeAdAdapter
|
||||
|
||||
@synthesize properties = _properties;
|
||||
|
||||
- (instancetype)initWithFBNativeAd:(FBNativeAd *)fbNativeAd adProperties:(NSDictionary *)adProps
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_fbNativeAd = fbNativeAd;
|
||||
_fbNativeAd.delegate = self;
|
||||
|
||||
NSMutableDictionary *properties;
|
||||
if (adProps) {
|
||||
properties = [NSMutableDictionary dictionaryWithDictionary:adProps];
|
||||
} else {
|
||||
properties = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
if (fbNativeAd.title) {
|
||||
[properties setObject:fbNativeAd.title forKey:kAdTitleKey];
|
||||
}
|
||||
|
||||
if (fbNativeAd.body) {
|
||||
[properties setObject:fbNativeAd.body forKey:kAdTextKey];
|
||||
}
|
||||
|
||||
if (fbNativeAd.callToAction) {
|
||||
[properties setObject:fbNativeAd.callToAction forKey:kAdCTATextKey];
|
||||
}
|
||||
|
||||
if (fbNativeAd.icon.url.absoluteString) {
|
||||
[properties setObject:fbNativeAd.icon.url.absoluteString forKey:kAdIconImageKey];
|
||||
}
|
||||
|
||||
if (fbNativeAd.placementID) {
|
||||
[properties setObject:fbNativeAd.placementID forKey:@"placementID"];
|
||||
}
|
||||
|
||||
if (fbNativeAd.socialContext) {
|
||||
[properties setObject:fbNativeAd.socialContext forKey:@"socialContext"];
|
||||
}
|
||||
|
||||
_properties = properties;
|
||||
|
||||
_adChoicesView = [[FBAdChoicesView alloc] initWithNativeAd:fbNativeAd];
|
||||
_adChoicesView.backgroundShown = NO;
|
||||
|
||||
// If video ad is enabled, use mediaView, otherwise use coverImage.
|
||||
if ([[_properties objectForKey:kFBVideoAdsEnabledKey] boolValue]) {
|
||||
_mediaView = [[FBMediaView alloc] initWithNativeAd:fbNativeAd];
|
||||
} else {
|
||||
if (fbNativeAd.coverImage.url.absoluteString) {
|
||||
[properties setObject:fbNativeAd.coverImage.url.absoluteString forKey:kAdMainImageKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - MPNativeAdAdapter
|
||||
|
||||
- (NSURL *)defaultActionURL
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)enableThirdPartyClickTracking
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)willAttachToView:(UIView *)view
|
||||
{
|
||||
[self.fbNativeAd registerViewForInteraction:view withViewController:[self.delegate viewControllerForPresentingModalView]];
|
||||
}
|
||||
|
||||
- (void)willAttachToView:(UIView *)view withAdContentViews:(NSArray *)adContentViews
|
||||
{
|
||||
if ( adContentViews.count > 0 ) {
|
||||
[self.fbNativeAd registerViewForInteraction:view withViewController:[self.delegate viewControllerForPresentingModalView] withClickableViews:adContentViews];
|
||||
} else {
|
||||
[self willAttachToView:view];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)privacyInformationIconView
|
||||
{
|
||||
return self.adChoicesView;
|
||||
}
|
||||
|
||||
- (UIView *)mainMediaView
|
||||
{
|
||||
return self.mediaView;
|
||||
}
|
||||
|
||||
#pragma mark - FBNativeAdDelegate
|
||||
|
||||
- (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(nativeAdWillLogImpression:)]) {
|
||||
[self.delegate nativeAdWillLogImpression:self];
|
||||
} else {
|
||||
MPLogWarn(@"Delegate does not implement impression tracking callback. Impressions likely not being tracked.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)nativeAdDidClick:(FBNativeAd *)nativeAd
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(nativeAdDidClick:)]) {
|
||||
[self.delegate nativeAdDidClick:self];
|
||||
} else {
|
||||
MPLogWarn(@"Delegate does not implement click tracking callback. Clicks likely not being tracked.");
|
||||
}
|
||||
|
||||
[self.delegate nativeAdWillPresentModalForAdapter:self];
|
||||
}
|
||||
|
||||
- (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd
|
||||
{
|
||||
[self.delegate nativeAdDidDismissModalForAdapter:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// FacebookNativeCustomEvent.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#if __has_include(<MoPub/MoPub.h>)
|
||||
#import <MoPub/MoPub.h>
|
||||
#else
|
||||
#import "MPNativeCustomEvent.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Certified with Facebook Audience Network 4.26.1
|
||||
*/
|
||||
@interface FacebookNativeCustomEvent : MPNativeCustomEvent
|
||||
|
||||
|
||||
/**
|
||||
* Toggle FB video ads on/off. If it is enabled, it means you are open yourself to video inventory.
|
||||
* If it is not enabled, it is gauranteed you won't get video ads.
|
||||
*
|
||||
* IMPORTANT: If you choose to use this method, be sure to call it before making any ad requests,
|
||||
* and avoid calling it more than once.
|
||||
*/
|
||||
|
||||
+ (void)setVideoEnabled:(BOOL)enabled;
|
||||
|
||||
@end
|
|
@ -1,104 +0,0 @@
|
|||
//
|
||||
// FacebookNativeCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
#import <FBAudienceNetwork/FBAudienceNetwork.h>
|
||||
#import "FacebookNativeCustomEvent.h"
|
||||
#import "FacebookNativeAdAdapter.h"
|
||||
#import "MPNativeAd.h"
|
||||
#import "MPNativeAdError.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPNativeAdConstants.h"
|
||||
|
||||
static const NSInteger FacebookNoFillErrorCode = 1001;
|
||||
static BOOL gVideoEnabled = NO;
|
||||
|
||||
@interface FacebookNativeCustomEvent () <FBNativeAdDelegate>
|
||||
|
||||
@property (nonatomic, readwrite, strong) FBNativeAd *fbNativeAd;
|
||||
@property (nonatomic) BOOL videoEnabled;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FacebookNativeCustomEvent
|
||||
|
||||
+ (void)setVideoEnabled:(BOOL)enabled
|
||||
{
|
||||
gVideoEnabled = enabled;
|
||||
}
|
||||
|
||||
- (void)requestAdWithCustomEventInfo:(NSDictionary *)info
|
||||
{
|
||||
[self requestAdWithCustomEventInfo:info adMarkup:nil];
|
||||
}
|
||||
|
||||
- (void)requestAdWithCustomEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup
|
||||
{
|
||||
NSString *placementID = [info objectForKey:@"placement_id"];
|
||||
|
||||
if ([info objectForKey:kFBVideoAdsEnabledKey] == nil) {
|
||||
self.videoEnabled = gVideoEnabled;
|
||||
} else {
|
||||
self.videoEnabled = [[info objectForKey:kFBVideoAdsEnabledKey] boolValue];
|
||||
}
|
||||
|
||||
if (placementID) {
|
||||
_fbNativeAd = [[FBNativeAd alloc] initWithPlacementID:placementID];
|
||||
self.fbNativeAd.delegate = self;
|
||||
[FBAdSettings setMediationService:[NSString stringWithFormat:@"MOPUB_%@", MP_SDK_VERSION]];
|
||||
|
||||
// Load the advanced bid payload.
|
||||
if (adMarkup != nil) {
|
||||
MPLogInfo(@"Loading Facebook native ad markup");
|
||||
[self.fbNativeAd loadAdWithBidPayload:adMarkup];
|
||||
}
|
||||
// Request a banner ad.
|
||||
else {
|
||||
MPLogInfo(@"Requesting Facebook native ad");
|
||||
[self.fbNativeAd loadAd];
|
||||
}
|
||||
} else {
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(@"Invalid Facebook placement ID")];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FBNativeAdDelegate
|
||||
|
||||
- (void)nativeAdDidLoad:(FBNativeAd *)nativeAd
|
||||
{
|
||||
FacebookNativeAdAdapter *adAdapter = [[FacebookNativeAdAdapter alloc] initWithFBNativeAd:nativeAd adProperties:@{kFBVideoAdsEnabledKey:@(self.videoEnabled)}];
|
||||
MPNativeAd *interfaceAd = [[MPNativeAd alloc] initWithAdAdapter:adAdapter];
|
||||
|
||||
NSMutableArray *imageURLs = [NSMutableArray array];
|
||||
|
||||
if (nativeAd.icon.url) {
|
||||
[imageURLs addObject:nativeAd.icon.url];
|
||||
}
|
||||
|
||||
// If video is enabled, no need to load coverImage.
|
||||
if (!self.videoEnabled && nativeAd.coverImage.url) {
|
||||
[imageURLs addObject:nativeAd.coverImage.url];
|
||||
}
|
||||
|
||||
[super precacheImagesWithURLs:imageURLs completionBlock:^(NSArray *errors) {
|
||||
if (errors) {
|
||||
MPLogDebug(@"%@", errors);
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForImageDownloadFailure()];
|
||||
} else {
|
||||
[self.delegate nativeCustomEvent:self didLoadAd:interfaceAd];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)nativeAd:(FBNativeAd *)nativeAd didFailWithError:(NSError *)error
|
||||
{
|
||||
if (error.code == FacebookNoFillErrorCode) {
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForNoInventory()];
|
||||
} else {
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(@"Facebook ad load error")];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,24 +0,0 @@
|
|||
#
|
||||
# Be sure to run `pod lib lint MoPub-Facebook-Adapters.podspec' to ensure this is a
|
||||
# valid spec before submitting.
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'MoPub-FacebookAudienceNetwork-Adapters'
|
||||
s.version = '4.28.1.2'
|
||||
s.summary = 'Facebook Adapters for mediating through MoPub.'
|
||||
s.description = <<-DESC
|
||||
Supported ad formats: Banners, Interstitial, Rewarded Video and Native.\n
|
||||
To download and integrate the Facebook SDK, please check https://developers.facebook.com/docs/audience-network/ios/#sdk. \n\n
|
||||
For inquiries and support, please visit https://developers.facebook.com/products/audience-network/faq/. \n
|
||||
DESC
|
||||
s.homepage = 'https://github.com/mopub/mopub-ios-mediation'
|
||||
s.license = { :type => 'New BSD', :file => 'LICENSE' }
|
||||
s.author = { 'MoPub' => 'support@mopub.com' }
|
||||
s.source = { :git => 'https://github.com/mopub/mopub-ios-mediation.git', :commit => 'master' }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.static_framework = true
|
||||
s.source_files = 'FacebookAudienceNetwork/*.{h,m}'
|
||||
s.dependency 'mopub-ios-sdk', '~> 5.0'
|
||||
s.dependency 'FBAudienceNetwork', '4.28.1'
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
## Overview
|
||||
* This folder contains mediation adapters used to mediate Facebook AN.
|
||||
* To download and integrate the Facebook AN SDK, please check [this tutorial](https://developers.facebook.com/docs/audience-network/ios/#sdk).
|
||||
* For inquiries and support, please visit [support](https://developers.facebook.com/products/audience-network/faq/) forum.
|
||||
|
||||
## Adapter integration
|
||||
* To integrate adapters, please visit our [integration tutorial](https://developers.mopub.com/docs/ios/integrating-networks/).
|
|
@ -1,307 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <FBAudienceNetwork/FBAdDefines.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FBNativeAdDelegate;
|
||||
@class FBAdImage;
|
||||
|
||||
/**
|
||||
Determines what parts of a native ad's content are cached through FBMediaView
|
||||
*/
|
||||
typedef NS_OPTIONS(NSInteger, FBNativeAdsCachePolicy) {
|
||||
/// No ad content is cached
|
||||
FBNativeAdsCachePolicyNone = 1 << 0,
|
||||
/// Icon is cached
|
||||
FBNativeAdsCachePolicyIcon = 1 << 1,
|
||||
/// Cover image is cached
|
||||
FBNativeAdsCachePolicyCoverImage = 1 << 2,
|
||||
/// Video is cached
|
||||
FBNativeAdsCachePolicyVideo = 1 << 3,
|
||||
/// AdChoices icon is cached
|
||||
FBNativeAdsCachePolicyAdChoices = 1 << 4,
|
||||
/// All content is cached
|
||||
FBNativeAdsCachePolicyAll = FBNativeAdsCachePolicyCoverImage | FBNativeAdsCachePolicyIcon | FBNativeAdsCachePolicyVideo | FBNativeAdsCachePolicyAdChoices,
|
||||
};
|
||||
|
||||
/**
|
||||
The FBNativeAd represents ad metadata to allow you to construct custom ad views.
|
||||
See the AdUnitsSample in the sample apps section of the Audience Network framework.
|
||||
*/
|
||||
FB_CLASS_EXPORT FB_SUBCLASSING_RESTRICTED
|
||||
@interface FBNativeAd : NSObject
|
||||
|
||||
/**
|
||||
Typed access to the id of the ad placement.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSString *placementID;
|
||||
/**
|
||||
Typed access to the ad star rating. See `FBAdStarRating` for details.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) struct FBAdStarRating starRating FB_DEPRECATED;
|
||||
/**
|
||||
Typed access to the ad title.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *title;
|
||||
/**
|
||||
Typed access to the ad subtitle.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *subtitle;
|
||||
/**
|
||||
Typed access to the ad social context, for example "Over half a million users".
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *socialContext;
|
||||
/**
|
||||
Typed access to the call to action phrase of the ad, for example "Install Now".
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *callToAction;
|
||||
/**
|
||||
Typed access to the ad icon. See `FBAdImage` for details.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly, nullable) FBAdImage *icon;
|
||||
/**
|
||||
Typed access to the ad cover image creative. See `FBAdImage` for details.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly, nullable) FBAdImage *coverImage;
|
||||
/**
|
||||
Typed access to the body raw untruncated text, usually a longer description of the ad. Note, this method always returns untruncated text, as opposed to -(NSString *) body.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *rawBody;
|
||||
/**
|
||||
Typed access to the body text, usually a longer description of the ad.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *body;
|
||||
/**
|
||||
Typed access to the AdChoices icon. See `FBAdImage` for details. See `FBAdChoicesView` for an included implementation.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly, nullable) FBAdImage *adChoicesIcon;
|
||||
/**
|
||||
Typed access to the AdChoices URL. Navigate to this link when the icon is tapped. See `FBAdChoicesView` for an included implementation.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSURL *adChoicesLinkURL;
|
||||
/**
|
||||
Typed access to the AdChoices text, usually a localized version of "AdChoices". See `FBAdChoicesView` for an included implementation.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *adChoicesText;
|
||||
|
||||
/**
|
||||
Set the native ad caching policy. This controls which media (images, video, etc) from the native ad are cached before the native ad calls nativeAdLoaded on its delegate. The default is to not block on caching. Ensure that media is loaded through FBMediaView or through [FBAdImage loadImageAsyncWithBlock:] to take full advantage of caching.
|
||||
*/
|
||||
@property (nonatomic, assign) FBNativeAdsCachePolicy mediaCachePolicy;
|
||||
/**
|
||||
the delegate
|
||||
*/
|
||||
@property (nonatomic, weak, nullable) id<FBNativeAdDelegate> delegate;
|
||||
|
||||
/**
|
||||
This is a method to initialize a FBNativeAd object matching the given placement id.
|
||||
|
||||
- Parameter placementID: The id of the ad placement. You can create your placement id from Facebook developers page.
|
||||
*/
|
||||
- (instancetype)initWithPlacementID:(NSString *)placementID NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
This is a method to associate a FBNativeAd with the UIView you will use to display the native ads.
|
||||
|
||||
- Parameter view: The UIView you created to render all the native ads data elements.
|
||||
- Parameter viewController: The UIViewController that will be used to present SKStoreProductViewController
|
||||
(iTunes Store product information) or the in-app browser. If nil is passed, the top view controller currently shown will be used.
|
||||
|
||||
|
||||
The whole area of the UIView will be clickable.
|
||||
*/
|
||||
- (void)registerViewForInteraction:(UIView *)view
|
||||
withViewController:(nullable UIViewController *)viewController;
|
||||
|
||||
/**
|
||||
This is a method to associate FBNativeAd with the UIView you will use to display the native ads
|
||||
and set clickable areas.
|
||||
|
||||
- Parameter view: The UIView you created to render all the native ads data elements.
|
||||
- Parameter viewController: The UIViewController that will be used to present SKStoreProductViewController
|
||||
(iTunes Store product information). If nil is passed, the top view controller currently shown will be used.
|
||||
- Parameter clickableViews: An array of UIView you created to render the native ads data element, e.g.
|
||||
CallToAction button, Icon image, which you want to specify as clickable.
|
||||
*/
|
||||
- (void)registerViewForInteraction:(UIView *)view
|
||||
withViewController:(nullable UIViewController *)viewController
|
||||
withClickableViews:(FB_NSArrayOf(UIView *)*)clickableViews;
|
||||
|
||||
/**
|
||||
This is a method to disconnect a FBNativeAd with the UIView you used to display the native ads.
|
||||
*/
|
||||
- (void)unregisterView;
|
||||
|
||||
/**
|
||||
Begins loading the FBNativeAd content.
|
||||
|
||||
You can implement `nativeAdDidLoad:` and `nativeAd:didFailWithError:` methods
|
||||
of `FBNativeAdDelegate` if you would like to be notified as loading succeeds or fails.
|
||||
*/
|
||||
- (void)loadAd;
|
||||
|
||||
/**
|
||||
Begins loading the FBNativeAd content from a bid payload attained through a server side bid.
|
||||
|
||||
- Parameter bidPayload: The payload of the ad bid. You can get your bid payload from Facebook bidder endpoint.
|
||||
*/
|
||||
- (void)loadAdWithBidPayload:(NSString *)bidPayload;
|
||||
|
||||
/**
|
||||
Call isAdValid to check whether native ad is valid & internal consistent prior rendering using its properties. If
|
||||
rendering is done as part of the loadAd callback, it is guarantee to be consistent
|
||||
*/
|
||||
@property (nonatomic, getter=isAdValid, readonly) BOOL adValid;
|
||||
|
||||
@property (nonatomic, copy, readonly, nullable, getter=getAdNetwork) NSString *adNetwork;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
The methods declared by the FBNativeAdDelegate protocol allow the adopting delegate to respond to messages
|
||||
from the FBNativeAd class and thus respond to operations such as whether the native ad has been loaded.
|
||||
*/
|
||||
@protocol FBNativeAdDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
Sent when an FBNativeAd has been successfully loaded.
|
||||
|
||||
- Parameter nativeAd: An FBNativeAd object sending the message.
|
||||
*/
|
||||
- (void)nativeAdDidLoad:(FBNativeAd *)nativeAd;
|
||||
|
||||
/**
|
||||
Sent immediately before the impression of an FBNativeAd object will be logged.
|
||||
|
||||
- Parameter nativeAd: An FBNativeAd object sending the message.
|
||||
*/
|
||||
- (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd;
|
||||
|
||||
/**
|
||||
Sent when an FBNativeAd is failed to load.
|
||||
|
||||
- Parameter nativeAd: An FBNativeAd object sending the message.
|
||||
- Parameter error: An error object containing details of the error.
|
||||
*/
|
||||
- (void)nativeAd:(FBNativeAd *)nativeAd didFailWithError:(NSError *)error;
|
||||
|
||||
/**
|
||||
Sent after an ad has been clicked by the person.
|
||||
|
||||
- Parameter nativeAd: An FBNativeAd object sending the message.
|
||||
*/
|
||||
- (void)nativeAdDidClick:(FBNativeAd *)nativeAd;
|
||||
|
||||
/**
|
||||
When an ad is clicked, the modal view will be presented. And when the user finishes the
|
||||
interaction with the modal view and dismiss it, this message will be sent, returning control
|
||||
to the application.
|
||||
|
||||
- Parameter nativeAd: An FBNativeAd object sending the message.
|
||||
*/
|
||||
- (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
Represents the Facebook ad star rating, which contains the rating value and rating scale.
|
||||
*/
|
||||
FB_EXPORT struct FBAdStarRating {
|
||||
/// The value of the star rating, X in X/5
|
||||
CGFloat value;
|
||||
/// The total possible star rating, Y in 4/Y
|
||||
NSInteger scale;
|
||||
} FBAdStarRating;
|
||||
|
||||
/**
|
||||
Represents an image creative.
|
||||
*/
|
||||
FB_CLASS_EXPORT
|
||||
@interface FBAdImage : NSObject
|
||||
|
||||
/**
|
||||
Typed access to the image url.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSURL *url;
|
||||
/**
|
||||
Typed access to the image width.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) NSInteger width;
|
||||
/**
|
||||
Typed access to the image height.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) NSInteger height;
|
||||
|
||||
/**
|
||||
This is a method to initialize an FBAdImage.
|
||||
|
||||
- Parameter url: the image url.
|
||||
- Parameter width: the image width.
|
||||
- Parameter height: the image height.
|
||||
*/
|
||||
- (instancetype)initWithURL:(NSURL *)url
|
||||
width:(NSInteger)width
|
||||
height:(NSInteger)height NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
Loads an image from self.url over the network, or returns the cached image immediately.
|
||||
|
||||
- Parameter block: Block to handle the loaded image.
|
||||
*/
|
||||
- (void)loadImageAsyncWithBlock:(nullable void (^)(UIImage * __nullable image))block;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
Helper view that draws a star rating based off a native ad.
|
||||
*/
|
||||
FB_CLASS_EXPORT FB_DEPRECATED
|
||||
@interface FBAdStarRatingView : UIView
|
||||
|
||||
/**
|
||||
The current rating from an FBNativeAd. When set, updates the view.
|
||||
*/
|
||||
@property (nonatomic, assign) struct FBAdStarRating rating FB_DEPRECATED;
|
||||
|
||||
/**
|
||||
The color drawn for filled-in stars. Defaults to yellow.
|
||||
*/
|
||||
@property (strong, nonatomic) UIColor *primaryColor FB_DEPRECATED;
|
||||
|
||||
/**
|
||||
The color drawn for empty stars. Defaults to gray.
|
||||
*/
|
||||
@property (strong, nonatomic) UIColor *secondaryColor FB_DEPRECATED;
|
||||
|
||||
/**
|
||||
Initializes a star rating view with a given frame and star rating.
|
||||
|
||||
- Parameter frame: Frame of this view.
|
||||
- Parameter starRating: Star rating from a native ad.
|
||||
*/
|
||||
- (instancetype)initWithFrame:(CGRect)frame withStarRating:(struct FBAdStarRating)starRating NS_DESIGNATED_INITIALIZER FB_DEPRECATED;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,136 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <FBAudienceNetwork/FBAdDefines.h>
|
||||
#import <FBAudienceNetwork/FBNativeAd.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FBNativeAdViewAttributes;
|
||||
|
||||
/**
|
||||
Determines the type of native ad template. Different views are created
|
||||
for different values of FBNativeAdViewType
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, FBNativeAdViewType) {
|
||||
/// Fixed height view, 100 points (banner equivalent)
|
||||
FBNativeAdViewTypeGenericHeight100 = 1,
|
||||
/// Fixed height view, 120 points (banner equivalent)
|
||||
FBNativeAdViewTypeGenericHeight120,
|
||||
/// Fixed height view, 300 points
|
||||
FBNativeAdViewTypeGenericHeight300,
|
||||
/// Fixed height view, 400 points
|
||||
FBNativeAdViewTypeGenericHeight400,
|
||||
};
|
||||
|
||||
/**
|
||||
The FBNativeAdView creates prebuilt native ad template views and manages native ads.
|
||||
*/
|
||||
FB_CLASS_EXPORT
|
||||
@interface FBNativeAdView : UIView
|
||||
|
||||
/**
|
||||
The type of the view, specifies which template to use
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) FBNativeAdViewType type;
|
||||
|
||||
/**
|
||||
This is a method to create a native ad template using the given placement id and type.
|
||||
- Parameter nativeAd: The native ad to use to create this view.
|
||||
- Parameter type: The type of this native ad template. For more information, consult FBNativeAdViewType.
|
||||
*/
|
||||
+ (instancetype)nativeAdViewWithNativeAd:(FBNativeAd *)nativeAd withType:(FBNativeAdViewType)type;
|
||||
|
||||
/**
|
||||
A view controller that is used to present modal content. If nil, the view searches for a view controller.
|
||||
*/
|
||||
@property (nonatomic, weak, nullable) UIViewController *rootViewController;
|
||||
|
||||
/**
|
||||
This is a method to create a native ad template using the given placement id and type.
|
||||
- Parameter nativeAd: The native ad to use to create this view.
|
||||
- Parameter type: The type of this native ad template. For more information, consult FBNativeAdViewType.
|
||||
- Parameter attributes: The attributes to render this native ad template with.
|
||||
*/
|
||||
+ (instancetype)nativeAdViewWithNativeAd:(FBNativeAd *)nativeAd withType:(FBNativeAdViewType)type withAttributes:(FBNativeAdViewAttributes *)attributes;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
Describes the look and feel of a native ad view.
|
||||
*/
|
||||
@interface FBNativeAdViewAttributes : NSObject <NSCopying>
|
||||
|
||||
/**
|
||||
This is a method to create native ad view attributes with a dictionary
|
||||
*/
|
||||
- (instancetype)initWithDictionary:(NSDictionary *) dict NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
Background color of the native ad view.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *backgroundColor;
|
||||
/**
|
||||
Color of the title label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *titleColor;
|
||||
/**
|
||||
Font of the title label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIFont *titleFont;
|
||||
/**
|
||||
Color of the description label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *descriptionColor;
|
||||
/**
|
||||
Font of the description label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIFont *descriptionFont;
|
||||
/**
|
||||
Background color of the call to action button.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *buttonColor;
|
||||
/**
|
||||
Color of the call to action button's title label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *buttonTitleColor;
|
||||
/**
|
||||
Font of the call to action button's title label.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIFont *buttonTitleFont;
|
||||
/**
|
||||
Border color of the call to action button. If nil, no border is shown.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) UIColor *buttonBorderColor;
|
||||
/**
|
||||
Enables or disables autoplay for some types of media. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, assign, getter=isAutoplayEnabled) BOOL autoplayEnabled;
|
||||
|
||||
/**
|
||||
Returns default attributes for a given type.
|
||||
|
||||
- Parameter type: The type for this layout.
|
||||
*/
|
||||
+ (instancetype)defaultAttributesForType:(FBNativeAdViewType)type;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
Binary file not shown.
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// MPBannerCustomEvent+Internal.h
|
||||
// MoPubSampleApp
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPBannerCustomEvent.h"
|
||||
|
||||
@interface MPBannerCustomEvent (Internal)
|
||||
|
||||
/**
|
||||
* Track marketplace and 3rd party impressions.
|
||||
* Extended class implements this method if necessary.
|
||||
* Currently, only HTML and MRAID banners contain MPX and 3rd party trackers.
|
||||
* Mediated networks don't contain MPX and 3rd party trackers.
|
||||
*/
|
||||
|
||||
- (void)trackMPXAndThirdPartyImpressions;
|
||||
|
||||
/**
|
||||
* Start viewability tracker. The default implementation of this method does nothing.
|
||||
* Subclasses can override this method if necessary.
|
||||
*/
|
||||
- (void)startViewabilityTracker;
|
||||
|
||||
@end
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// MPAdAlertGestureRecognizer.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
extern NSInteger const kMPAdAlertGestureMaxAllowedYAxisMovement;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MPAdAlertGestureRecognizerState_ZigRight1,
|
||||
MPAdAlertGestureRecognizerState_ZagLeft2,
|
||||
MPAdAlertGestureRecognizerState_Recognized
|
||||
} MPAdAlertGestureRecognizerState;
|
||||
|
||||
@interface MPAdAlertGestureRecognizer : UIGestureRecognizer
|
||||
|
||||
// default is 4
|
||||
@property (nonatomic, assign) NSInteger numZigZagsForRecognition;
|
||||
|
||||
// default is 100
|
||||
@property (nonatomic, assign) CGFloat minTrackedDistanceForZigZag;
|
||||
|
||||
@property (nonatomic, readonly) MPAdAlertGestureRecognizerState currentAlertGestureState;
|
||||
@property (nonatomic, readonly) CGPoint inflectionPoint;
|
||||
@property (nonatomic, readonly) BOOL thresholdReached;
|
||||
@property (nonatomic, readonly) NSInteger curNumZigZags;
|
||||
|
||||
@end
|
|
@ -1,43 +0,0 @@
|
|||
//
|
||||
// MPAPIEndpoints.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAPIEndpoints.h"
|
||||
#import "MPConstants.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
|
||||
@implementation MPAPIEndpoints
|
||||
|
||||
static BOOL sUsesHTTPS = YES;
|
||||
|
||||
+ (void)setUsesHTTPS:(BOOL)usesHTTPS
|
||||
{
|
||||
sUsesHTTPS = usesHTTPS;
|
||||
}
|
||||
|
||||
+ (NSString *)baseURL
|
||||
{
|
||||
if ([[MPCoreInstanceProvider sharedProvider] appTransportSecuritySettings] == MPATSSettingEnabled) {
|
||||
return [@"https://" stringByAppendingString:MOPUB_BASE_HOSTNAME];
|
||||
}
|
||||
|
||||
return [@"http://" stringByAppendingString:MOPUB_BASE_HOSTNAME];
|
||||
}
|
||||
|
||||
+ (NSString *)baseURLScheme
|
||||
{
|
||||
return sUsesHTTPS ? @"https://" : @"http://";
|
||||
}
|
||||
|
||||
+ (NSString *)baseURLStringWithPath:(NSString *)path
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@%@%@",
|
||||
[[self class] baseURLScheme],
|
||||
MOPUB_BASE_HOSTNAME,
|
||||
path];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,65 +0,0 @@
|
|||
//
|
||||
// MPAdBrowserController.h
|
||||
// MoPub
|
||||
//
|
||||
// Created by Nafis Jamal on 1/19/11.
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPWebView.h"
|
||||
|
||||
#ifndef CF_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#else
|
||||
#define CF_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@class MPAdConfiguration;
|
||||
|
||||
@protocol MPAdBrowserControllerDelegate;
|
||||
|
||||
@interface MPAdBrowserController : UIViewController <MPWebViewDelegate, UIActionSheetDelegate>
|
||||
|
||||
@property (nonatomic, strong) IBOutlet MPWebView *webView;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *backButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *forwardButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *refreshButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *safariButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *spinnerItem;
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *spinner;
|
||||
|
||||
@property (nonatomic, weak) id<MPAdBrowserControllerDelegate> delegate;
|
||||
@property (nonatomic, copy) NSURL *URL;
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL HTMLString:(NSString *)HTMLString delegate:(id<MPAdBrowserControllerDelegate>)delegate;
|
||||
- (instancetype)initWithURL:(NSURL *)URL delegate:(id<MPAdBrowserControllerDelegate>)delegate;
|
||||
|
||||
// Navigation methods.
|
||||
- (IBAction)back;
|
||||
- (IBAction)forward;
|
||||
- (IBAction)refresh;
|
||||
- (IBAction)safari;
|
||||
- (IBAction)done;
|
||||
|
||||
// Drawing methods.
|
||||
- (CGContextRef)createContext CF_RETURNS_RETAINED;
|
||||
- (UIImage *)backArrowImage;
|
||||
- (UIImage *)forwardArrowImage;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol MPAdBrowserControllerDelegate <NSObject>
|
||||
|
||||
- (void)dismissBrowserController:(MPAdBrowserController *)browserController animated:(BOOL)animated;
|
||||
|
||||
@optional
|
||||
|
||||
- (MPAdConfiguration *)adConfiguration;
|
||||
|
||||
@end
|
|
@ -1,345 +0,0 @@
|
|||
//
|
||||
// MPAdBrowserController.m
|
||||
// MoPub
|
||||
//
|
||||
// Created by Nafis Jamal on 1/19/11.
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdBrowserController.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPAdConfiguration.h"
|
||||
#import "MPAPIEndpoints.h"
|
||||
#import "NSBundle+MPAdditions.h"
|
||||
#import "MPURLRequest.h"
|
||||
|
||||
static NSString * const kAdBrowserControllerNibName = @"MPAdBrowserController";
|
||||
|
||||
@interface MPAdBrowserController ()
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UINavigationBar *navigationBar;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *navigationBarYConstraint;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIToolbar *browserControlToolbar;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *browserControlToolbarBottomConstraint;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *webViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *webViewLeadingConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *webViewTrailingConstraint;
|
||||
|
||||
@property (nonatomic, strong) UIActionSheet *actionSheet;
|
||||
@property (nonatomic, strong) NSString *HTMLString;
|
||||
@property (nonatomic, assign) int webViewLoadCount;
|
||||
|
||||
- (void)dismissActionSheet;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdBrowserController
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Lifecycle
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL HTMLString:(NSString *)HTMLString delegate:(id<MPAdBrowserControllerDelegate>)delegate
|
||||
{
|
||||
if (self = [super initWithNibName:kAdBrowserControllerNibName bundle:[NSBundle resourceBundleForClass:self.class]])
|
||||
{
|
||||
self.delegate = delegate;
|
||||
self.URL = URL;
|
||||
self.HTMLString = HTMLString;
|
||||
|
||||
MPLogDebug(@"Ad browser (%p) initialized with URL: %@", self, self.URL);
|
||||
|
||||
self.spinner = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
|
||||
[self.spinner sizeToFit];
|
||||
self.spinner.hidesWhenStopped = YES;
|
||||
|
||||
self.webViewLoadCount = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL delegate:(id<MPAdBrowserControllerDelegate>)delegate {
|
||||
return [self initWithURL:URL
|
||||
HTMLString:nil
|
||||
delegate:delegate];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
self.webView.delegate = nil;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
// Set web view delegate
|
||||
self.webView.delegate = self;
|
||||
self.webView.scalesPageToFit = YES;
|
||||
|
||||
// Set up toolbar buttons
|
||||
self.backButton.image = [self backArrowImage];
|
||||
self.backButton.title = nil;
|
||||
self.forwardButton.image = [self forwardArrowImage];
|
||||
self.forwardButton.title = nil;
|
||||
self.spinnerItem.customView = self.spinner;
|
||||
self.spinnerItem.title = nil;
|
||||
|
||||
// If iOS 11, set up autolayout constraints so that the toolbar and web view stay within the safe area
|
||||
// Note: The web view has to be constrained to the safe area on top for the notch in Portait and leading/trailing
|
||||
// for the notch in Landscape. Only the bottom of the toolbar needs to be constrained because Apple will move
|
||||
// the buttons into the safe area automatically in Landscape, and otherwise it's preferable for the toolbar to
|
||||
// stretch the length of the unsafe area as well.
|
||||
if (@available(iOS 11, *)) {
|
||||
// Disable the old constraints
|
||||
self.navigationBarYConstraint.active = NO;
|
||||
self.browserControlToolbarBottomConstraint.active = NO;
|
||||
self.webViewTopConstraint.active = NO;
|
||||
self.webViewLeadingConstraint.active = NO;
|
||||
self.webViewTrailingConstraint.active = NO;
|
||||
|
||||
// Set new constraints based on the safe area layout guide
|
||||
self.navigationBarYConstraint = [self.navigationBar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor]; // put nav bar just above safe area
|
||||
self.browserControlToolbarBottomConstraint = [self.browserControlToolbar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor];
|
||||
self.webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor];
|
||||
self.webViewLeadingConstraint = [self.webView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor];
|
||||
self.webViewTrailingConstraint = [self.webView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor];
|
||||
|
||||
// Enable the new constraints
|
||||
[NSLayoutConstraint activateConstraints:@[
|
||||
self.navigationBarYConstraint,
|
||||
self.browserControlToolbarBottomConstraint,
|
||||
self.webViewTopConstraint,
|
||||
self.webViewLeadingConstraint,
|
||||
self.webViewTrailingConstraint,
|
||||
]];
|
||||
}
|
||||
|
||||
// Set web view background color to white so scrolling at extremes won't have a gray background
|
||||
self.webView.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Set button enabled status.
|
||||
self.backButton.enabled = self.webView.canGoBack;
|
||||
self.forwardButton.enabled = self.webView.canGoForward;
|
||||
self.refreshButton.enabled = NO;
|
||||
self.safariButton.enabled = NO;
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
NSURL *baseURL = (self.URL != nil) ? self.URL : [NSURL URLWithString:[MPAPIEndpoints baseURL]];
|
||||
|
||||
if (self.HTMLString) {
|
||||
[self.webView loadHTMLString:self.HTMLString baseURL:baseURL];
|
||||
} else {
|
||||
[self.webView loadRequest:[MPURLRequest requestWithURL:self.URL]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[self.webView stopLoading];
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Hidding status bar (iOS 7 and above)
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Navigation
|
||||
|
||||
- (IBAction)refresh
|
||||
{
|
||||
[self dismissActionSheet];
|
||||
[self.webView reload];
|
||||
}
|
||||
|
||||
- (IBAction)done
|
||||
{
|
||||
[self dismissActionSheet];
|
||||
if (self.delegate) {
|
||||
[self.delegate dismissBrowserController:self animated:MP_ANIMATED];
|
||||
} else {
|
||||
[self dismissViewControllerAnimated:MP_ANIMATED completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)back
|
||||
{
|
||||
[self dismissActionSheet];
|
||||
[self.webView goBack];
|
||||
self.backButton.enabled = self.webView.canGoBack;
|
||||
self.forwardButton.enabled = self.webView.canGoForward;
|
||||
}
|
||||
|
||||
- (IBAction)forward
|
||||
{
|
||||
[self dismissActionSheet];
|
||||
[self.webView goForward];
|
||||
self.backButton.enabled = self.webView.canGoBack;
|
||||
self.forwardButton.enabled = self.webView.canGoForward;
|
||||
}
|
||||
|
||||
- (IBAction)safari
|
||||
{
|
||||
if (self.actionSheet) {
|
||||
[self dismissActionSheet];
|
||||
} else {
|
||||
self.actionSheet = [[UIActionSheet alloc] initWithTitle:nil
|
||||
delegate:self
|
||||
cancelButtonTitle:@"Cancel"
|
||||
destructiveButtonTitle:nil
|
||||
otherButtonTitles:@"Open in Safari", nil];
|
||||
|
||||
if ([UIActionSheet instancesRespondToSelector:@selector(showFromBarButtonItem:animated:)]) {
|
||||
[self.actionSheet showFromBarButtonItem:self.safariButton animated:YES];
|
||||
} else {
|
||||
[self.actionSheet showInView:self.webView];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissActionSheet
|
||||
{
|
||||
[self.actionSheet dismissWithClickedButtonIndex:0 animated:YES];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark UIActionSheetDelegate
|
||||
|
||||
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
self.actionSheet = nil;
|
||||
if (buttonIndex == 0) {
|
||||
// Open in Safari.
|
||||
[[UIApplication sharedApplication] openURL:self.URL];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MPWebViewDelegate
|
||||
|
||||
- (BOOL)webView:(MPWebView *)webView
|
||||
shouldStartLoadWithRequest:(NSURLRequest *)request
|
||||
navigationType:(UIWebViewNavigationType)navigationType
|
||||
{
|
||||
MPLogDebug(@"Ad browser (%p) starting to load URL: %@", self, request.URL);
|
||||
self.URL = request.URL;
|
||||
|
||||
BOOL appShouldOpenURL = ![self.URL.scheme isEqualToString:@"http"] && ![self.URL.scheme isEqualToString:@"https"];
|
||||
|
||||
if (appShouldOpenURL) {
|
||||
[[UIApplication sharedApplication] openURL:self.URL];
|
||||
}
|
||||
|
||||
return !appShouldOpenURL;
|
||||
}
|
||||
|
||||
- (void)webViewDidStartLoad:(MPWebView *)webView
|
||||
{
|
||||
self.refreshButton.enabled = YES;
|
||||
self.safariButton.enabled = YES;
|
||||
[self.spinner startAnimating];
|
||||
|
||||
self.webViewLoadCount++;
|
||||
}
|
||||
|
||||
- (void)webViewDidFinishLoad:(MPWebView *)webView
|
||||
{
|
||||
self.webViewLoadCount--;
|
||||
if (self.webViewLoadCount > 0) return;
|
||||
|
||||
self.refreshButton.enabled = YES;
|
||||
self.safariButton.enabled = YES;
|
||||
self.backButton.enabled = self.webView.canGoBack;
|
||||
self.forwardButton.enabled = self.webView.canGoForward;
|
||||
[self.spinner stopAnimating];
|
||||
}
|
||||
|
||||
- (void)webView:(MPWebView *)webView didFailLoadWithError:(NSError *)error
|
||||
{
|
||||
self.webViewLoadCount--;
|
||||
|
||||
self.refreshButton.enabled = YES;
|
||||
self.safariButton.enabled = YES;
|
||||
self.backButton.enabled = self.webView.canGoBack;
|
||||
self.forwardButton.enabled = self.webView.canGoForward;
|
||||
[self.spinner stopAnimating];
|
||||
|
||||
// Ignore NSURLErrorDomain error (-999).
|
||||
if (error.code == NSURLErrorCancelled) return;
|
||||
|
||||
// Ignore "Frame Load Interrupted" errors after navigating to iTunes or the App Store.
|
||||
if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return;
|
||||
|
||||
MPLogError(@"Ad browser (%p) experienced an error: %@.", self, [error localizedDescription]);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Drawing
|
||||
|
||||
- (CGContextRef)createContext
|
||||
{
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef context = CGBitmapContextCreate(nil,27,27,8,0,
|
||||
colorSpace,(CGBitmapInfo)kCGImageAlphaPremultipliedLast);
|
||||
CFRelease(colorSpace);
|
||||
return context;
|
||||
}
|
||||
|
||||
- (UIImage *)backArrowImage
|
||||
{
|
||||
CGContextRef context = [self createContext];
|
||||
CGColorRef fillColor = [[UIColor blackColor] CGColor];
|
||||
CGContextSetFillColor(context, CGColorGetComponents(fillColor));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 8.0f, 13.0f);
|
||||
CGContextAddLineToPoint(context, 24.0f, 4.0f);
|
||||
CGContextAddLineToPoint(context, 24.0f, 22.0f);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
|
||||
CGImageRef imageRef = CGBitmapContextCreateImage(context);
|
||||
CGContextRelease(context);
|
||||
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
|
||||
CGImageRelease(imageRef);
|
||||
return image;
|
||||
}
|
||||
|
||||
- (UIImage *)forwardArrowImage
|
||||
{
|
||||
CGContextRef context = [self createContext];
|
||||
CGColorRef fillColor = [[UIColor blackColor] CGColor];
|
||||
CGContextSetFillColor(context, CGColorGetComponents(fillColor));
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 24.0f, 13.0f);
|
||||
CGContextAddLineToPoint(context, 8.0f, 4.0f);
|
||||
CGContextAddLineToPoint(context, 8.0f, 22.0f);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
|
||||
CGImageRef imageRef = CGBitmapContextCreateImage(context);
|
||||
CGContextRelease(context);
|
||||
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
|
||||
CGImageRelease(imageRef);
|
||||
return image;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,97 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13528" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<device id="retina3_5" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13526"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MPAdBrowserController">
|
||||
<connections>
|
||||
<outlet property="backButton" destination="8" id="17"/>
|
||||
<outlet property="browserControlToolbar" destination="5" id="K2j-U0-ZFa"/>
|
||||
<outlet property="browserControlToolbarBottomConstraint" destination="Sny-Vh-INp" id="ZmT-wG-KYK"/>
|
||||
<outlet property="doneButton" destination="6" id="18"/>
|
||||
<outlet property="forwardButton" destination="9" id="19"/>
|
||||
<outlet property="navigationBar" destination="4XW-fj-Oyl" id="oxx-Y5-NCm"/>
|
||||
<outlet property="navigationBarYConstraint" destination="Fqe-Oc-jVO" id="jxz-eh-ONa"/>
|
||||
<outlet property="refreshButton" destination="11" id="20"/>
|
||||
<outlet property="safariButton" destination="13" id="31"/>
|
||||
<outlet property="spinnerItem" destination="15" id="21"/>
|
||||
<outlet property="view" destination="1" id="3"/>
|
||||
<outlet property="webView" destination="UGP-YN-zIO" id="Vc0-UI-9RP"/>
|
||||
<outlet property="webViewLeadingConstraint" destination="SXG-tP-bmi" id="lcX-PL-FM4"/>
|
||||
<outlet property="webViewTopConstraint" destination="4ZE-ez-bSu" id="0Sx-rE-Wnb"/>
|
||||
<outlet property="webViewTrailingConstraint" destination="Vfx-V2-bsa" id="rCO-B1-yBB"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<navigationBar contentMode="scaleToFill" barStyle="blackTranslucent" translatesAutoresizingMaskIntoConstraints="NO" id="4XW-fj-Oyl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
</navigationBar>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UGP-YN-zIO" customClass="MPWebView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="416"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="blackTranslucent" translatesAutoresizingMaskIntoConstraints="NO" id="5">
|
||||
<rect key="frame" x="0.0" y="416" width="320" height="44"/>
|
||||
<items>
|
||||
<barButtonItem title="B" style="plain" id="8">
|
||||
<connections>
|
||||
<action selector="back" destination="-1" id="24"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem style="plain" systemItem="flexibleSpace" id="10"/>
|
||||
<barButtonItem title="F" style="plain" id="9">
|
||||
<connections>
|
||||
<action selector="forward" destination="-1" id="25"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem style="plain" systemItem="flexibleSpace" id="12"/>
|
||||
<barButtonItem style="plain" systemItem="refresh" id="11">
|
||||
<connections>
|
||||
<action selector="refresh" destination="-1" id="26"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem style="plain" systemItem="flexibleSpace" id="14"/>
|
||||
<barButtonItem style="plain" systemItem="action" id="13">
|
||||
<connections>
|
||||
<action selector="safari" destination="-1" id="28"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem style="plain" systemItem="flexibleSpace" id="16"/>
|
||||
<barButtonItem title="S" style="plain" id="15"/>
|
||||
<barButtonItem style="plain" systemItem="flexibleSpace" id="7"/>
|
||||
<barButtonItem style="done" systemItem="done" id="6">
|
||||
<connections>
|
||||
<action selector="done" destination="-1" id="29"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</items>
|
||||
</toolbar>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="4XW-fj-Oyl" secondAttribute="trailing" id="43a-P8-pNp"/>
|
||||
<constraint firstItem="UGP-YN-zIO" firstAttribute="top" secondItem="1" secondAttribute="top" id="4ZE-ez-bSu"/>
|
||||
<constraint firstItem="5" firstAttribute="top" secondItem="UGP-YN-zIO" secondAttribute="bottom" id="CVu-bs-DxZ"/>
|
||||
<constraint firstItem="4XW-fj-Oyl" firstAttribute="top" secondItem="1" secondAttribute="top" id="Fqe-Oc-jVO"/>
|
||||
<constraint firstItem="UGP-YN-zIO" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="SXG-tP-bmi"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5" secondAttribute="bottom" id="Sny-Vh-INp"/>
|
||||
<constraint firstAttribute="trailing" secondItem="UGP-YN-zIO" secondAttribute="trailing" id="Vfx-V2-bsa"/>
|
||||
<constraint firstItem="4XW-fj-Oyl" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="ZMd-xu-AMu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="5" secondAttribute="trailing" id="g7P-9K-6K4"/>
|
||||
<constraint firstItem="5" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="nKl-Xt-tgS"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
// MPAdConfiguration.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPGlobal.h"
|
||||
|
||||
@class MPRewardedVideoReward;
|
||||
|
||||
enum {
|
||||
MPAdTypeUnknown = -1,
|
||||
MPAdTypeBanner = 0,
|
||||
MPAdTypeInterstitial = 1
|
||||
};
|
||||
typedef NSUInteger MPAdType;
|
||||
|
||||
extern NSString * const kAdTypeHeaderKey;
|
||||
extern NSString * const kAdUnitWarmingUpHeaderKey;
|
||||
extern NSString * const kClickthroughHeaderKey;
|
||||
extern NSString * const kCreativeIdHeaderKey;
|
||||
extern NSString * const kCustomSelectorHeaderKey;
|
||||
extern NSString * const kCustomEventClassNameHeaderKey;
|
||||
extern NSString * const kCustomEventClassDataHeaderKey;
|
||||
extern NSString * const kFailUrlHeaderKey;
|
||||
extern NSString * const kHeightHeaderKey;
|
||||
extern NSString * const kImpressionTrackerHeaderKey;
|
||||
extern NSString * const kLaunchpageHeaderKey;
|
||||
extern NSString * const kNativeSDKParametersHeaderKey;
|
||||
extern NSString * const kNetworkTypeHeaderKey;
|
||||
extern NSString * const kRefreshTimeHeaderKey;
|
||||
extern NSString * const kAdTimeoutHeaderKey;
|
||||
extern NSString * const kScrollableHeaderKey;
|
||||
extern NSString * const kWidthHeaderKey;
|
||||
extern NSString * const kDspCreativeIdKey;
|
||||
extern NSString * const kPrecacheRequiredKey;
|
||||
extern NSString * const kIsVastVideoPlayerKey;
|
||||
extern NSString * const kRewardedVideoCurrencyNameHeaderKey;
|
||||
extern NSString * const kRewardedVideoCurrencyAmountHeaderKey;
|
||||
extern NSString * const kRewardedVideoCompletionUrlHeaderKey;
|
||||
extern NSString * const kRewardedCurrenciesHeaderKey;
|
||||
extern NSString * const kRewardedPlayableDurationHeaderKey;
|
||||
extern NSString * const kRewardedPlayableRewardOnClickHeaderKey;
|
||||
|
||||
extern NSString * const kInterstitialAdTypeHeaderKey;
|
||||
extern NSString * const kOrientationTypeHeaderKey;
|
||||
|
||||
extern NSString * const kAdTypeHtml;
|
||||
extern NSString * const kAdTypeInterstitial;
|
||||
extern NSString * const kAdTypeMraid;
|
||||
extern NSString * const kAdTypeClear;
|
||||
extern NSString * const kAdTypeNative;
|
||||
extern NSString * const kAdTypeNativeVideo;
|
||||
|
||||
extern NSString * const kClickthroughExperimentBrowserAgent;
|
||||
|
||||
extern NSString * const kViewabilityDisableHeaderKey;
|
||||
|
||||
extern NSString * const kBannerImpressionVisableMsHeaderKey;
|
||||
extern NSString * const kBannerImpressionMinPixelHeaderKey;
|
||||
|
||||
@interface MPAdConfiguration : NSObject
|
||||
|
||||
@property (nonatomic, assign) MPAdType adType;
|
||||
@property (nonatomic, assign) BOOL adUnitWarmingUp;
|
||||
@property (nonatomic, copy) NSString *networkType;
|
||||
@property (nonatomic, assign) CGSize preferredSize;
|
||||
@property (nonatomic, strong) NSURL *clickTrackingURL;
|
||||
@property (nonatomic, strong) NSURL *impressionTrackingURL;
|
||||
@property (nonatomic, strong) NSURL *failoverURL;
|
||||
@property (nonatomic, strong) NSURL *interceptURLPrefix;
|
||||
@property (nonatomic, assign) BOOL scrollable;
|
||||
@property (nonatomic, assign) NSTimeInterval refreshInterval;
|
||||
@property (nonatomic, assign) NSTimeInterval adTimeoutInterval;
|
||||
@property (nonatomic, copy) NSData *adResponseData;
|
||||
@property (nonatomic, strong) NSDictionary *nativeSDKParameters;
|
||||
@property (nonatomic, copy) NSString *customSelectorName;
|
||||
@property (nonatomic, assign) Class customEventClass;
|
||||
@property (nonatomic, strong) NSDictionary *customEventClassData;
|
||||
@property (nonatomic, assign) MPInterstitialOrientationType orientationType;
|
||||
@property (nonatomic, copy) NSString *dspCreativeId;
|
||||
@property (nonatomic, assign) BOOL precacheRequired;
|
||||
@property (nonatomic, assign) BOOL isVastVideoPlayer;
|
||||
@property (nonatomic, strong) NSDate *creationTimestamp;
|
||||
@property (nonatomic, copy) NSString *creativeId;
|
||||
@property (nonatomic, copy) NSString *headerAdType;
|
||||
@property (nonatomic, assign) NSInteger nativeVideoPlayVisiblePercent;
|
||||
@property (nonatomic, assign) NSInteger nativeVideoPauseVisiblePercent;
|
||||
@property (nonatomic, assign) CGFloat nativeImpressionMinVisiblePixels;
|
||||
@property (nonatomic, assign) NSInteger nativeImpressionMinVisiblePercent; // The pixels header takes priority over percentage, but percentage is left for backwards compatibility
|
||||
@property (nonatomic, assign) NSTimeInterval nativeImpressionMinVisibleTimeInterval;
|
||||
@property (nonatomic, assign) NSTimeInterval nativeVideoMaxBufferingTime;
|
||||
@property (nonatomic) NSDictionary *nativeVideoTrackers;
|
||||
@property (nonatomic, readonly) NSArray *availableRewards;
|
||||
@property (nonatomic, strong) MPRewardedVideoReward *selectedReward;
|
||||
@property (nonatomic, copy) NSString *rewardedVideoCompletionUrl;
|
||||
@property (nonatomic, assign) NSTimeInterval rewardedPlayableDuration;
|
||||
@property (nonatomic, assign) BOOL rewardedPlayableShouldRewardOnClick;
|
||||
@property (nonatomic, copy) NSString *advancedBidPayload;
|
||||
|
||||
|
||||
// viewable impression tracking experiment
|
||||
@property (nonatomic) NSTimeInterval impressionMinVisibleTimeInSec;
|
||||
@property (nonatomic) CGFloat impressionMinVisiblePixels;
|
||||
@property (nonatomic) BOOL visibleImpressionTrackingEnabled;
|
||||
|
||||
- (id)initWithHeaders:(NSDictionary *)headers data:(NSData *)data;
|
||||
|
||||
- (BOOL)hasPreferredSize;
|
||||
- (NSString *)adResponseHTMLString;
|
||||
- (NSString *)clickDetectionURLPrefix;
|
||||
|
||||
@end
|
|
@ -1,530 +0,0 @@
|
|||
//
|
||||
// MPAdConfiguration.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdConfiguration.h"
|
||||
|
||||
#import "MOPUBExperimentProvider.h"
|
||||
#import "MPConsentAdServerKeys.h"
|
||||
#import "MPConsentManager.h"
|
||||
#import "MPConstants.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPRewardedVideoReward.h"
|
||||
#import "MPViewabilityTracker.h"
|
||||
#import "NSJSONSerialization+MPAdditions.h"
|
||||
#import "NSString+MPAdditions.h"
|
||||
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
#import "MPVASTTrackingEvent.h"
|
||||
#endif
|
||||
|
||||
NSString * const kAdTypeHeaderKey = @"X-Adtype";
|
||||
NSString * const kAdUnitWarmingUpHeaderKey = @"X-Warmup";
|
||||
NSString * const kClickthroughHeaderKey = @"X-Clickthrough";
|
||||
NSString * const kCreativeIdHeaderKey = @"X-CreativeId";
|
||||
NSString * const kCustomSelectorHeaderKey = @"X-Customselector";
|
||||
NSString * const kCustomEventClassNameHeaderKey = @"X-Custom-Event-Class-Name";
|
||||
NSString * const kCustomEventClassDataHeaderKey = @"X-Custom-Event-Class-Data";
|
||||
NSString * const kFailUrlHeaderKey = @"X-Failurl";
|
||||
NSString * const kHeightHeaderKey = @"X-Height";
|
||||
NSString * const kImpressionTrackerHeaderKey = @"X-Imptracker";
|
||||
NSString * const kLaunchpageHeaderKey = @"X-Launchpage";
|
||||
NSString * const kNativeSDKParametersHeaderKey = @"X-Nativeparams";
|
||||
NSString * const kNetworkTypeHeaderKey = @"X-Networktype";
|
||||
NSString * const kRefreshTimeHeaderKey = @"X-Refreshtime";
|
||||
NSString * const kAdTimeoutHeaderKey = @"X-AdTimeout";
|
||||
NSString * const kScrollableHeaderKey = @"X-Scrollable";
|
||||
NSString * const kWidthHeaderKey = @"X-Width";
|
||||
NSString * const kDspCreativeIdKey = @"X-DspCreativeid";
|
||||
NSString * const kPrecacheRequiredKey = @"X-PrecacheRequired";
|
||||
NSString * const kIsVastVideoPlayerKey = @"X-VastVideoPlayer";
|
||||
|
||||
NSString * const kInterstitialAdTypeHeaderKey = @"X-Fulladtype";
|
||||
NSString * const kOrientationTypeHeaderKey = @"X-Orientation";
|
||||
|
||||
NSString * const kNativeImpressionMinVisiblePixelsHeaderKey = @"X-Native-Impression-Min-Px"; // The pixels header takes priority over percentage, but percentage is left for backwards compatibility
|
||||
NSString * const kNativeImpressionMinVisiblePercentHeaderKey = @"X-Impression-Min-Visible-Percent";
|
||||
NSString * const kNativeImpressionVisibleMsHeaderKey = @"X-Impression-Visible-Ms";
|
||||
NSString * const kNativeVideoPlayVisiblePercentHeaderKey = @"X-Play-Visible-Percent";
|
||||
NSString * const kNativeVideoPauseVisiblePercentHeaderKey = @"X-Pause-Visible-Percent";
|
||||
NSString * const kNativeVideoMaxBufferingTimeMsHeaderKey = @"X-Max-Buffer-Ms";
|
||||
NSString * const kNativeVideoTrackersHeaderKey = @"X-Video-Trackers";
|
||||
|
||||
NSString * const kBannerImpressionVisableMsHeaderKey = @"X-Banner-Impression-Min-Ms";
|
||||
NSString * const kBannerImpressionMinPixelHeaderKey = @"X-Banner-Impression-Min-Pixels";
|
||||
|
||||
NSString * const kAdTypeHtml = @"html";
|
||||
NSString * const kAdTypeInterstitial = @"interstitial";
|
||||
NSString * const kAdTypeMraid = @"mraid";
|
||||
NSString * const kAdTypeClear = @"clear";
|
||||
NSString * const kAdTypeNative = @"json";
|
||||
NSString * const kAdTypeNativeVideo = @"json_video";
|
||||
|
||||
// rewarded video
|
||||
NSString * const kRewardedVideoCurrencyNameHeaderKey = @"X-Rewarded-Video-Currency-Name";
|
||||
NSString * const kRewardedVideoCurrencyAmountHeaderKey = @"X-Rewarded-Video-Currency-Amount";
|
||||
NSString * const kRewardedVideoCompletionUrlHeaderKey = @"X-Rewarded-Video-Completion-Url";
|
||||
NSString * const kRewardedCurrenciesHeaderKey = @"X-Rewarded-Currencies";
|
||||
|
||||
// rewarded playables
|
||||
NSString * const kRewardedPlayableDurationHeaderKey = @"X-Rewarded-Duration";
|
||||
NSString * const kRewardedPlayableRewardOnClickHeaderKey = @"X-Should-Reward-On-Click";
|
||||
|
||||
// native video
|
||||
NSString * const kNativeVideoTrackerUrlMacro = @"%%VIDEO_EVENT%%";
|
||||
NSString * const kNativeVideoTrackerEventsHeaderKey = @"events";
|
||||
NSString * const kNativeVideoTrackerUrlsHeaderKey = @"urls";
|
||||
NSString * const kNativeVideoTrackerEventDictionaryKey = @"event";
|
||||
NSString * const kNativeVideoTrackerTextDictionaryKey = @"text";
|
||||
|
||||
// clickthrough experiment
|
||||
NSString * const kClickthroughExperimentBrowserAgent = @"X-Browser-Agent";
|
||||
static const NSInteger kMaximumVariantForClickthroughExperiment = 2;
|
||||
|
||||
// viewability
|
||||
NSString * const kViewabilityDisableHeaderKey = @"X-Disable-Viewability";
|
||||
|
||||
|
||||
@interface MPAdConfiguration ()
|
||||
|
||||
@property (nonatomic, copy) NSString *adResponseHTMLString;
|
||||
@property (nonatomic, strong, readwrite) NSArray *availableRewards;
|
||||
@property (nonatomic) MOPUBDisplayAgentType clickthroughExperimentBrowserAgent;
|
||||
|
||||
- (MPAdType)adTypeFromHeaders:(NSDictionary *)headers;
|
||||
- (NSString *)networkTypeFromHeaders:(NSDictionary *)headers;
|
||||
- (NSTimeInterval)refreshIntervalFromHeaders:(NSDictionary *)headers;
|
||||
- (NSDictionary *)dictionaryFromHeaders:(NSDictionary *)headers forKey:(NSString *)key;
|
||||
- (NSURL *)URLFromHeaders:(NSDictionary *)headers forKey:(NSString *)key;
|
||||
- (Class)setUpCustomEventClassFromHeaders:(NSDictionary *)headers;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation MPAdConfiguration
|
||||
|
||||
- (id)initWithHeaders:(NSDictionary *)headers data:(NSData *)data
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.adResponseData = data;
|
||||
|
||||
self.adType = [self adTypeFromHeaders:headers];
|
||||
|
||||
self.adUnitWarmingUp = [[headers objectForKey:kAdUnitWarmingUpHeaderKey] boolValue];
|
||||
|
||||
self.networkType = [self networkTypeFromHeaders:headers];
|
||||
self.networkType = self.networkType ? self.networkType : @"";
|
||||
|
||||
self.preferredSize = CGSizeMake([[headers objectForKey:kWidthHeaderKey] floatValue],
|
||||
[[headers objectForKey:kHeightHeaderKey] floatValue]);
|
||||
|
||||
self.clickTrackingURL = [self URLFromHeaders:headers
|
||||
forKey:kClickthroughHeaderKey];
|
||||
self.impressionTrackingURL = [self URLFromHeaders:headers
|
||||
forKey:kImpressionTrackerHeaderKey];
|
||||
self.failoverURL = [self URLFromHeaders:headers
|
||||
forKey:kFailUrlHeaderKey];
|
||||
self.interceptURLPrefix = [self URLFromHeaders:headers
|
||||
forKey:kLaunchpageHeaderKey];
|
||||
|
||||
self.scrollable = [[headers objectForKey:kScrollableHeaderKey] boolValue];
|
||||
self.refreshInterval = [self refreshIntervalFromHeaders:headers];
|
||||
self.adTimeoutInterval = [self timeIntervalFromHeaders:headers forKey:kAdTimeoutHeaderKey];
|
||||
|
||||
|
||||
self.nativeSDKParameters = [self dictionaryFromHeaders:headers
|
||||
forKey:kNativeSDKParametersHeaderKey];
|
||||
self.customSelectorName = [headers objectForKey:kCustomSelectorHeaderKey];
|
||||
|
||||
self.orientationType = [self orientationTypeFromHeaders:headers];
|
||||
|
||||
self.customEventClass = [self setUpCustomEventClassFromHeaders:headers];
|
||||
|
||||
self.customEventClassData = [self customEventClassDataFromHeaders:headers];
|
||||
|
||||
self.dspCreativeId = [headers objectForKey:kDspCreativeIdKey];
|
||||
|
||||
self.precacheRequired = [[headers objectForKey:kPrecacheRequiredKey] boolValue];
|
||||
|
||||
self.isVastVideoPlayer = [[headers objectForKey:kIsVastVideoPlayerKey] boolValue];
|
||||
|
||||
self.creationTimestamp = [NSDate date];
|
||||
|
||||
self.creativeId = [headers objectForKey:kCreativeIdHeaderKey];
|
||||
|
||||
self.headerAdType = [headers objectForKey:kAdTypeHeaderKey];
|
||||
|
||||
self.nativeVideoPlayVisiblePercent = [self percentFromHeaders:headers forKey:kNativeVideoPlayVisiblePercentHeaderKey];
|
||||
|
||||
self.nativeVideoPauseVisiblePercent = [self percentFromHeaders:headers forKey:kNativeVideoPauseVisiblePercentHeaderKey];
|
||||
|
||||
self.nativeImpressionMinVisiblePixels = [[self adAmountFromHeaders:headers key:kNativeImpressionMinVisiblePixelsHeaderKey] floatValue];
|
||||
|
||||
self.nativeImpressionMinVisiblePercent = [self percentFromHeaders:headers forKey:kNativeImpressionMinVisiblePercentHeaderKey];
|
||||
|
||||
self.nativeImpressionMinVisibleTimeInterval = [self timeIntervalFromMsHeaders:headers forKey:kNativeImpressionVisibleMsHeaderKey];
|
||||
|
||||
self.nativeVideoMaxBufferingTime = [self timeIntervalFromMsHeaders:headers forKey:kNativeVideoMaxBufferingTimeMsHeaderKey];
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
self.nativeVideoTrackers = [self nativeVideoTrackersFromHeaders:headers key:kNativeVideoTrackersHeaderKey];
|
||||
#endif
|
||||
|
||||
self.impressionMinVisibleTimeInSec = [self timeIntervalFromMsHeaders:headers forKey:kBannerImpressionVisableMsHeaderKey];
|
||||
self.impressionMinVisiblePixels = [[self adAmountFromHeaders:headers key:kBannerImpressionMinPixelHeaderKey] floatValue];
|
||||
|
||||
// rewarded video
|
||||
|
||||
// Attempt to parse the multiple currency header first since this will take
|
||||
// precedence over the older single currency approach.
|
||||
self.availableRewards = [self parseAvailableRewardsFromHeaders:headers];
|
||||
if (self.availableRewards != nil) {
|
||||
// Multiple currencies exist. We will select the first entry in the list
|
||||
// as the default selected reward.
|
||||
if (self.availableRewards.count > 0) {
|
||||
self.selectedReward = self.availableRewards[0];
|
||||
}
|
||||
// In the event that the list of available currencies is empty, we will
|
||||
// follow the behavior from the single currency approach and create an unspecified reward.
|
||||
else {
|
||||
MPRewardedVideoReward * defaultReward = [[MPRewardedVideoReward alloc] initWithCurrencyType:kMPRewardedVideoRewardCurrencyTypeUnspecified amount:@(kMPRewardedVideoRewardCurrencyAmountUnspecified)];
|
||||
self.availableRewards = [NSArray arrayWithObject:defaultReward];
|
||||
self.selectedReward = defaultReward;
|
||||
}
|
||||
}
|
||||
// Multiple currencies are not available; attempt to process single currency
|
||||
// headers.
|
||||
else {
|
||||
NSString *currencyName = [headers objectForKey:kRewardedVideoCurrencyNameHeaderKey] ?: kMPRewardedVideoRewardCurrencyTypeUnspecified;
|
||||
|
||||
NSNumber *currencyAmount = [self adAmountFromHeaders:headers key:kRewardedVideoCurrencyAmountHeaderKey];
|
||||
if (currencyAmount.integerValue <= 0) {
|
||||
currencyAmount = @(kMPRewardedVideoRewardCurrencyAmountUnspecified);
|
||||
}
|
||||
|
||||
MPRewardedVideoReward * reward = [[MPRewardedVideoReward alloc] initWithCurrencyType:currencyName amount:currencyAmount];
|
||||
self.availableRewards = [NSArray arrayWithObject:reward];
|
||||
self.selectedReward = reward;
|
||||
}
|
||||
|
||||
self.rewardedVideoCompletionUrl = [headers objectForKey:kRewardedVideoCompletionUrlHeaderKey];
|
||||
|
||||
// rewarded playables
|
||||
self.rewardedPlayableDuration = [self timeIntervalFromHeaders:headers forKey:kRewardedPlayableDurationHeaderKey];
|
||||
self.rewardedPlayableShouldRewardOnClick = [[headers objectForKey:kRewardedPlayableRewardOnClickHeaderKey] boolValue];
|
||||
|
||||
// clickthrough experiment
|
||||
self.clickthroughExperimentBrowserAgent = [self clickthroughExperimentVariantFromHeaders:headers forKey:kClickthroughExperimentBrowserAgent];
|
||||
[MOPUBExperimentProvider setDisplayAgentFromAdServer:self.clickthroughExperimentBrowserAgent];
|
||||
|
||||
// viewability
|
||||
NSString * disabledViewabilityValue = [headers objectForKey:kViewabilityDisableHeaderKey];
|
||||
NSNumber * disabledViewabilityVendors = disabledViewabilityValue != nil ? [disabledViewabilityValue safeIntegerValue] : nil;
|
||||
if (disabledViewabilityVendors != nil &&
|
||||
[disabledViewabilityVendors integerValue] >= MPViewabilityOptionNone &&
|
||||
[disabledViewabilityVendors integerValue] <= MPViewabilityOptionAll) {
|
||||
MPViewabilityOption vendorsToDisable = (MPViewabilityOption)([disabledViewabilityVendors integerValue]);
|
||||
[MPViewabilityTracker disableViewability:vendorsToDisable];
|
||||
}
|
||||
|
||||
// consent
|
||||
[[MPConsentManager sharedManager] forceStatusShouldForceExplicitNo:[headers[kForceExplicitNoKey] boolValue]
|
||||
shouldInvalidateConsent:[headers[kInvalidateConsentKey] boolValue]
|
||||
shouldReacquireConsent:[headers[kReacquireConsentKey] boolValue]
|
||||
consentChangeReason:headers[kConsentChangedReasonKey]
|
||||
shouldBroadcast:YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (Class)setUpCustomEventClassFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSString *customEventClassName = [headers objectForKey:kCustomEventClassNameHeaderKey];
|
||||
|
||||
NSMutableDictionary *convertedCustomEvents = [NSMutableDictionary dictionary];
|
||||
if (self.adType == MPAdTypeBanner) {
|
||||
[convertedCustomEvents setObject:@"MPGoogleAdMobBannerCustomEvent" forKey:@"admob_native"];
|
||||
[convertedCustomEvents setObject:@"MPMillennialBannerCustomEvent" forKey:@"millennial_native"];
|
||||
[convertedCustomEvents setObject:@"MPHTMLBannerCustomEvent" forKey:@"html"];
|
||||
[convertedCustomEvents setObject:@"MPMRAIDBannerCustomEvent" forKey:@"mraid"];
|
||||
[convertedCustomEvents setObject:@"MOPUBNativeVideoCustomEvent" forKey:@"json_video"];
|
||||
[convertedCustomEvents setObject:@"MPMoPubNativeCustomEvent" forKey:@"json"];
|
||||
} else if (self.adType == MPAdTypeInterstitial) {
|
||||
[convertedCustomEvents setObject:@"MPGoogleAdMobInterstitialCustomEvent" forKey:@"admob_full"];
|
||||
[convertedCustomEvents setObject:@"MPMillennialInterstitialCustomEvent" forKey:@"millennial_full"];
|
||||
[convertedCustomEvents setObject:@"MPHTMLInterstitialCustomEvent" forKey:@"html"];
|
||||
[convertedCustomEvents setObject:@"MPMRAIDInterstitialCustomEvent" forKey:@"mraid"];
|
||||
[convertedCustomEvents setObject:@"MPMoPubRewardedVideoCustomEvent" forKey:@"rewarded_video"];
|
||||
[convertedCustomEvents setObject:@"MPMoPubRewardedPlayableCustomEvent" forKey:@"rewarded_playable"];
|
||||
}
|
||||
if ([convertedCustomEvents objectForKey:self.networkType]) {
|
||||
customEventClassName = [convertedCustomEvents objectForKey:self.networkType];
|
||||
}
|
||||
|
||||
Class customEventClass = NSClassFromString(customEventClassName);
|
||||
|
||||
if (customEventClassName && !customEventClass) {
|
||||
MPLogWarn(@"Could not find custom event class named %@", customEventClassName);
|
||||
}
|
||||
|
||||
return customEventClass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (NSDictionary *)customEventClassDataFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSDictionary *result = [self dictionaryFromHeaders:headers forKey:kCustomEventClassDataHeaderKey];
|
||||
if (!result) {
|
||||
result = [self dictionaryFromHeaders:headers forKey:kNativeSDKParametersHeaderKey];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)hasPreferredSize
|
||||
{
|
||||
return (self.preferredSize.width > 0 && self.preferredSize.height > 0);
|
||||
}
|
||||
|
||||
- (NSString *)adResponseHTMLString
|
||||
{
|
||||
if (!_adResponseHTMLString) {
|
||||
self.adResponseHTMLString = [[NSString alloc] initWithData:self.adResponseData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
return _adResponseHTMLString;
|
||||
}
|
||||
|
||||
- (NSString *)clickDetectionURLPrefix
|
||||
{
|
||||
return self.interceptURLPrefix.absoluteString ? self.interceptURLPrefix.absoluteString : @"";
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (MPAdType)adTypeFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSString *adTypeString = [headers objectForKey:kAdTypeHeaderKey];
|
||||
|
||||
if ([adTypeString isEqualToString:@"interstitial"] || [adTypeString isEqualToString:@"rewarded_video"] || [adTypeString isEqualToString:@"rewarded_playable"]) {
|
||||
return MPAdTypeInterstitial;
|
||||
} else if (adTypeString &&
|
||||
[headers objectForKey:kOrientationTypeHeaderKey]) {
|
||||
return MPAdTypeInterstitial;
|
||||
} else if (adTypeString) {
|
||||
return MPAdTypeBanner;
|
||||
} else {
|
||||
return MPAdTypeUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)networkTypeFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSString *adTypeString = [headers objectForKey:kAdTypeHeaderKey];
|
||||
if ([adTypeString isEqualToString:@"interstitial"]) {
|
||||
return [headers objectForKey:kInterstitialAdTypeHeaderKey];
|
||||
} else {
|
||||
return adTypeString;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSURL *)URLFromHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSString *URLString = [headers objectForKey:key];
|
||||
return URLString ? [NSURL URLWithString:URLString] : nil;
|
||||
}
|
||||
|
||||
- (NSDictionary *)dictionaryFromHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSData *data = [(NSString *)[headers objectForKey:key] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *JSONFromHeaders = nil;
|
||||
if (data) {
|
||||
JSONFromHeaders = [NSJSONSerialization mp_JSONObjectWithData:data options:NSJSONReadingMutableContainers clearNullObjects:YES error:nil];
|
||||
}
|
||||
return JSONFromHeaders;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)refreshIntervalFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSString *intervalString = [headers objectForKey:kRefreshTimeHeaderKey];
|
||||
NSTimeInterval interval = -1;
|
||||
if (intervalString) {
|
||||
interval = [intervalString doubleValue];
|
||||
if (interval < MINIMUM_REFRESH_INTERVAL) {
|
||||
interval = MINIMUM_REFRESH_INTERVAL;
|
||||
}
|
||||
}
|
||||
return interval;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)timeIntervalFromHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSString *intervalString = [headers objectForKey:key];
|
||||
NSTimeInterval interval = -1;
|
||||
if (intervalString) {
|
||||
int parsedInt = -1;
|
||||
BOOL isNumber = [[NSScanner scannerWithString:intervalString] scanInt:&parsedInt];
|
||||
if (isNumber && parsedInt >= 0) {
|
||||
interval = parsedInt;
|
||||
}
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)timeIntervalFromMsHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSString *msString = [headers objectForKey:key];
|
||||
NSTimeInterval interval = -1;
|
||||
if (msString) {
|
||||
int parsedInt = -1;
|
||||
BOOL isNumber = [[NSScanner scannerWithString:msString] scanInt:&parsedInt];
|
||||
if (isNumber && parsedInt >= 0) {
|
||||
interval = parsedInt / 1000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
- (NSInteger)percentFromHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSString *percentString = [headers objectForKey:key];
|
||||
NSInteger percent = -1;
|
||||
if (percentString) {
|
||||
int parsedInt = -1;
|
||||
BOOL isNumber = [[NSScanner scannerWithString:percentString] scanInt:&parsedInt];
|
||||
if (isNumber && parsedInt >= 0 && parsedInt <= 100) {
|
||||
percent = parsedInt;
|
||||
}
|
||||
}
|
||||
|
||||
return percent;
|
||||
}
|
||||
|
||||
- (NSNumber *)adAmountFromHeaders:(NSDictionary *)headers key:(NSString *)key
|
||||
{
|
||||
NSString *amountString = [headers objectForKey:key];
|
||||
NSNumber *amount = @(-1);
|
||||
if (amountString) {
|
||||
int parsedInt = -1;
|
||||
BOOL isNumber = [[NSScanner scannerWithString:amountString] scanInt:&parsedInt];
|
||||
if (isNumber && parsedInt >= 0) {
|
||||
amount = @(parsedInt);
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
- (MPInterstitialOrientationType)orientationTypeFromHeaders:(NSDictionary *)headers
|
||||
{
|
||||
NSString *orientation = [headers objectForKey:kOrientationTypeHeaderKey];
|
||||
if ([orientation isEqualToString:@"p"]) {
|
||||
return MPInterstitialOrientationTypePortrait;
|
||||
} else if ([orientation isEqualToString:@"l"]) {
|
||||
return MPInterstitialOrientationTypeLandscape;
|
||||
} else {
|
||||
return MPInterstitialOrientationTypeAll;
|
||||
}
|
||||
}
|
||||
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
- (NSDictionary *)nativeVideoTrackersFromHeaders:(NSDictionary *)headers key:(NSString *)key
|
||||
{
|
||||
NSDictionary *dictFromHeader = [self dictionaryFromHeaders:headers forKey:key];
|
||||
if (!dictFromHeader) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableDictionary *videoTrackerDict = [NSMutableDictionary new];
|
||||
NSArray *events = dictFromHeader[kNativeVideoTrackerEventsHeaderKey];
|
||||
NSArray *urls = dictFromHeader[kNativeVideoTrackerUrlsHeaderKey];
|
||||
NSSet *supportedEvents = [NSSet setWithObjects:MPVASTTrackingEventTypeStart, MPVASTTrackingEventTypeFirstQuartile, MPVASTTrackingEventTypeMidpoint, MPVASTTrackingEventTypeThirdQuartile, MPVASTTrackingEventTypeComplete, nil];
|
||||
for (NSString *event in events) {
|
||||
if (![supportedEvents containsObject:event]) {
|
||||
continue;
|
||||
}
|
||||
[self setVideoTrackers:videoTrackerDict event:event urls:urls];
|
||||
}
|
||||
if (videoTrackerDict.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
return videoTrackerDict;
|
||||
}
|
||||
|
||||
- (void)setVideoTrackers:(NSMutableDictionary *)videoTrackerDict event:(NSString *)event urls:(NSArray *)urls {
|
||||
NSMutableArray *trackers = [NSMutableArray new];
|
||||
for (NSString *url in urls) {
|
||||
if ([url rangeOfString:kNativeVideoTrackerUrlMacro].location != NSNotFound) {
|
||||
NSString *trackerUrl = [url stringByReplacingOccurrencesOfString:kNativeVideoTrackerUrlMacro withString:event];
|
||||
NSDictionary *dict = @{kNativeVideoTrackerEventDictionaryKey:event, kNativeVideoTrackerTextDictionaryKey:trackerUrl};
|
||||
MPVASTTrackingEvent *tracker = [[MPVASTTrackingEvent alloc] initWithDictionary:dict];
|
||||
[trackers addObject:tracker];
|
||||
}
|
||||
}
|
||||
if (trackers.count > 0) {
|
||||
videoTrackerDict[event] = trackers;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (NSArray *)parseAvailableRewardsFromHeaders:(NSDictionary *)headers {
|
||||
// The X-Rewarded-Currencies header key doesn't exist. This is probably
|
||||
// not a rewarded ad.
|
||||
NSDictionary * currencies = [self dictionaryFromHeaders:headers forKey:kRewardedCurrenciesHeaderKey];
|
||||
if (currencies == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Either the list of available rewards doesn't exist or is empty.
|
||||
// This is an error.
|
||||
NSArray * rewards = [currencies objectForKey:@"rewards"];
|
||||
if (rewards.count == 0) {
|
||||
MPLogError(@"No available rewards found.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Parse the list of JSON rewards into objects.
|
||||
NSMutableArray * availableRewards = [NSMutableArray arrayWithCapacity:rewards.count];
|
||||
[rewards enumerateObjectsUsingBlock:^(NSDictionary * rewardDict, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
NSString * name = rewardDict[@"name"] ?: kMPRewardedVideoRewardCurrencyTypeUnspecified;
|
||||
NSNumber * amount = rewardDict[@"amount"] ?: @(kMPRewardedVideoRewardCurrencyAmountUnspecified);
|
||||
|
||||
MPRewardedVideoReward * reward = [[MPRewardedVideoReward alloc] initWithCurrencyType:name amount:amount];
|
||||
[availableRewards addObject:reward];
|
||||
}];
|
||||
|
||||
return availableRewards;
|
||||
}
|
||||
|
||||
- (MOPUBDisplayAgentType)clickthroughExperimentVariantFromHeaders:(NSDictionary *)headers forKey:(NSString *)key
|
||||
{
|
||||
NSString *variantString = [headers objectForKey:key];
|
||||
NSInteger variant = 0;
|
||||
if (variantString) {
|
||||
int parsedInt = -1;
|
||||
BOOL isNumber = [[NSScanner scannerWithString:variantString] scanInt:&parsedInt];
|
||||
if (isNumber && parsedInt >= 0 && parsedInt <= kMaximumVariantForClickthroughExperiment) {
|
||||
variant = parsedInt;
|
||||
}
|
||||
}
|
||||
|
||||
return variant;
|
||||
}
|
||||
|
||||
- (BOOL)visibleImpressionTrackingEnabled
|
||||
{
|
||||
if (self.impressionMinVisibleTimeInSec < 0 || self.impressionMinVisiblePixels <= 0) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,217 +0,0 @@
|
|||
//
|
||||
// MPAdServerCommunicator.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdServerCommunicator.h"
|
||||
|
||||
#import "MoPub.h"
|
||||
#import "MPAdConfiguration.h"
|
||||
#import "MPAPIEndpoints.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
#import "MPError.h"
|
||||
#import "MPHTTPNetworkSession.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPURLRequest.h"
|
||||
|
||||
// Ad response header
|
||||
static NSString * const kAdResponseTypeHeaderKey = @"X-Ad-Response-Type";
|
||||
static NSString * const kAdResponseTypeMultipleResponse = @"multi";
|
||||
|
||||
// Multiple response JSON fields
|
||||
static NSString * const kMultiAdResponsesKey = @"ad-responses";
|
||||
static NSString * const kMultiAdResponsesHeadersKey = @"headers";
|
||||
static NSString * const kMultiAdResponsesBodyKey = @"body";
|
||||
static NSString * const kMultiAdResponsesAdMarkupKey = @"adm";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@interface MPAdServerCommunicator ()
|
||||
|
||||
@property (nonatomic, assign, readwrite) BOOL loading;
|
||||
@property (nonatomic, strong) NSURLSessionTask * task;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPAdServerCommunicator (Consent)
|
||||
|
||||
/**
|
||||
Removes all ads.mopub.com cookies that are presently saved in NSHTTPCookieStorage to avoid inadvertently
|
||||
sending personal data across the wire via cookies. This method is expected to be called every ad request.
|
||||
*/
|
||||
- (void)removeAllMoPubCookies;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation MPAdServerCommunicator
|
||||
|
||||
- (id)initWithDelegate:(id<MPAdServerCommunicatorDelegate>)delegate
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.task cancel];
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)loadURL:(NSURL *)URL
|
||||
{
|
||||
[self cancel];
|
||||
|
||||
// Delete any cookies previous creatives have set before starting the load
|
||||
[self removeAllMoPubCookies];
|
||||
|
||||
// Check to be sure the SDK is initialized before starting the request
|
||||
if (!MoPub.sharedInstance.isSdkInitialized) {
|
||||
[self failLoadForSDKInit];
|
||||
}
|
||||
|
||||
// Generate request
|
||||
MPURLRequest * request = [[MPURLRequest alloc] initWithURL:URL];
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
self.task = [MPHTTPNetworkSession startTaskWithHttpRequest:request responseHandler:^(NSData * data, NSHTTPURLResponse * response) {
|
||||
// Capture strong self for the duration of this block.
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
|
||||
// Status code indicates an error.
|
||||
if (response.statusCode >= 400) {
|
||||
[strongSelf didFailWithError:[strongSelf errorForStatusCode:response.statusCode]];
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the response.
|
||||
[strongSelf didFinishLoadingWithData:data headers:response.allHeaderFields];
|
||||
|
||||
} errorHandler:^(NSError * error) {
|
||||
// Capture strong self for the duration of this block.
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
|
||||
// Handle the error.
|
||||
[strongSelf didFailWithError:error];
|
||||
}];
|
||||
|
||||
self.loading = YES;
|
||||
}
|
||||
|
||||
- (void)cancel
|
||||
{
|
||||
self.loading = NO;
|
||||
[self.task cancel];
|
||||
self.task = nil;
|
||||
}
|
||||
|
||||
- (void)failLoadForSDKInit {
|
||||
MPLogError(@"Warning: Ad requested before initializing MoPub SDK. MoPub SDK 5.2.0 will require initializeSdkWithConfiguration:completion: to be called on MoPub.sharedInstance before attempting to load ads. Please update your integration as soon as possible.");
|
||||
}
|
||||
|
||||
#pragma mark - Handlers
|
||||
|
||||
- (void)didFailWithError:(NSError *)error {
|
||||
// Do not record a logging event if we failed.
|
||||
self.loading = NO;
|
||||
[self.delegate communicatorDidFailWithError:error];
|
||||
}
|
||||
|
||||
- (void)didFinishLoadingWithData:(NSData *)data headers:(NSDictionary *)headers {
|
||||
NSArray <MPAdConfiguration *> *configurations;
|
||||
// Single ad response
|
||||
if (![headers[kAdResponseTypeHeaderKey] isEqualToString:kAdResponseTypeMultipleResponse]) {
|
||||
MPAdConfiguration *configuration = [[MPAdConfiguration alloc] initWithHeaders:headers
|
||||
data:data];
|
||||
configurations = @[configuration];
|
||||
}
|
||||
// Multiple ad responses
|
||||
else {
|
||||
// The response data is a JSON payload conforming to the structure:
|
||||
// ad-responses: [
|
||||
// {
|
||||
// headers: { x-adtype: html, ... },
|
||||
// body: "<!DOCTYPE html> <html> <head> ... </html>",
|
||||
// adm: "some ad markup"
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
NSError * error = nil;
|
||||
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
|
||||
if (error) {
|
||||
MPLogError(@"Failed to parse multiple ad response JSON: %@", error.localizedDescription);
|
||||
self.loading = NO;
|
||||
[self.delegate communicatorDidFailWithError:error];
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray * responses = json[kMultiAdResponsesKey];
|
||||
if (responses == nil) {
|
||||
MPLogError(@"No ad responses");
|
||||
self.loading = NO;
|
||||
[self.delegate communicatorDidFailWithError:[MOPUBError errorWithCode:MOPUBErrorUnableToParseJSONAdResponse]];
|
||||
return;
|
||||
}
|
||||
|
||||
MPLogInfo(@"There are %ld ad responses", responses.count);
|
||||
|
||||
NSMutableArray<MPAdConfiguration *> * responseConfigurations = [NSMutableArray arrayWithCapacity:responses.count];
|
||||
for (NSDictionary * responseJson in responses) {
|
||||
NSDictionary * headers = responseJson[kMultiAdResponsesHeadersKey];
|
||||
NSData * body = [responseJson[kMultiAdResponsesBodyKey] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
MPAdConfiguration * configuration = [[MPAdConfiguration alloc] initWithHeaders:headers data:body];
|
||||
if (configuration) {
|
||||
configuration.advancedBidPayload = responseJson[kMultiAdResponsesAdMarkupKey];
|
||||
[responseConfigurations addObject:configuration];
|
||||
}
|
||||
else {
|
||||
MPLogInfo(@"Failed to generate configuration from\nheaders:\n%@\nbody:\n%@", headers, responseJson[kMultiAdResponsesBodyKey]);
|
||||
}
|
||||
}
|
||||
|
||||
configurations = [NSArray arrayWithArray:responseConfigurations];
|
||||
}
|
||||
|
||||
self.loading = NO;
|
||||
[self.delegate communicatorDidReceiveAdConfigurations:configurations];
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
- (NSError *)errorForStatusCode:(NSInteger)statusCode
|
||||
{
|
||||
NSString *errorMessage = [NSString stringWithFormat:
|
||||
NSLocalizedString(@"MoPub returned status code %d.",
|
||||
@"Status code error"),
|
||||
statusCode];
|
||||
NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:errorMessage
|
||||
forKey:NSLocalizedDescriptionKey];
|
||||
return [NSError errorWithDomain:@"mopub.com" code:statusCode userInfo:errorInfo];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Consent
|
||||
|
||||
@implementation MPAdServerCommunicator (Consent)
|
||||
|
||||
- (void)removeAllMoPubCookies {
|
||||
// Make NSURL from base URL
|
||||
NSURL *moPubBaseURL = [NSURL URLWithString:[MPAPIEndpoints baseURL]];
|
||||
|
||||
// Get array of cookies with the base URL, and delete each one
|
||||
NSArray <NSHTTPCookie *> * cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:moPubBaseURL];
|
||||
for (NSHTTPCookie * cookie in cookies) {
|
||||
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,67 +0,0 @@
|
|||
//
|
||||
// MPAdServerURLBuilder.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
@interface MPAdServerURLBuilder : NSObject
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location;
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location
|
||||
desiredAssets:(NSArray *)assets
|
||||
viewability:(BOOL)viewability;
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location
|
||||
desiredAssets:(NSArray *)assets
|
||||
adSequence:(NSInteger)adSequence
|
||||
viewability:(BOOL)viewability;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPAdServerURLBuilder (OpenEndpoint)
|
||||
|
||||
/**
|
||||
Constructs the conversion tracking URL using current consent state, SDK state, and @c appID parameter.
|
||||
@param appID The App ID to be included in the URL.
|
||||
@returns URL to the open endpoint configuring for conversion tracking.
|
||||
*/
|
||||
+ (NSURL *)conversionTrackingURLForAppID:(NSString *)appID;
|
||||
|
||||
/**
|
||||
Constructs the session tracking URL using current consent state and SDK state.
|
||||
@returns URL to the open endpoint configuring for session tracking.
|
||||
*/
|
||||
+ (NSURL *)sessionTrackingURL;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPAdServerURLBuilder (Consent)
|
||||
|
||||
/**
|
||||
Constructs the consent synchronization endpoint URL using the current consent manager
|
||||
state.
|
||||
@returns URL to the consent synchronization endpoint.
|
||||
*/
|
||||
+ (NSURL *)consentSynchronizationUrl;
|
||||
|
||||
/**
|
||||
Constructs the URL to fetch the consent dialog using the current consent manager state.
|
||||
@returns URL to the consent dialog endpoint
|
||||
*/
|
||||
+ (NSURL *)consentDialogURL;
|
||||
|
||||
@end
|
|
@ -1,552 +0,0 @@
|
|||
//
|
||||
// MPAdServerURLBuilder.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdServerURLBuilder.h"
|
||||
|
||||
#import "MPAdvancedBiddingManager.h"
|
||||
#import "MPConsentAdServerKeys.h"
|
||||
#import "MPConstants.h"
|
||||
#import "MPGeolocationProvider.h"
|
||||
#import "MPGlobal.h"
|
||||
#import "MPIdentityProvider.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
#import "MPReachability.h"
|
||||
#import "MPAPIEndpoints.h"
|
||||
#import "MPViewabilityTracker.h"
|
||||
#import "NSString+MPAdditions.h"
|
||||
#import "NSString+MPConsentStatus.h"
|
||||
#import "MPConsentManager.h"
|
||||
|
||||
static NSString * const kMoPubInterfaceOrientationPortrait = @"p";
|
||||
static NSString * const kMoPubInterfaceOrientationLandscape = @"l";
|
||||
static NSInteger const kAdSequenceNone = -1;
|
||||
|
||||
// Ad Server URL Keys
|
||||
static NSString * const kServerAPIVersionKey = @"v";
|
||||
static NSString * const kApplicationVersionKey = @"av";
|
||||
|
||||
// Open Endpoint-specific Keys
|
||||
static NSString * const kOpenEndpointIDKey = @"id";
|
||||
static NSString * const kOpenEndpointSessionTrackingKey = @"st";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@interface MPAdServerURLBuilder ()
|
||||
|
||||
+ (NSString *)queryParameterForKeywords:(NSString *)keywords;
|
||||
+ (NSString *)queryParameterForUserDataKeywords:(NSString *)userDataKeywords;
|
||||
+ (NSString *)queryParameterForOrientation;
|
||||
+ (NSString *)queryParameterForScaleFactor;
|
||||
+ (NSString *)queryParameterForTimeZone;
|
||||
+ (NSString *)queryParameterForLocation:(CLLocation *)location;
|
||||
+ (NSString *)queryParameterForMRAID;
|
||||
+ (NSString *)queryParameterForDNT;
|
||||
+ (NSString *)queryParameterForConnectionType;
|
||||
+ (NSString *)queryParameterForApplicationVersion;
|
||||
+ (NSString *)queryParameterForCarrierName;
|
||||
+ (NSString *)queryParameterForISOCountryCode;
|
||||
+ (NSString *)queryParameterForMobileNetworkCode;
|
||||
+ (NSString *)queryParameterForMobileCountryCode;
|
||||
+ (NSString *)queryParameterForDeviceName;
|
||||
+ (NSString *)queryParameterForDesiredAdAssets:(NSArray *)assets;
|
||||
+ (NSString *)queryParameterForAdSequence:(NSInteger)adSequence;
|
||||
+ (NSString *)queryParameterForPhysicalScreenSize;
|
||||
+ (NSString *)queryParameterForBundleIdentifier;
|
||||
+ (NSString *)queryParameterForAppTransportSecurity;
|
||||
+ (NSString *)queryParameterForConsent;
|
||||
+ (BOOL)advertisingTrackingEnabled;
|
||||
|
||||
// Helper methods
|
||||
+ (NSString *)URLEncodedApplicationVersion;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation MPAdServerURLBuilder
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location
|
||||
{
|
||||
return [self URLWithAdUnitID:adUnitID
|
||||
keywords:keywords
|
||||
userDataKeywords:userDataKeywords
|
||||
location:location
|
||||
desiredAssets:nil
|
||||
viewability:YES];
|
||||
}
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location
|
||||
desiredAssets:(NSArray *)assets
|
||||
viewability:(BOOL)viewability
|
||||
{
|
||||
|
||||
|
||||
return [self URLWithAdUnitID:adUnitID
|
||||
keywords:keywords
|
||||
userDataKeywords:userDataKeywords
|
||||
location:location
|
||||
desiredAssets:assets
|
||||
adSequence:kAdSequenceNone
|
||||
viewability:viewability];
|
||||
}
|
||||
|
||||
+ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID
|
||||
keywords:(NSString *)keywords
|
||||
userDataKeywords:(NSString *)userDataKeywords
|
||||
location:(CLLocation *)location
|
||||
desiredAssets:(NSArray *)assets
|
||||
adSequence:(NSInteger)adSequence
|
||||
viewability:(BOOL)viewability
|
||||
{
|
||||
NSString *URLString = [NSString stringWithFormat:@"%@?%@=%@&udid=%@&id=%@&nv=%@",
|
||||
[MPAPIEndpoints baseURLStringWithPath:MOPUB_API_PATH_AD_REQUEST],
|
||||
kServerAPIVersionKey,
|
||||
MP_SERVER_VERSION,
|
||||
[MPIdentityProvider identifier],
|
||||
[adUnitID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
MP_SDK_VERSION];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForOrientation]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForScaleFactor]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForTimeZone]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForMRAID]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForDNT]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForConnectionType]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForApplicationVersion]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForCarrierName]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForISOCountryCode]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForMobileNetworkCode]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForMobileCountryCode]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForDeviceName]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForDesiredAdAssets:assets]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForAdSequence:adSequence]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForPhysicalScreenSize]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForBundleIdentifier]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForAppTransportSecurity]];
|
||||
|
||||
if ([MPConsentManager sharedManager].canCollectPersonalInfo) {
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForLocation:location]];
|
||||
}
|
||||
|
||||
// If a user is in GDPR region and MoPub doesn't obtain consent from the user, personal keywords won't be sent
|
||||
// to the server. It's handled in `queryParameterForKeywords` method.
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForKeywords:keywords]];
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForUserDataKeywords:userDataKeywords]];
|
||||
|
||||
if (viewability) {
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForViewability]];
|
||||
}
|
||||
|
||||
NSString * advancedBiddingQueryParameter = [self queryParameterForAdvancedBidding];
|
||||
if (advancedBiddingQueryParameter) {
|
||||
URLString = [URLString stringByAppendingString:advancedBiddingQueryParameter];
|
||||
}
|
||||
|
||||
URLString = [URLString stringByAppendingString:[self queryParameterForConsent]];
|
||||
|
||||
// In the event that the `adUnitIdUsedForConsent` from `MPConsentManager` is still `nil`,
|
||||
// we should populate it with this `adUnitId`. This is to cover the edge case where the
|
||||
// publisher does not explcitily initialize the SDK via `initializeSdkWithConfiguration:completion:`.
|
||||
if (adUnitID != nil && MPConsentManager.sharedManager.adUnitIdUsedForConsent == nil) {
|
||||
MPConsentManager.sharedManager.adUnitIdUsedForConsent = adUnitID;
|
||||
}
|
||||
|
||||
return [NSURL URLWithString:URLString];
|
||||
}
|
||||
|
||||
|
||||
+ (NSString *)queryParameterForUserDataKeywords:(NSString *)userDataKeywords
|
||||
{
|
||||
if (![MPConsentManager sharedManager].canCollectPersonalInfo) {
|
||||
return @"";
|
||||
}
|
||||
return [MPAdServerURLBuilder queryParameterForKeywords:userDataKeywords key:@"user_data_q"];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForKeywords:(NSString *)keywords
|
||||
{
|
||||
return [MPAdServerURLBuilder queryParameterForKeywords:keywords key:@"q"];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForKeywords:(NSString *)keywords key:(NSString *)key
|
||||
{
|
||||
NSString *trimmedKeywords = [keywords stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet whitespaceCharacterSet]];
|
||||
if ([trimmedKeywords length] > 0) {
|
||||
NSString *keywords = [trimmedKeywords stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
return [NSString stringWithFormat:@"&%@=%@", key, keywords];
|
||||
}
|
||||
return @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForOrientation
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
NSString *orientString = UIInterfaceOrientationIsPortrait(orientation) ?
|
||||
kMoPubInterfaceOrientationPortrait : kMoPubInterfaceOrientationLandscape;
|
||||
return [NSString stringWithFormat:@"&o=%@", orientString];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForScaleFactor
|
||||
{
|
||||
return [NSString stringWithFormat:@"&sc=%.1f", MPDeviceScaleFactor()];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForTimeZone
|
||||
{
|
||||
static NSDateFormatter *formatter;
|
||||
@synchronized(self)
|
||||
{
|
||||
if (!formatter) formatter = [[NSDateFormatter alloc] init];
|
||||
}
|
||||
[formatter setDateFormat:@"Z"];
|
||||
NSDate *today = [NSDate date];
|
||||
return [NSString stringWithFormat:@"&z=%@", [formatter stringFromDate:today]];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForLocation:(CLLocation *)location
|
||||
{
|
||||
NSString *result = @"";
|
||||
|
||||
CLLocation *bestLocation = location;
|
||||
CLLocation *locationFromProvider = [[[MPCoreInstanceProvider sharedProvider] sharedMPGeolocationProvider] lastKnownLocation];
|
||||
|
||||
if (locationFromProvider) {
|
||||
bestLocation = locationFromProvider;
|
||||
}
|
||||
|
||||
if (bestLocation && bestLocation.horizontalAccuracy >= 0) {
|
||||
result = [NSString stringWithFormat:@"&ll=%@,%@",
|
||||
[NSNumber numberWithDouble:bestLocation.coordinate.latitude],
|
||||
[NSNumber numberWithDouble:bestLocation.coordinate.longitude]];
|
||||
|
||||
if (bestLocation.horizontalAccuracy) {
|
||||
result = [result stringByAppendingFormat:@"&lla=%@",
|
||||
[NSNumber numberWithDouble:bestLocation.horizontalAccuracy]];
|
||||
}
|
||||
|
||||
if (bestLocation == locationFromProvider) {
|
||||
result = [result stringByAppendingString:@"&llsdk=1"];
|
||||
}
|
||||
|
||||
NSTimeInterval locationLastUpdatedMillis = [[NSDate date] timeIntervalSinceDate:bestLocation.timestamp] * 1000.0;
|
||||
|
||||
result = [result stringByAppendingFormat:@"&llf=%.0f", locationLastUpdatedMillis];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForMRAID
|
||||
{
|
||||
if (NSClassFromString(@"MPMRAIDBannerCustomEvent") &&
|
||||
NSClassFromString(@"MPMRAIDInterstitialCustomEvent")) {
|
||||
return @"&mr=1";
|
||||
} else {
|
||||
return @"";
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForDNT
|
||||
{
|
||||
return [self advertisingTrackingEnabled] ? @"" : @"&dnt=1";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForConnectionType
|
||||
{
|
||||
return [[[MPCoreInstanceProvider sharedProvider] sharedMPReachability] hasWifi] ? @"&ct=2" : @"&ct=3";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForApplicationVersion
|
||||
{
|
||||
return [NSString stringWithFormat:@"&%@=%@", kApplicationVersionKey, [self URLEncodedApplicationVersion]];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForCarrierName
|
||||
{
|
||||
NSString *carrierName = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"carrierName"];
|
||||
return carrierName ? [NSString stringWithFormat:@"&cn=%@",
|
||||
[carrierName mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForISOCountryCode
|
||||
{
|
||||
NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"isoCountryCode"];
|
||||
return code ? [NSString stringWithFormat:@"&iso=%@", [code mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForMobileNetworkCode
|
||||
{
|
||||
NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"mobileNetworkCode"];
|
||||
return code ? [NSString stringWithFormat:@"&mnc=%@", [code mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForMobileCountryCode
|
||||
{
|
||||
NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"mobileCountryCode"];
|
||||
return code ? [NSString stringWithFormat:@"&mcc=%@", [code mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForDeviceName
|
||||
{
|
||||
NSString *deviceName = [[UIDevice currentDevice] mp_hardwareDeviceName];
|
||||
return deviceName ? [NSString stringWithFormat:@"&dn=%@", [deviceName mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForDesiredAdAssets:(NSArray *)assets
|
||||
{
|
||||
NSString *concatenatedAssets = [assets componentsJoinedByString:@","];
|
||||
return [concatenatedAssets length] ? [NSString stringWithFormat:@"&assets=%@", concatenatedAssets] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForAdSequence:(NSInteger)adSequence
|
||||
{
|
||||
return (adSequence >= 0) ? [NSString stringWithFormat:@"&seq=%ld", (long)adSequence] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForPhysicalScreenSize
|
||||
{
|
||||
CGSize screenSize = MPScreenResolution();
|
||||
|
||||
return [NSString stringWithFormat:@"&w=%.0f&h=%.0f", screenSize.width, screenSize.height];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForBundleIdentifier
|
||||
{
|
||||
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
|
||||
return bundleIdentifier ? [NSString stringWithFormat:@"&bundle=%@", [bundleIdentifier mp_URLEncodedString]] : @"";
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForAppTransportSecurity
|
||||
{
|
||||
return [NSString stringWithFormat:@"&ats=%@", @([[MPCoreInstanceProvider sharedProvider] appTransportSecuritySettings])];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForViewability {
|
||||
return [NSString stringWithFormat:@"&vv=%d", (int)[MPViewabilityTracker enabledViewabilityVendors]];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForAdvancedBidding {
|
||||
// Opted out of advanced bidding, no query parameter should be sent.
|
||||
if (![MPAdvancedBiddingManager sharedManager].advancedBiddingEnabled) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// No JSON at this point means that no advanced bidders were initialized.
|
||||
NSString * tokens = MPAdvancedBiddingManager.sharedManager.bidderTokensJson;
|
||||
if (tokens == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// URL encode the JSON string
|
||||
NSString * urlEncodedTokens = [tokens mp_URLEncodedString];
|
||||
if (urlEncodedTokens == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSString stringWithFormat:@"&abt=%@", urlEncodedTokens];
|
||||
}
|
||||
|
||||
+ (NSString *)queryParameterForConsent {
|
||||
MPConsentManager * manager = MPConsentManager.sharedManager;
|
||||
|
||||
// Consent state
|
||||
NSString * consent = [NSString stringFromConsentStatus:manager.currentStatus];
|
||||
NSMutableString * consentQuery = [NSMutableString stringWithFormat:@"&%@=%@", kCurrentConsentStatusKey, consent];
|
||||
|
||||
// GDPR applicable state
|
||||
if (manager.isGDPRApplicable != MPBoolUnknown) {
|
||||
NSString * gdprBoolValue = manager.isGDPRApplicable > 0 ? @"1" : @"0";
|
||||
[consentQuery appendFormat:@"&%@=%@", kGDPRAppliesKey, gdprBoolValue];
|
||||
}
|
||||
|
||||
// User consented versions
|
||||
if (manager.consentedPrivacyPolicyVersion != nil) {
|
||||
[consentQuery appendFormat:@"&%@=%@", kConsentedPrivacyPolicyVersionKey, manager.consentedPrivacyPolicyVersion];
|
||||
}
|
||||
|
||||
if (manager.consentedVendorListVersion != nil) {
|
||||
[consentQuery appendFormat:@"&%@=%@", kConsentedVendorListVersionKey, manager.consentedVendorListVersion];
|
||||
}
|
||||
|
||||
return consentQuery;
|
||||
}
|
||||
|
||||
+ (BOOL)advertisingTrackingEnabled
|
||||
{
|
||||
return [MPIdentityProvider advertisingTrackingEnabled];
|
||||
}
|
||||
|
||||
+ (NSString *)URLEncodedApplicationVersion {
|
||||
static NSString * gApplicationVersion;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
gApplicationVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] mp_URLEncodedString];
|
||||
});
|
||||
|
||||
return gApplicationVersion;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface MPAdServerURLBuilder (Helper)
|
||||
|
||||
+ (NSURL *)URLWithEndpointPath:(NSString *)endpointPath queryParameters:(NSDictionary *)parameters;
|
||||
|
||||
+ (NSString *)queryItemForKey:(NSString *)key value:(NSString *)value;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdServerURLBuilder (Helper)
|
||||
|
||||
+ (NSURL *)URLWithEndpointPath:(NSString *)endpointPath queryParameters:(NSDictionary *)parameters {
|
||||
// Build the full URL string
|
||||
NSString * baseURLString = [MPAPIEndpoints baseURLStringWithPath:endpointPath];
|
||||
|
||||
NSMutableArray * queryItems = [NSMutableArray array];
|
||||
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) {
|
||||
NSString * queryItem = [self queryItemForKey:key value:value];
|
||||
[queryItems addObject:queryItem];
|
||||
}];
|
||||
|
||||
NSString * queryParameters = [queryItems componentsJoinedByString:@"&"];
|
||||
NSString * url = [NSString stringWithFormat:@"%@?%@", baseURLString, queryParameters];
|
||||
|
||||
return [NSURL URLWithString:url];
|
||||
}
|
||||
|
||||
+ (NSString *)queryItemForKey:(NSString *)key value:(NSString *)value {
|
||||
if (key == nil || value == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString * encodedValue = [value mp_URLEncodedString];
|
||||
return [NSString stringWithFormat:@"%@=%@", key, encodedValue];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdServerURLBuilder (OpenEndpoint)
|
||||
|
||||
+ (NSURL *)conversionTrackingURLForAppID:(NSString *)appID {
|
||||
return [self openEndpointURLWithIDParameter:appID isSessionTracking:NO];
|
||||
}
|
||||
|
||||
+ (NSURL *)sessionTrackingURL {
|
||||
NSString *bundleIdentifier = [[[NSBundle mainBundle] bundleIdentifier] mp_URLEncodedString];
|
||||
return [self openEndpointURLWithIDParameter:bundleIdentifier isSessionTracking:YES];
|
||||
}
|
||||
|
||||
+ (NSURL *)openEndpointURLWithIDParameter:(NSString *)idParameter isSessionTracking:(BOOL)isSessionTracking {
|
||||
MPConsentManager * manager = MPConsentManager.sharedManager;
|
||||
|
||||
NSMutableDictionary * queryParameters = [NSMutableDictionary dictionary];
|
||||
|
||||
// REQUIRED: IDFA
|
||||
queryParameters[kIdfaKey] = [MPIdentityProvider identifier];
|
||||
|
||||
// REQUIRED: ID Parameter (used for different things depending on which URL, take from method parameter)
|
||||
queryParameters[kOpenEndpointIDKey] = idParameter;
|
||||
|
||||
// REQUIRED: Server API Version
|
||||
queryParameters[kServerAPIVersionKey] = MP_SERVER_VERSION;
|
||||
|
||||
// REQUIRED: SDK Version
|
||||
queryParameters[kSDKVersionKey] = MP_SDK_VERSION;
|
||||
|
||||
// REQUIRED: Application Version
|
||||
queryParameters[kApplicationVersionKey] = [self URLEncodedApplicationVersion];
|
||||
|
||||
// OPTIONAL: Include Session Tracking Parameter if needed
|
||||
if (isSessionTracking) {
|
||||
queryParameters[kOpenEndpointSessionTrackingKey] = @"1";
|
||||
}
|
||||
|
||||
// REQUIRED: GDPR region applicable
|
||||
if (manager.isGDPRApplicable != MPBoolUnknown) {
|
||||
queryParameters[kGDPRAppliesKey] = manager.isGDPRApplicable > 0 ? @"1" : @"0";
|
||||
}
|
||||
|
||||
// REQUIRED: Current consent status
|
||||
queryParameters[kCurrentConsentStatusKey] = [NSString stringFromConsentStatus:manager.currentStatus];
|
||||
|
||||
// OPTIONAL: Consented versions
|
||||
queryParameters[kConsentedPrivacyPolicyVersionKey] = manager.consentedPrivacyPolicyVersion;
|
||||
queryParameters[kConsentedVendorListVersionKey] = manager.consentedVendorListVersion;
|
||||
|
||||
return [self URLWithEndpointPath:MOPUB_API_PATH_OPEN queryParameters:queryParameters];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdServerURLBuilder (Consent)
|
||||
|
||||
#pragma mark - Consent URLs
|
||||
|
||||
+ (NSURL *)consentSynchronizationUrl {
|
||||
MPConsentManager * manager = MPConsentManager.sharedManager;
|
||||
|
||||
// REQUIRED: Ad unit ID for consent may be empty if the publisher
|
||||
// never initialized the SDK.
|
||||
NSMutableDictionary * queryParameters = [NSMutableDictionary dictionary];
|
||||
queryParameters[kAdUnitIdKey] = manager.adUnitIdUsedForConsent;
|
||||
|
||||
// REQUIRED: SDK version, DNT, Bundle
|
||||
queryParameters[kSDKVersionKey] = MP_SDK_VERSION;
|
||||
queryParameters[kDoNotTrackIdKey] = [MPIdentityProvider advertisingTrackingEnabled] ? nil : @"1";
|
||||
queryParameters[kBundleKey] = [[[NSBundle mainBundle] bundleIdentifier] mp_URLEncodedString];
|
||||
|
||||
// REQUIRED: Current consent status
|
||||
queryParameters[kCurrentConsentStatusKey] = [NSString stringFromConsentStatus:manager.currentStatus];
|
||||
|
||||
// REQUIRED: GDPR region applicable
|
||||
if (manager.isGDPRApplicable != MPBoolUnknown) {
|
||||
queryParameters[kGDPRAppliesKey] = manager.isGDPRApplicable > 0 ? @"1" : @"0";
|
||||
}
|
||||
|
||||
// OPTIONAL: IFA for consent, last synchronized consent status, last changed reason,
|
||||
// last changed timestamp in milliseconds
|
||||
queryParameters[kIdfaKey] = manager.ifaForConsent;
|
||||
queryParameters[kLastSynchronizedConsentStatusKey] = manager.lastSynchronizedStatus;
|
||||
queryParameters[kConsentChangedReasonKey] = manager.lastChangedReason;
|
||||
queryParameters[kLastChangedMsKey] = manager.lastChangedTimestampInMilliseconds > 0 ? [NSString stringWithFormat:@"%llu", (unsigned long long)manager.lastChangedTimestampInMilliseconds] : nil;
|
||||
|
||||
// OPTIONAL: Consented versions
|
||||
queryParameters[kConsentedPrivacyPolicyVersionKey] = manager.consentedPrivacyPolicyVersion;
|
||||
queryParameters[kConsentedVendorListVersionKey] = manager.consentedVendorListVersion;
|
||||
queryParameters[kCachedIabVendorListHashKey] = manager.iabVendorListHash;
|
||||
|
||||
// OPTIONAL: Server extras
|
||||
queryParameters[kExtrasKey] = manager.extras;
|
||||
|
||||
return [self URLWithEndpointPath:MOPUB_API_PATH_CONSENT_SYNC queryParameters:queryParameters];
|
||||
}
|
||||
|
||||
+ (NSURL *)consentDialogURL {
|
||||
MPConsentManager * manager = MPConsentManager.sharedManager;
|
||||
|
||||
// REQUIRED: Ad unit ID for consent may be empty if the publisher
|
||||
// never initialized the SDK.
|
||||
NSMutableDictionary * queryParameters = [NSMutableDictionary dictionary];
|
||||
queryParameters[kAdUnitIdKey] = manager.adUnitIdUsedForConsent;
|
||||
|
||||
// REQUIRED: SDK version, DNT, Bundle, Language
|
||||
queryParameters[kSDKVersionKey] = MP_SDK_VERSION;
|
||||
queryParameters[kDoNotTrackIdKey] = [MPIdentityProvider advertisingTrackingEnabled] ? nil : @"1";
|
||||
queryParameters[kBundleKey] = [[[NSBundle mainBundle] bundleIdentifier] mp_URLEncodedString];
|
||||
queryParameters[kLanguageKey] = manager.currentLanguageCode;
|
||||
|
||||
return [self URLWithEndpointPath:MOPUB_API_PATH_CONSENT_DIALOG queryParameters:queryParameters];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
//
|
||||
// MPCountdownTimerView.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2016 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
/**
|
||||
* A view that will display a countdown timer and invoke a completion block once
|
||||
* the timer has elapsed.
|
||||
*/
|
||||
@interface MPCountdownTimerView : UIView
|
||||
|
||||
/**
|
||||
* Flag indicating if the timer is active.
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL isActive;
|
||||
|
||||
/**
|
||||
* Flag indicating if the timer is currently paused.
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL isPaused;
|
||||
|
||||
/**
|
||||
* Initializes a countdown timer view. The timer is not automatically started.
|
||||
*
|
||||
* @param frame Frame of the view.
|
||||
* @param seconds Duration of the timer in seconds. This value must be greater than zero.
|
||||
* @returns An initialized timer if successful; otherwise nil.
|
||||
*/
|
||||
- (instancetype)initWithFrame:(CGRect)frame duration:(NSTimeInterval)seconds;
|
||||
|
||||
/**
|
||||
* Starts the countdown timer. If the timer has already started, calling this method again will do nothing.
|
||||
*
|
||||
* @param completion Completion block that is fired when the timer elapses or is stopped.
|
||||
*/
|
||||
- (void)startWithTimerCompletion:(void(^)(BOOL hasElapsed))completion;
|
||||
|
||||
/**
|
||||
* Stops the timer and optionally invokes the completion block from `startWithTimerCompletion:`.
|
||||
* If the timer hasn't started, calling this method will do nothing.
|
||||
*/
|
||||
- (void)stopAndSignalCompletion:(BOOL)shouldSignalCompletion;
|
||||
|
||||
/**
|
||||
* Pauses the timer. If the timer hasn't started, calling this method will do nothing.
|
||||
*/
|
||||
- (void)pause;
|
||||
|
||||
/**
|
||||
* Resumes the timer. If the timer isn't paused, calling this method will do nothing.
|
||||
*/
|
||||
- (void)resume;
|
||||
|
||||
@end
|
|
@ -1,195 +0,0 @@
|
|||
//
|
||||
// MPCountdownTimerView.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2016 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPCountdownTimerView.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPTimer.h"
|
||||
#import "NSBundle+MPAdditions.h"
|
||||
|
||||
// The frequency at which the internal timer is fired in seconds.
|
||||
// This value matches the step size of the jQuery knob in MPCountdownTimer.html.
|
||||
static const NSTimeInterval kCountdownTimerInterval = 0.05;
|
||||
|
||||
@interface MPCountdownTimerView() <UIWebViewDelegate>
|
||||
@property (nonatomic, assign, readwrite) BOOL isPaused;
|
||||
|
||||
@property (nonatomic, copy) void(^completionBlock)(BOOL);
|
||||
@property (nonatomic, assign) NSTimeInterval currentSeconds;
|
||||
@property (nonatomic, strong) MPTimer * timer;
|
||||
@property (nonatomic, strong) UIWebView * timerView;
|
||||
@end
|
||||
|
||||
@implementation MPCountdownTimerView
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame duration:(NSTimeInterval)seconds {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
// Duration should be non-negative.
|
||||
if (seconds < 0) {
|
||||
MPLogDebug(@"Attempted to initialize MPCountdownTimerView with a negative duration. No timer will be created.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
_completionBlock = nil;
|
||||
_currentSeconds = seconds;
|
||||
_isPaused = NO;
|
||||
_timer = nil;
|
||||
_timerView = ({
|
||||
UIWebView * view = [[UIWebView alloc] initWithFrame:self.bounds];
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
view.backgroundColor = [UIColor clearColor];
|
||||
view.delegate = self;
|
||||
view.opaque = NO;
|
||||
view.userInteractionEnabled = NO;
|
||||
view;
|
||||
});
|
||||
self.userInteractionEnabled = NO;
|
||||
|
||||
[self addSubview:_timerView];
|
||||
[_timerView loadHTMLString:self.timerHtml baseURL:self.timerBaseUrl];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// Stop the timer if the view is going away, but do not notify the completion block
|
||||
// if there is one.
|
||||
_completionBlock = nil;
|
||||
[self stopAndSignalCompletion:NO];
|
||||
}
|
||||
|
||||
#pragma mark - Timer
|
||||
|
||||
- (BOOL)isActive {
|
||||
return (self.timer != nil);
|
||||
}
|
||||
|
||||
- (void)startWithTimerCompletion:(void(^)(BOOL hasElapsed))completion {
|
||||
if (self.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset any internal state that may be dirty from a previous timer run.
|
||||
self.isPaused = NO;
|
||||
|
||||
// Copy the completion block and set up the initial state of the timer.
|
||||
self.completionBlock = completion;
|
||||
|
||||
// Start the timer now.
|
||||
self.timer = [MPTimer timerWithTimeInterval:kCountdownTimerInterval
|
||||
target:self
|
||||
selector:@selector(onTimerUpdate:)
|
||||
repeats:YES];
|
||||
[self.timer scheduleNow];
|
||||
|
||||
MPLogInfo(@"MPCountdownTimerView started");
|
||||
}
|
||||
|
||||
- (void)stopAndSignalCompletion:(BOOL)shouldSignalCompletion {
|
||||
if (!self.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalidate and clear the timer to stop it completely.
|
||||
[self.timer invalidate];
|
||||
self.timer = nil;
|
||||
|
||||
MPLogInfo(@"MPCountdownTimerView stopped");
|
||||
|
||||
// Notify the completion block and clear it out once it's handling has finished.
|
||||
if (shouldSignalCompletion && self.completionBlock != nil) {
|
||||
BOOL hasElapsed = (self.currentSeconds <= 0);
|
||||
self.completionBlock(hasElapsed);
|
||||
|
||||
MPLogInfo(@"MPCountdownTimerView completion block notified");
|
||||
}
|
||||
|
||||
// Clear out the completion block since the timer has stopped and it is
|
||||
// no longer needed for this instance.
|
||||
self.completionBlock = nil;
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
if (!self.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.isPaused = [self.timer pause];
|
||||
if (self.isPaused) {
|
||||
MPLogInfo(@"MPCountdownTimerView paused");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resume {
|
||||
if (!self.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self.timer resume]) {
|
||||
self.isPaused = NO;
|
||||
MPLogInfo(@"MPCountdownTimerView resumed");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Resources
|
||||
|
||||
- (NSString *)timerHtml {
|
||||
// Save the contents of the HTML into a static string since it will not change
|
||||
// across instances.
|
||||
static NSString * html = nil;
|
||||
|
||||
if (html == nil) {
|
||||
NSBundle * parentBundle = [NSBundle resourceBundleForClass:self.class];
|
||||
NSString * filepath = [parentBundle pathForResource:@"MPCountdownTimer" ofType:@"html"];
|
||||
html = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil];
|
||||
|
||||
if (html == nil) {
|
||||
MPLogError(@"Could not find MPCountdownTimer.html in bundle %@", parentBundle.bundlePath);
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
- (NSURL *)timerBaseUrl {
|
||||
// Save the base URL into a static string since it will not change
|
||||
// across instances.
|
||||
static NSURL * baseUrl = nil;
|
||||
|
||||
if (baseUrl == nil) {
|
||||
NSBundle * parentBundle = [NSBundle resourceBundleForClass:self.class];
|
||||
baseUrl = [NSURL fileURLWithPath:parentBundle.bundlePath];
|
||||
}
|
||||
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
#pragma mark - MPTimer
|
||||
|
||||
- (void)onTimerUpdate:(MPTimer *)sender {
|
||||
// Update the count.
|
||||
self.currentSeconds -= kCountdownTimerInterval;
|
||||
|
||||
NSString * jsToEvaluate = [NSString stringWithFormat:@"setCounterValue(%f);", self.currentSeconds];
|
||||
[self.timerView stringByEvaluatingJavaScriptFromString:jsToEvaluate];
|
||||
|
||||
// Stop the timer and notify the completion block.
|
||||
if (self.currentSeconds <= 0) {
|
||||
[self stopAndSignalCompletion:YES];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UIWebViewDelegate
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
||||
NSString * jsToEvaluate = [NSString stringWithFormat:@"setMaxCounterValue(%f); setCounterValue(%f);", self.currentSeconds, self.currentSeconds];
|
||||
[self.timerView stringByEvaluatingJavaScriptFromString:jsToEvaluate];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// MPProgressOverlayView.h
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 7/18/12.
|
||||
// Copyright 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@protocol MPProgressOverlayViewDelegate;
|
||||
|
||||
@interface MPProgressOverlayView : UIView {
|
||||
id<MPProgressOverlayViewDelegate> __weak _delegate;
|
||||
UIView *_outerContainer;
|
||||
UIView *_innerContainer;
|
||||
UIActivityIndicatorView *_activityIndicator;
|
||||
UIButton *_closeButton;
|
||||
CGPoint _closeButtonPortraitCenter;
|
||||
}
|
||||
|
||||
@property (nonatomic, weak) id<MPProgressOverlayViewDelegate> delegate;
|
||||
@property (nonatomic, strong) UIButton *closeButton;
|
||||
|
||||
- (id)initWithDelegate:(id<MPProgressOverlayViewDelegate>)delegate;
|
||||
- (void)show;
|
||||
- (void)hide;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol MPProgressOverlayViewDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
- (void)overlayCancelButtonPressed;
|
||||
- (void)overlayDidAppear;
|
||||
|
||||
@end
|
|
@ -1,325 +0,0 @@
|
|||
//
|
||||
// MPProgressOverlayView.m
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 7/18/12.
|
||||
// Copyright 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPProgressOverlayView.h"
|
||||
#import "MPGlobal.h"
|
||||
#import "MPLogging.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
static NSString * const kCloseButtonXImageName = @"MPCloseButtonX.png";
|
||||
|
||||
@interface MPProgressOverlayView ()
|
||||
|
||||
- (void)updateCloseButtonPosition;
|
||||
- (void)registerForDeviceOrientationNotifications;
|
||||
- (void)unregisterForDeviceOrientationNotifications;
|
||||
- (void)deviceOrientationDidChange:(NSNotification *)notification;
|
||||
- (void)setTransformForCurrentOrientationAnimated:(BOOL)animated;
|
||||
- (void)setTransformForAllSubviews:(CGAffineTransform)transform;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define kProgressOverlaySide 60.0
|
||||
#define kProgressOverlayBorderWidth 1.0
|
||||
#define kProgressOverlayCornerRadius 8.0
|
||||
#define kProgressOverlayShadowOpacity 0.8
|
||||
#define kProgressOverlayShadowRadius 8.0
|
||||
#define kProgressOverlayCloseButtonDelay 4.0
|
||||
|
||||
static void exponentialDecayInterpolation(void *info, const CGFloat *input, CGFloat *output);
|
||||
|
||||
@implementation MPProgressOverlayView
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize closeButton = _closeButton;
|
||||
|
||||
- (id)initWithDelegate:(id<MPProgressOverlayViewDelegate>)delegate
|
||||
{
|
||||
self = [self initWithFrame:MPKeyWindow().bounds];
|
||||
if (self) {
|
||||
self.delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.alpha = 0.0;
|
||||
self.opaque = NO;
|
||||
|
||||
// Close button.
|
||||
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
_closeButton.alpha = 0.0;
|
||||
_closeButton.hidden = YES;
|
||||
[_closeButton addTarget:self
|
||||
action:@selector(closeButtonPressed)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
UIImage *image = [UIImage imageNamed:MPResourcePathForResource(kCloseButtonXImageName)];
|
||||
[_closeButton setImage:image forState:UIControlStateNormal];
|
||||
[_closeButton sizeToFit];
|
||||
|
||||
_closeButtonPortraitCenter =
|
||||
CGPointMake(self.bounds.size.width - 6.0 - CGRectGetMidX(_closeButton.bounds),
|
||||
6.0 + CGRectGetMidY(_closeButton.bounds));
|
||||
|
||||
_closeButton.center = _closeButtonPortraitCenter;
|
||||
[self addSubview:_closeButton];
|
||||
|
||||
// Progress indicator container.
|
||||
CGRect outerFrame = CGRectMake(0, 0, kProgressOverlaySide, kProgressOverlaySide);
|
||||
_outerContainer = [[UIView alloc] initWithFrame:outerFrame];
|
||||
_outerContainer.alpha = 0.6;
|
||||
_outerContainer.backgroundColor = [UIColor whiteColor];
|
||||
_outerContainer.center = self.center;
|
||||
_outerContainer.frame = CGRectIntegral(_outerContainer.frame);
|
||||
_outerContainer.opaque = NO;
|
||||
_outerContainer.layer.cornerRadius = kProgressOverlayCornerRadius;
|
||||
if ([_outerContainer.layer respondsToSelector:@selector(setShadowColor:)]) {
|
||||
_outerContainer.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
_outerContainer.layer.shadowOffset = CGSizeMake(0.0f, kProgressOverlayShadowRadius - 2.0f);
|
||||
_outerContainer.layer.shadowOpacity = kProgressOverlayShadowOpacity;
|
||||
_outerContainer.layer.shadowRadius = kProgressOverlayShadowRadius;
|
||||
}
|
||||
[self addSubview:_outerContainer];
|
||||
|
||||
CGFloat innerSide = kProgressOverlaySide - 2 * kProgressOverlayBorderWidth;
|
||||
CGRect innerFrame = CGRectMake(0, 0, innerSide, innerSide);
|
||||
_innerContainer = [[UIView alloc] initWithFrame:innerFrame];
|
||||
_innerContainer.backgroundColor = [UIColor blackColor];
|
||||
_innerContainer.center = CGPointMake(CGRectGetMidX(_outerContainer.bounds),
|
||||
CGRectGetMidY(_outerContainer.bounds));
|
||||
_innerContainer.frame = CGRectIntegral(_innerContainer.frame);
|
||||
_innerContainer.layer.cornerRadius =
|
||||
kProgressOverlayCornerRadius - kProgressOverlayBorderWidth;
|
||||
_innerContainer.opaque = NO;
|
||||
[_outerContainer addSubview:_innerContainer];
|
||||
|
||||
// Progress indicator.
|
||||
|
||||
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:
|
||||
UIActivityIndicatorViewStyleWhiteLarge];
|
||||
[_activityIndicator sizeToFit];
|
||||
[_activityIndicator startAnimating];
|
||||
_activityIndicator.center = self.center;
|
||||
_activityIndicator.frame = CGRectIntegral(_activityIndicator.frame);
|
||||
[self addSubview:_activityIndicator];
|
||||
|
||||
[self registerForDeviceOrientationNotifications];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self unregisterForDeviceOrientationNotifications];
|
||||
}
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
- (void)show
|
||||
{
|
||||
[MPKeyWindow() addSubview:self];
|
||||
|
||||
[self setTransformForCurrentOrientationAnimated:NO];
|
||||
|
||||
if (MP_ANIMATED) {
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
self.alpha = 1.0;
|
||||
} completion:^(BOOL finished) {
|
||||
if ([self.delegate respondsToSelector:@selector(overlayDidAppear)]) {
|
||||
[self.delegate overlayDidAppear];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
self.alpha = 1.0;
|
||||
if ([self.delegate respondsToSelector:@selector(overlayDidAppear)]) {
|
||||
[self.delegate overlayDidAppear];
|
||||
}
|
||||
}
|
||||
|
||||
[self performSelector:@selector(enableCloseButton)
|
||||
withObject:nil
|
||||
afterDelay:kProgressOverlayCloseButtonDelay];
|
||||
}
|
||||
|
||||
- (void)hide
|
||||
{
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(enableCloseButton) object:nil];
|
||||
|
||||
self.closeButton.hidden = YES;
|
||||
self.closeButton.alpha = 0.0f;
|
||||
|
||||
if (MP_ANIMATED) {
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
self.alpha = 0.0;
|
||||
} completion:^(BOOL finished) {
|
||||
[self removeFromSuperview];
|
||||
}];
|
||||
} else {
|
||||
self.alpha = 0.0;
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Drawing and Layout
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
static const CGFloat input_value_range[2] = {0, 1};
|
||||
static const CGFloat output_value_range[8] = {0, 1, 0, 1, 0, 1, 0, 1};
|
||||
CGFunctionCallbacks callbacks = {0, exponentialDecayInterpolation, NULL};
|
||||
|
||||
CGFunctionRef shadingFunction = CGFunctionCreate((__bridge void *)(self), 1, input_value_range, 4,
|
||||
output_value_range, &callbacks);
|
||||
|
||||
CGPoint startPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
|
||||
CGFloat startRadius = 0.0;
|
||||
CGPoint endPoint = startPoint;
|
||||
CGFloat endRadius = MAX(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) / 2;
|
||||
|
||||
CGShadingRef shading = CGShadingCreateRadial(colorSpace, startPoint, startRadius, endPoint,
|
||||
endRadius, shadingFunction,
|
||||
YES, // extend shading beyond starting circle
|
||||
YES); // extend shading beyond ending circle
|
||||
CGContextDrawShading(context, shading);
|
||||
|
||||
CGShadingRelease(shading);
|
||||
CGFunctionRelease(shadingFunction);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
|
||||
#define kGradientMaximumAlphaValue 0.90
|
||||
#define kGradientAlphaDecayFactor 1.1263
|
||||
|
||||
static void exponentialDecayInterpolation(void *info, const CGFloat *input, CGFloat *output)
|
||||
{
|
||||
// output is an RGBA array corresponding to the color black with an alpha value somewhere on
|
||||
// our exponential decay curve.
|
||||
CGFloat progress = *input;
|
||||
output[0] = 0.0;
|
||||
output[1] = 0.0;
|
||||
output[2] = 0.0;
|
||||
output[3] = kGradientMaximumAlphaValue - exp(-progress / kGradientAlphaDecayFactor);
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[self updateCloseButtonPosition];
|
||||
}
|
||||
|
||||
- (void)updateCloseButtonPosition
|
||||
{
|
||||
// Ensure that the close button is anchored to the top-right corner of the screen.
|
||||
|
||||
CGPoint originalCenter = _closeButtonPortraitCenter;
|
||||
CGPoint center = originalCenter;
|
||||
BOOL statusBarHidden = [UIApplication sharedApplication].statusBarHidden;
|
||||
CGFloat statusBarOffset = (statusBarHidden) ? 0.0 : 20.0;
|
||||
|
||||
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
switch (orientation) {
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
center.x = CGRectGetMaxX(self.bounds) - originalCenter.x + statusBarOffset;
|
||||
center.y = originalCenter.y;
|
||||
break;
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
center.x = originalCenter.x - statusBarOffset;
|
||||
center.y = CGRectGetMaxY(self.bounds) - originalCenter.y;
|
||||
break;
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
center.x = CGRectGetMaxX(self.bounds) - originalCenter.x;
|
||||
center.y = CGRectGetMaxY(self.bounds) - originalCenter.y - statusBarOffset;
|
||||
break;
|
||||
default:
|
||||
center.y = originalCenter.y + statusBarOffset;
|
||||
break;
|
||||
}
|
||||
|
||||
_closeButton.center = center;
|
||||
}
|
||||
|
||||
#pragma mark - Internal
|
||||
|
||||
- (void)registerForDeviceOrientationNotifications
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(deviceOrientationDidChange:)
|
||||
name:UIDeviceOrientationDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)unregisterForDeviceOrientationNotifications
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIDeviceOrientationDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)deviceOrientationDidChange:(NSNotification *)notification
|
||||
{
|
||||
[self setTransformForCurrentOrientationAnimated:YES];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)enableCloseButton
|
||||
{
|
||||
_closeButton.hidden = NO;
|
||||
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
_closeButton.alpha = 1.0;
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
- (void)closeButtonPressed
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(overlayCancelButtonPressed)]) {
|
||||
[_delegate overlayCancelButtonPressed];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTransformForCurrentOrientationAnimated:(BOOL)animated
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
float angle = 0;
|
||||
if (UIInterfaceOrientationIsPortrait(orientation)) {
|
||||
if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
||||
angle = M_PI;
|
||||
}
|
||||
} else {
|
||||
if (orientation == UIInterfaceOrientationLandscapeLeft) {
|
||||
angle = -M_PI_2;
|
||||
} else {
|
||||
angle = M_PI_2;
|
||||
}
|
||||
}
|
||||
|
||||
if (animated) {
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[self setTransformForAllSubviews:CGAffineTransformMakeRotation(angle)];
|
||||
[UIView commitAnimations];
|
||||
} else {
|
||||
[self setTransformForAllSubviews:CGAffineTransformMakeRotation(angle)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTransformForAllSubviews:(CGAffineTransform)transform
|
||||
{
|
||||
for (UIView *view in self.subviews) {
|
||||
view.transform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// MPVideoConfig.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPVASTResponse.h"
|
||||
|
||||
@interface MPVideoConfig : NSObject
|
||||
|
||||
@property (nonatomic, readonly) NSURL *mediaURL;
|
||||
@property (nonatomic, readonly) NSURL *clickThroughURL;
|
||||
@property (nonatomic, readonly) NSArray *clickTrackingURLs;
|
||||
@property (nonatomic, readonly) NSArray *errorURLs;
|
||||
@property (nonatomic, readonly) NSArray *impressionURLs;
|
||||
|
||||
/** @name Tracking Events */
|
||||
|
||||
@property (nonatomic, readonly) NSArray *creativeViewTrackers;
|
||||
@property (nonatomic, readonly) NSArray *startTrackers;
|
||||
@property (nonatomic, readonly) NSArray *firstQuartileTrackers;
|
||||
@property (nonatomic, readonly) NSArray *midpointTrackers;
|
||||
@property (nonatomic, readonly) NSArray *thirdQuartileTrackers;
|
||||
@property (nonatomic, readonly) NSArray *completionTrackers;
|
||||
@property (nonatomic, readonly) NSArray *muteTrackers;
|
||||
@property (nonatomic, readonly) NSArray *unmuteTrackers;
|
||||
@property (nonatomic, readonly) NSArray *pauseTrackers;
|
||||
@property (nonatomic, readonly) NSArray *rewindTrackers;
|
||||
@property (nonatomic, readonly) NSArray *resumeTrackers;
|
||||
@property (nonatomic, readonly) NSArray *fullscreenTrackers;
|
||||
@property (nonatomic, readonly) NSArray *exitFullscreenTrackers;
|
||||
@property (nonatomic, readonly) NSArray *expandTrackers;
|
||||
@property (nonatomic, readonly) NSArray *collapseTrackers;
|
||||
@property (nonatomic, readonly) NSArray *acceptInvitationLinearTrackers;
|
||||
@property (nonatomic, readonly) NSArray *closeLinearTrackers;
|
||||
@property (nonatomic, readonly) NSArray *skipTrackers;
|
||||
@property (nonatomic, readonly) NSArray *otherProgressTrackers;
|
||||
|
||||
/** @name Viewability */
|
||||
|
||||
@property (nonatomic, readonly) NSTimeInterval minimumViewabilityTimeInterval;
|
||||
@property (nonatomic, readonly) double minimumFractionOfVideoVisible;
|
||||
@property (nonatomic, readonly) NSURL *viewabilityTrackingURL;
|
||||
|
||||
- (instancetype)initWithVASTResponse:(MPVASTResponse *)response additionalTrackers:(NSDictionary *)additionalTrackers;
|
||||
|
||||
@end
|
|
@ -1,119 +0,0 @@
|
|||
//
|
||||
// MPHTMLInterstitialCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPHTMLInterstitialCustomEvent.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPAdConfiguration.h"
|
||||
#import "MPInstanceProvider.h"
|
||||
|
||||
@interface MPHTMLInterstitialCustomEvent ()
|
||||
|
||||
@property (nonatomic, strong) MPHTMLInterstitialViewController *interstitial;
|
||||
@property (nonatomic, assign) BOOL trackedImpression;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPHTMLInterstitialCustomEvent
|
||||
|
||||
@synthesize interstitial = _interstitial;
|
||||
|
||||
- (BOOL)enableAutomaticImpressionAndClickTracking
|
||||
{
|
||||
// An HTML interstitial tracks its own clicks. Turn off automatic tracking to prevent the tap event callback
|
||||
// from generating an additional click.
|
||||
// However, an HTML interstitial does not track its own impressions so we must manually do it in this class.
|
||||
// See interstitialDidAppear:
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info
|
||||
{
|
||||
MPLogInfo(@"Loading MoPub HTML interstitial");
|
||||
MPAdConfiguration *configuration = [self.delegate configuration];
|
||||
MPLogTrace(@"Loading HTML interstitial with source: %@", [configuration adResponseHTMLString]);
|
||||
|
||||
self.interstitial = [[MPInstanceProvider sharedProvider] buildMPHTMLInterstitialViewControllerWithDelegate:self
|
||||
orientationType:configuration.orientationType];
|
||||
[self.interstitial loadConfiguration:configuration];
|
||||
}
|
||||
|
||||
- (void)showInterstitialFromRootViewController:(UIViewController *)rootViewController
|
||||
{
|
||||
[self.interstitial presentInterstitialFromViewController:rootViewController];
|
||||
}
|
||||
|
||||
#pragma mark - MPInterstitialViewControllerDelegate
|
||||
|
||||
- (CLLocation *)location
|
||||
{
|
||||
return [self.delegate location];
|
||||
}
|
||||
|
||||
- (NSString *)adUnitId
|
||||
{
|
||||
return [self.delegate adUnitId];
|
||||
}
|
||||
|
||||
- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial did load");
|
||||
[self.delegate interstitialCustomEvent:self didLoadAd:self.interstitial];
|
||||
}
|
||||
|
||||
- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial did fail");
|
||||
[self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
}
|
||||
|
||||
- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial will appear");
|
||||
[self.delegate interstitialCustomEventWillAppear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial did appear");
|
||||
[self.delegate interstitialCustomEventDidAppear:self];
|
||||
|
||||
if (!self.trackedImpression) {
|
||||
self.trackedImpression = YES;
|
||||
[self.delegate trackImpression];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial will disappear");
|
||||
[self.delegate interstitialCustomEventWillDisappear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial did disappear");
|
||||
[self.delegate interstitialCustomEventDidDisappear:self];
|
||||
|
||||
// Deallocate the interstitial as we don't need it anymore. If we don't deallocate the interstitial after dismissal,
|
||||
// then the html in the webview will continue to run which could lead to bugs such as continuing to play the sound of an inline
|
||||
// video since the app may hold onto the interstitial ad controller. Moreover, we keep an array of controllers around as well.
|
||||
self.interstitial = nil;
|
||||
}
|
||||
|
||||
- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial did receive tap event");
|
||||
[self.delegate interstitialCustomEventDidReceiveTapEvent:self];
|
||||
}
|
||||
|
||||
- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub HTML interstitial will leave application");
|
||||
[self.delegate interstitialCustomEventWillLeaveApplication:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,642 +0,0 @@
|
|||
//
|
||||
// MPWebView.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2016 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPWebView.h"
|
||||
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
static BOOL const kMoPubAllowsInlineMediaPlaybackDefault = YES;
|
||||
static BOOL const kMoPubRequiresUserActionForMediaPlaybackDefault = NO;
|
||||
|
||||
// Set defaults for this as its default differs between UIWebView and WKWebView
|
||||
static BOOL const kMoPubAllowsLinkPreviewDefault = NO;
|
||||
|
||||
static NSString *const kMoPubJavaScriptDisableDialogScript = @"window.alert = function() { }; window.prompt = function() { }; window.confirm = function() { };";
|
||||
|
||||
static NSString *const kMoPubFrameKeyPathString = @"frame";
|
||||
|
||||
static BOOL gForceWKWebView = NO;
|
||||
|
||||
@interface MPWebView () <UIWebViewDelegate, WKNavigationDelegate, WKUIDelegate, UIScrollViewDelegate>
|
||||
|
||||
@property (weak, nonatomic) WKWebView *wkWebView;
|
||||
@property (weak, nonatomic) UIWebView *uiWebView;
|
||||
|
||||
@property (strong, nonatomic) NSArray<NSLayoutConstraint *> *wkWebViewLayoutConstraints;
|
||||
|
||||
@property (nonatomic, assign) BOOL hasMovedToWindow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPWebView
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
[self setUpStepsForceUIWebView:NO];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if (self = [super initWithCoder:aDecoder]) {
|
||||
[self setUpStepsForceUIWebView:NO];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self setUpStepsForceUIWebView:NO];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame forceUIWebView:(BOOL)forceUIWebView {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self setUpStepsForceUIWebView:forceUIWebView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setUpStepsForceUIWebView:(BOOL)forceUIWebView {
|
||||
// set up web view
|
||||
UIView *webView;
|
||||
|
||||
if ((gForceWKWebView || !forceUIWebView) && [WKWebView class]) {
|
||||
WKUserContentController *contentController = [[WKUserContentController alloc] init];
|
||||
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
|
||||
config.allowsInlineMediaPlayback = kMoPubAllowsInlineMediaPlaybackDefault;
|
||||
if (@available(iOS 9.0, *)) {
|
||||
config.requiresUserActionForMediaPlayback = kMoPubRequiresUserActionForMediaPlaybackDefault;
|
||||
} else {
|
||||
config.mediaPlaybackRequiresUserAction = kMoPubRequiresUserActionForMediaPlaybackDefault;
|
||||
}
|
||||
config.userContentController = contentController;
|
||||
|
||||
WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:self.bounds configuration:config];
|
||||
|
||||
wkWebView.UIDelegate = self;
|
||||
wkWebView.navigationDelegate = self;
|
||||
|
||||
webView = wkWebView;
|
||||
|
||||
self.wkWebView = wkWebView;
|
||||
|
||||
// Put WKWebView onto the offscreen view so any loading will complete correctly; see comment below.
|
||||
[self retainWKWebViewOffscreen:wkWebView];
|
||||
} else {
|
||||
UIWebView *uiWebView = [[UIWebView alloc] initWithFrame:self.bounds];
|
||||
|
||||
uiWebView.allowsInlineMediaPlayback = kMoPubAllowsInlineMediaPlaybackDefault;
|
||||
uiWebView.mediaPlaybackRequiresUserAction = kMoPubRequiresUserActionForMediaPlaybackDefault;
|
||||
|
||||
uiWebView.delegate = self;
|
||||
|
||||
webView = uiWebView;
|
||||
|
||||
self.uiWebView = uiWebView;
|
||||
|
||||
[self addSubview:webView];
|
||||
}
|
||||
|
||||
webView.backgroundColor = [UIColor clearColor];
|
||||
webView.opaque = NO;
|
||||
|
||||
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
// set default scalesPageToFit
|
||||
self.scalesPageToFit = NO;
|
||||
|
||||
// set default `shouldConformToSafeArea`
|
||||
self.shouldConformToSafeArea = NO;
|
||||
|
||||
// configure like the old MPAdWebView
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.opaque = NO;
|
||||
|
||||
// set default for allowsLinkPreview as they're different between WKWebView and UIWebView
|
||||
self.allowsLinkPreview = kMoPubAllowsLinkPreviewDefault;
|
||||
|
||||
// set up KVO to adjust the frame of the WKWebView to avoid white screens
|
||||
if (self.wkWebView) {
|
||||
[self addObserver:self
|
||||
forKeyPath:kMoPubFrameKeyPathString
|
||||
options:NSKeyValueObservingOptionOld
|
||||
context:NULL];
|
||||
}
|
||||
}
|
||||
|
||||
// WKWebView won't load/execute javascript unless it's on the view hierarchy. Because the MoPub SDK uses a lot of
|
||||
// javascript before adding the view to the hierarchy, let's stick the WKWebView into an offscreen-but-on-the-window
|
||||
// view, and move it to self when self gets a window.
|
||||
static UIView *gOffscreenView = nil;
|
||||
|
||||
- (void)retainWKWebViewOffscreen:(WKWebView *)webView {
|
||||
if (!gOffscreenView) {
|
||||
gOffscreenView = [self constructOffscreenView];
|
||||
}
|
||||
[gOffscreenView addSubview:webView];
|
||||
}
|
||||
|
||||
- (void)cleanUpOffscreenView {
|
||||
if (gOffscreenView.subviews.count == 0) {
|
||||
[gOffscreenView removeFromSuperview];
|
||||
gOffscreenView = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)constructOffscreenView {
|
||||
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
view.clipsToBounds = YES;
|
||||
|
||||
UIWindow *appWindow = [[UIApplication sharedApplication] keyWindow];
|
||||
[appWindow addSubview:view];
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow {
|
||||
// If using WKWebView, and if MPWebView is in the view hierarchy, and if the WKWebView is in the offscreen view currently,
|
||||
// move our WKWebView to self and deallocate OffscreenView if no other MPWebView is using it.
|
||||
if (self.wkWebView
|
||||
&& !self.hasMovedToWindow
|
||||
&& self.window != nil
|
||||
&& [self.wkWebView.superview isEqual:gOffscreenView]) {
|
||||
self.wkWebView.frame = self.bounds;
|
||||
[self addSubview:self.wkWebView];
|
||||
[self constrainWebViewShouldUseSafeArea:self.shouldConformToSafeArea];
|
||||
self.hasMovedToWindow = YES;
|
||||
|
||||
// Don't keep OffscreenView if we don't need it; it can always be re-allocated again later
|
||||
[self cleanUpOffscreenView];
|
||||
}
|
||||
}
|
||||
|
||||
// Occasionally, we encounter an issue where, when MPWebView is initialized at a different frame size than when it's shown,
|
||||
// the WKWebView shows as all white because it doesn't have a chance to get redrawn at the new size before getting shown.
|
||||
// This makes sure WKWebView is always already rendered at the correct size when it gets moved to the window.
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context {
|
||||
// Only keep the wkWebView up-to-date if its superview is the offscreen view.
|
||||
// If it's attached to self, the autoresizing mask should come into play & this is just extra work.
|
||||
if ([keyPath isEqualToString:kMoPubFrameKeyPathString]
|
||||
&& [self.wkWebView.superview isEqual:gOffscreenView]) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
// In iOS 11, WKWebView loads web view contents into the safe area only unless `viewport-fit=cover` is
|
||||
// included in the page's viewport tag. Also, as of iOS 11, it appears WKWebView does not redraw page
|
||||
// contents to match the safe area of a new position after being moved. As a result, making `wkWebView`'s
|
||||
// X/Y coordinates (0,0) can introduce an issue on iPhone X where banners do not load inside of
|
||||
// `wkWebView`'s bounds, even if the banner is moved into the safe area after loading.
|
||||
//
|
||||
// To skirt around these problems, always put `wkWebView` into the safe area when using iOS 11 or later.
|
||||
self.wkWebView.frame = CGRectMake(gOffscreenView.safeAreaInsets.left,
|
||||
gOffscreenView.safeAreaInsets.top,
|
||||
CGRectGetWidth(self.bounds),
|
||||
CGRectGetHeight(self.bounds));
|
||||
} else {
|
||||
self.wkWebView.frame = self.bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// Remove KVO observer
|
||||
if (self.wkWebView) {
|
||||
[self removeObserver:self forKeyPath:kMoPubFrameKeyPathString];
|
||||
}
|
||||
|
||||
// Avoids EXC_BAD_INSTRUCTION crash
|
||||
self.wkWebView.scrollView.delegate = nil;
|
||||
|
||||
// Be sure our WKWebView doesn't stay stuck to the static OffscreenView
|
||||
[self.wkWebView removeFromSuperview];
|
||||
// Deallocate OffscreenView if needed
|
||||
[self cleanUpOffscreenView];
|
||||
}
|
||||
|
||||
- (void)setShouldConformToSafeArea:(BOOL)shouldConformToSafeArea {
|
||||
_shouldConformToSafeArea = shouldConformToSafeArea;
|
||||
|
||||
if (self.hasMovedToWindow) {
|
||||
[self constrainWebViewShouldUseSafeArea:shouldConformToSafeArea];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)constrainWebViewShouldUseSafeArea:(BOOL)shouldUseSafeArea {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
self.wkWebView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
|
||||
if (self.wkWebViewLayoutConstraints) {
|
||||
[NSLayoutConstraint deactivateConstraints:self.wkWebViewLayoutConstraints];
|
||||
}
|
||||
|
||||
if (shouldUseSafeArea) {
|
||||
self.wkWebViewLayoutConstraints = @[
|
||||
[self.wkWebView.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor],
|
||||
[self.wkWebView.leadingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leadingAnchor],
|
||||
[self.wkWebView.trailingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.trailingAnchor],
|
||||
[self.wkWebView.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor],
|
||||
];
|
||||
} else {
|
||||
self.wkWebViewLayoutConstraints = @[
|
||||
[self.wkWebView.topAnchor constraintEqualToAnchor:self.topAnchor],
|
||||
[self.wkWebView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
|
||||
[self.wkWebView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
|
||||
[self.wkWebView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
|
||||
];
|
||||
}
|
||||
|
||||
[NSLayoutConstraint activateConstraints:self.wkWebViewLayoutConstraints];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isLoading {
|
||||
return self.uiWebView ? self.uiWebView.isLoading : self.wkWebView.isLoading;
|
||||
}
|
||||
|
||||
- (void)loadData:(NSData *)data
|
||||
MIMEType:(NSString *)MIMEType
|
||||
textEncodingName:(NSString *)encodingName
|
||||
baseURL:(NSURL *)baseURL {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView loadData:data
|
||||
MIMEType:MIMEType
|
||||
textEncodingName:encodingName
|
||||
baseURL:baseURL];
|
||||
} else if (@available(iOS 9.0, *)) {
|
||||
[self.wkWebView loadData:data
|
||||
MIMEType:MIMEType
|
||||
characterEncodingName:encodingName
|
||||
baseURL:baseURL];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)forceWKWebView:(BOOL)shouldForce
|
||||
{
|
||||
gForceWKWebView = shouldForce;
|
||||
}
|
||||
|
||||
+ (BOOL)isForceWKWebView
|
||||
{
|
||||
return gForceWKWebView;
|
||||
}
|
||||
|
||||
- (void)loadHTMLString:(NSString *)string
|
||||
baseURL:(NSURL *)baseURL {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView loadHTMLString:string
|
||||
baseURL:baseURL];
|
||||
} else {
|
||||
[self.wkWebView loadHTMLString:string
|
||||
baseURL:baseURL];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadRequest:(NSURLRequest *)request {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView loadRequest:request];
|
||||
} else {
|
||||
[self.wkWebView loadRequest:request];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopLoading {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView stopLoading];
|
||||
} else {
|
||||
[self.wkWebView stopLoading];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reload {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView reload];
|
||||
} else {
|
||||
[self.wkWebView reload];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)canGoBack {
|
||||
return self.uiWebView ? self.uiWebView.canGoBack : self.wkWebView.canGoBack;
|
||||
}
|
||||
|
||||
- (BOOL)canGoForward {
|
||||
return self.uiWebView ? self.uiWebView.canGoForward : self.wkWebView.canGoForward;
|
||||
}
|
||||
|
||||
- (void)goBack {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView goBack];
|
||||
} else {
|
||||
[self.wkWebView goBack];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)goForward {
|
||||
if (self.uiWebView) {
|
||||
[self.uiWebView goForward];
|
||||
} else {
|
||||
[self.wkWebView goForward];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setAllowsLinkPreview:(BOOL)allowsLinkPreview {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
if (self.uiWebView) {
|
||||
self.uiWebView.allowsLinkPreview = allowsLinkPreview;
|
||||
} else {
|
||||
self.wkWebView.allowsLinkPreview = allowsLinkPreview;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)allowsLinkPreview {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
if (self.uiWebView) {
|
||||
return self.uiWebView.allowsLinkPreview;
|
||||
} else {
|
||||
return self.wkWebView.allowsLinkPreview;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setScalesPageToFit:(BOOL)scalesPageToFit {
|
||||
if (self.uiWebView) {
|
||||
self.uiWebView.scalesPageToFit = scalesPageToFit;
|
||||
} else {
|
||||
if (scalesPageToFit) {
|
||||
self.wkWebView.scrollView.delegate = nil;
|
||||
|
||||
[self.wkWebView.configuration.userContentController removeAllUserScripts];
|
||||
} else {
|
||||
// Make sure the scroll view can't scroll (prevent double tap to zoom)
|
||||
self.wkWebView.scrollView.delegate = self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)scalesPageToFit {
|
||||
return self.uiWebView ? self.uiWebView.scalesPageToFit : self.scrollView.delegate == nil;
|
||||
}
|
||||
|
||||
- (UIScrollView *)scrollView {
|
||||
return self.uiWebView ? self.uiWebView.scrollView : self.wkWebView.scrollView;
|
||||
}
|
||||
|
||||
- (void)evaluateJavaScript:(NSString *)javaScriptString
|
||||
completionHandler:(MPWebViewJavascriptEvaluationCompletionHandler)completionHandler {
|
||||
if (self.uiWebView) {
|
||||
NSString *resultString = [self.uiWebView stringByEvaluatingJavaScriptFromString:javaScriptString];
|
||||
|
||||
if (completionHandler) {
|
||||
completionHandler(resultString, nil);
|
||||
}
|
||||
} else {
|
||||
[self.wkWebView evaluateJavaScript:javaScriptString
|
||||
completionHandler:completionHandler];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)javaScriptString {
|
||||
if (self.uiWebView) {
|
||||
return [self.uiWebView stringByEvaluatingJavaScriptFromString:javaScriptString];
|
||||
} else {
|
||||
// There is no way to reliably wait for `evaluateJavaScript:completionHandler:` to finish without risk of
|
||||
// deadlocking the main thread. This method is called on the main thread and the completion block is also
|
||||
// called on the main thread.
|
||||
// Instead of waiting, just fire and return an empty string.
|
||||
|
||||
// Methods attempted:
|
||||
// libdispatch dispatch groups
|
||||
// http://stackoverflow.com/questions/17920169/how-to-wait-for-method-that-has-completion-block-all-on-main-thread
|
||||
|
||||
[self.wkWebView evaluateJavaScript:javaScriptString completionHandler:nil];
|
||||
return @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)allowsInlineMediaPlayback {
|
||||
return self.uiWebView ? self.uiWebView.allowsInlineMediaPlayback : self.wkWebView.configuration.allowsInlineMediaPlayback;
|
||||
}
|
||||
|
||||
- (BOOL)mediaPlaybackRequiresUserAction {
|
||||
if (self.uiWebView) {
|
||||
return self.uiWebView.mediaPlaybackRequiresUserAction;
|
||||
} else {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
return self.wkWebView.configuration.requiresUserActionForMediaPlayback;
|
||||
} else if (![self.wkWebView.configuration respondsToSelector:@selector(requiresUserActionForMediaPlayback)]) {
|
||||
return self.wkWebView.configuration.mediaPlaybackRequiresUserAction;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)mediaPlaybackAllowsAirPlay {
|
||||
if (self.uiWebView) {
|
||||
return self.uiWebView.mediaPlaybackAllowsAirPlay;
|
||||
} else {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
return self.wkWebView.configuration.allowsAirPlayForMediaPlayback;
|
||||
} else if (![self.wkWebView.configuration respondsToSelector:@selector(allowsAirPlayForMediaPlayback)]) {
|
||||
return self.wkWebView.configuration.mediaPlaybackAllowsAirPlay;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)allowsPictureInPictureMediaPlayback {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
if (self.uiWebView) {
|
||||
return self.uiWebView.allowsPictureInPictureMediaPlayback;
|
||||
} else {
|
||||
return self.wkWebView.configuration.allowsPictureInPictureMediaPlayback;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - UIWebViewDelegate
|
||||
|
||||
- (BOOL)webView:(UIWebView *)webView
|
||||
shouldStartLoadWithRequest:(NSURLRequest *)request
|
||||
navigationType:(UIWebViewNavigationType)navigationType {
|
||||
if ([self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
|
||||
return [self.delegate webView:self
|
||||
shouldStartLoadWithRequest:request
|
||||
navigationType:navigationType];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)webViewDidStartLoad:(UIWebView *)webView {
|
||||
if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
|
||||
[self.delegate webViewDidStartLoad:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
||||
if ([self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
|
||||
[self.delegate webViewDidFinishLoad:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
|
||||
if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
|
||||
[self.delegate webView:self didFailLoadWithError:error];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UIWebView+MPAdditions methods
|
||||
|
||||
/// Find all subviews that are UIScrollViews or subclasses and set their scrolling and bounce.
|
||||
- (void)mp_setScrollable:(BOOL)scrollable {
|
||||
UIScrollView *scrollView = self.scrollView;
|
||||
scrollView.scrollEnabled = scrollable;
|
||||
scrollView.bounces = scrollable;
|
||||
}
|
||||
|
||||
/// Redefine alert, prompt, and confirm to do nothing
|
||||
- (void)disableJavaScriptDialogs
|
||||
{
|
||||
if (self.uiWebView) { // Only redefine on UIWebView, as the WKNavigationDelegate for WKWebView takes care of this.
|
||||
[self stringByEvaluatingJavaScriptFromString:kMoPubJavaScriptDisableDialogScript];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - WKNavigationDelegate
|
||||
|
||||
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
|
||||
if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
|
||||
[self.delegate webViewDidStartLoad:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
||||
if ([self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
|
||||
[self.delegate webViewDidFinishLoad:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
didFailNavigation:(WKNavigation *)navigation
|
||||
withError:(NSError *)error {
|
||||
if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
|
||||
[self.delegate webView:self didFailLoadWithError:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
didFailProvisionalNavigation:(WKNavigation *)navigation
|
||||
withError:(NSError *)error {
|
||||
if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
|
||||
[self.delegate webView:self didFailLoadWithError:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
|
||||
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
|
||||
WKNavigationActionPolicy policy = WKNavigationActionPolicyAllow;
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
|
||||
NSURLRequest *request = navigationAction.request;
|
||||
UIWebViewNavigationType navType;
|
||||
switch (navigationAction.navigationType) {
|
||||
case WKNavigationTypeLinkActivated:
|
||||
navType = UIWebViewNavigationTypeLinkClicked;
|
||||
break;
|
||||
case WKNavigationTypeFormSubmitted:
|
||||
navType = UIWebViewNavigationTypeFormSubmitted;
|
||||
break;
|
||||
case WKNavigationTypeBackForward:
|
||||
navType = UIWebViewNavigationTypeBackForward;
|
||||
break;
|
||||
case WKNavigationTypeReload:
|
||||
navType = UIWebViewNavigationTypeReload;
|
||||
break;
|
||||
case WKNavigationTypeFormResubmitted:
|
||||
navType = UIWebViewNavigationTypeFormResubmitted;
|
||||
break;
|
||||
default:
|
||||
navType = UIWebViewNavigationTypeOther;
|
||||
break;
|
||||
}
|
||||
|
||||
policy = [self.delegate webView:self
|
||||
shouldStartLoadWithRequest:request
|
||||
navigationType:navType] ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel;
|
||||
}
|
||||
|
||||
decisionHandler(policy);
|
||||
}
|
||||
|
||||
- (WKWebView *)webView:(WKWebView *)webView
|
||||
createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
|
||||
forNavigationAction:(WKNavigationAction *)navigationAction
|
||||
windowFeatures:(WKWindowFeatures *)windowFeatures {
|
||||
// Open any links to new windows in the current WKWebView rather than create a new one
|
||||
if (!navigationAction.targetFrame.isMainFrame) {
|
||||
[webView loadRequest:navigationAction.request];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
// Avoid double tap to zoom in WKWebView
|
||||
// Delegate is only set when scalesPagesToFit is set to NO
|
||||
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - WKUIDelegate
|
||||
|
||||
// WKUIDelegate method implementations makes it so that, if a WKWebView is being used, javascript dialog boxes can
|
||||
// never show. They're programatically dismissed with the "Cancel" option (if there is any such option) before showing
|
||||
// a view.
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
runJavaScriptAlertPanelWithMessage:(NSString *)message
|
||||
initiatedByFrame:(WKFrameInfo *)frame
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED < MP_IOS_9_0 // This pre-processor code is to be sure we can compile under both iOS 8 and 9 SDKs
|
||||
completionHandler:(void (^)())completionHandler {
|
||||
#else
|
||||
completionHandler:(void (^)(void))completionHandler {
|
||||
#endif
|
||||
completionHandler();
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
runJavaScriptConfirmPanelWithMessage:(NSString *)message
|
||||
initiatedByFrame:(WKFrameInfo *)frame
|
||||
completionHandler:(void (^)(BOOL))completionHandler {
|
||||
completionHandler(NO);
|
||||
}
|
||||
|
||||
- (void)webView:(WKWebView *)webView
|
||||
runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
|
||||
defaultText:(NSString *)defaultText
|
||||
initiatedByFrame:(WKFrameInfo *)frame
|
||||
completionHandler:(void (^)(NSString *result))completionHandler {
|
||||
completionHandler(nil);
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,233 +0,0 @@
|
|||
//
|
||||
// MPInterstitialAdManager.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "MPInterstitialAdManager.h"
|
||||
|
||||
#import "MPAdServerURLBuilder.h"
|
||||
#import "MPInterstitialAdController.h"
|
||||
#import "MPInterstitialCustomEventAdapter.h"
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
#import "MPInterstitialAdManagerDelegate.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPError.h"
|
||||
|
||||
@interface MPInterstitialAdManager ()
|
||||
|
||||
@property (nonatomic, assign) BOOL loading;
|
||||
@property (nonatomic, assign, readwrite) BOOL ready;
|
||||
@property (nonatomic, strong) MPBaseInterstitialAdapter *adapter;
|
||||
@property (nonatomic, strong) MPAdServerCommunicator *communicator;
|
||||
@property (nonatomic, strong) MPAdConfiguration *configuration;
|
||||
|
||||
- (void)setUpAdapterWithConfiguration:(MPAdConfiguration *)configuration;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation MPInterstitialAdManager
|
||||
|
||||
@synthesize loading = _loading;
|
||||
@synthesize ready = _ready;
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize communicator = _communicator;
|
||||
@synthesize adapter = _adapter;
|
||||
@synthesize configuration = _configuration;
|
||||
|
||||
- (id)initWithDelegate:(id<MPInterstitialAdManagerDelegate>)delegate
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.communicator = [[MPAdServerCommunicator alloc] initWithDelegate:self];
|
||||
self.delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.communicator cancel];
|
||||
[self.communicator setDelegate:nil];
|
||||
|
||||
self.adapter = nil;
|
||||
}
|
||||
|
||||
- (void)setAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
if (self.adapter != adapter) {
|
||||
[self.adapter unregisterDelegate];
|
||||
_adapter = adapter;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)loadAdWithURL:(NSURL *)URL
|
||||
{
|
||||
if (self.loading) {
|
||||
MPLogWarn(@"Interstitial controller is already loading an ad. "
|
||||
@"Wait for previous load to finish.");
|
||||
return;
|
||||
}
|
||||
|
||||
MPLogInfo(@"Interstitial controller is loading ad with MoPub server URL: %@", URL);
|
||||
|
||||
self.loading = YES;
|
||||
[self.communicator loadURL:URL];
|
||||
}
|
||||
|
||||
|
||||
- (void)loadInterstitialWithAdUnitID:(NSString *)ID keywords:(NSString *)keywords userDataKeywords:(NSString *)userDataKeywords location:(CLLocation *)location
|
||||
{
|
||||
if (self.ready) {
|
||||
[self.delegate managerDidLoadInterstitial:self];
|
||||
} else {
|
||||
[self loadAdWithURL:[MPAdServerURLBuilder URLWithAdUnitID:ID
|
||||
keywords:keywords
|
||||
userDataKeywords:userDataKeywords
|
||||
location:location]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)presentInterstitialFromViewController:(UIViewController *)controller
|
||||
{
|
||||
// Don't allow the ad to be shown if it isn't ready.
|
||||
if (!self.ready) {
|
||||
// We don't want to remotely log this event -- it's simply for publisher troubleshooting -- so use NSLog
|
||||
// rather than MPLog.
|
||||
NSLog(@"Interstitial ad view is not ready to be shown");
|
||||
return;
|
||||
}
|
||||
|
||||
[self.adapter showInterstitialFromViewController:controller];
|
||||
}
|
||||
|
||||
- (CLLocation *)location
|
||||
{
|
||||
return [self.delegate location];
|
||||
}
|
||||
|
||||
- (MPInterstitialAdController *)interstitialAdController
|
||||
{
|
||||
return [self.delegate interstitialAdController];
|
||||
}
|
||||
|
||||
- (id)interstitialDelegate
|
||||
{
|
||||
return [self.delegate interstitialDelegate];
|
||||
}
|
||||
|
||||
#pragma mark - MPAdServerCommunicatorDelegate
|
||||
|
||||
- (void)communicatorDidReceiveAdConfigurations:(NSArray<MPAdConfiguration *> *)configurations
|
||||
{
|
||||
self.configuration = configurations.firstObject;
|
||||
|
||||
MPLogInfo(@"Interstitial ad view is fetching ad network type: %@", self.configuration.networkType);
|
||||
|
||||
if (self.configuration.adUnitWarmingUp) {
|
||||
MPLogInfo(kMPWarmingUpErrorLogFormatWithAdUnitID, self.delegate.interstitialAdController.adUnitId);
|
||||
self.loading = NO;
|
||||
[self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorAdUnitWarmingUp]];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self.configuration.networkType isEqualToString:kAdTypeClear]) {
|
||||
MPLogInfo(kMPClearErrorLogFormatWithAdUnitID, self.delegate.interstitialAdController.adUnitId);
|
||||
self.loading = NO;
|
||||
[self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorNoInventory]];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.configuration.adType != MPAdTypeInterstitial) {
|
||||
MPLogWarn(@"Could not load ad: interstitial object received a non-interstitial ad unit ID.");
|
||||
self.loading = NO;
|
||||
[self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorAdapterInvalid]];
|
||||
return;
|
||||
}
|
||||
|
||||
[self setUpAdapterWithConfiguration:self.configuration];
|
||||
}
|
||||
|
||||
- (void)communicatorDidFailWithError:(NSError *)error
|
||||
{
|
||||
self.ready = NO;
|
||||
self.loading = NO;
|
||||
|
||||
[self.delegate manager:self didFailToLoadInterstitialWithError:error];
|
||||
}
|
||||
|
||||
- (void)setUpAdapterWithConfiguration:(MPAdConfiguration *)configuration;
|
||||
{
|
||||
MPBaseInterstitialAdapter *adapter = [[MPInstanceProvider sharedProvider] buildInterstitialAdapterForConfiguration:configuration
|
||||
delegate:self];
|
||||
if (!adapter) {
|
||||
[self adapter:nil didFailToLoadAdWithError:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
self.adapter = adapter;
|
||||
[self.adapter _getAdWithConfiguration:configuration];
|
||||
}
|
||||
|
||||
#pragma mark - MPInterstitialAdapterDelegate
|
||||
|
||||
- (void)adapterDidFinishLoadingAd:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
self.ready = YES;
|
||||
self.loading = NO;
|
||||
[self.delegate managerDidLoadInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)adapter:(MPBaseInterstitialAdapter *)adapter didFailToLoadAdWithError:(NSError *)error
|
||||
{
|
||||
self.ready = NO;
|
||||
self.loading = NO;
|
||||
[self loadAdWithURL:self.configuration.failoverURL];
|
||||
}
|
||||
|
||||
- (void)interstitialWillAppearForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
[self.delegate managerWillPresentInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidAppearForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
[self.delegate managerDidPresentInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialWillDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
[self.delegate managerWillDismissInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
self.ready = NO;
|
||||
[self.delegate managerDidDismissInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidExpireForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
self.ready = NO;
|
||||
[self.delegate managerDidExpireInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidReceiveTapEventForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
[self.delegate managerDidReceiveTapEventFromInterstitial:self];
|
||||
}
|
||||
|
||||
- (void)interstitialWillLeaveApplicationForAdapter:(MPBaseInterstitialAdapter *)adapter
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// MPInterstitialViewController.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPGlobal.h"
|
||||
|
||||
@class CLLocation;
|
||||
|
||||
@protocol MPInterstitialViewControllerDelegate;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@interface MPInterstitialViewController : UIViewController
|
||||
|
||||
@property (nonatomic, assign) MPInterstitialCloseButtonStyle closeButtonStyle;
|
||||
@property (nonatomic, assign) MPInterstitialOrientationType orientationType;
|
||||
@property (nonatomic, strong) UIButton *closeButton;
|
||||
@property (nonatomic, weak) id<MPInterstitialViewControllerDelegate> delegate;
|
||||
|
||||
- (void)presentInterstitialFromViewController:(UIViewController *)controller;
|
||||
- (void)dismissInterstitialAnimated:(BOOL)animated;
|
||||
- (BOOL)shouldDisplayCloseButton;
|
||||
- (void)willPresentInterstitial;
|
||||
- (void)didPresentInterstitial;
|
||||
- (void)willDismissInterstitial;
|
||||
- (void)didDismissInterstitial;
|
||||
- (void)layoutCloseButton;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol MPInterstitialViewControllerDelegate <NSObject>
|
||||
|
||||
- (NSString *)adUnitId;
|
||||
- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial;
|
||||
- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial;
|
||||
|
||||
@optional
|
||||
- (CLLocation *)location;
|
||||
- (void)interstitialRewardedVideoEnded;
|
||||
|
||||
@end
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// MPAdvancedBiddingManager.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPAdvancedBidder.h"
|
||||
|
||||
/**
|
||||
* Internally manages all aspects related to advanced bidding.
|
||||
*/
|
||||
@interface MPAdvancedBiddingManager : NSObject
|
||||
/**
|
||||
* A boolean value indicating whether advanced bidding is enabled. This boolean defaults to `YES`.
|
||||
* To disable advanced bidding, set this value to `NO`.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL advancedBiddingEnabled;
|
||||
|
||||
/**
|
||||
* A UTF-8 JSON string representation of the Advanced Bidding tokens.
|
||||
* @remark If `advancedBiddingEnabled` is set to `NO`, this will always return `nil`.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSString * _Nullable bidderTokensJson;
|
||||
|
||||
/**
|
||||
* Singleton instance of the manager.
|
||||
*/
|
||||
+ (MPAdvancedBiddingManager * _Nonnull)sharedManager;
|
||||
|
||||
/**
|
||||
Initializes each Advanced Bidder and retains a reference. If an Advanced Bidder is
|
||||
already initialized, nothing will be done.
|
||||
@param bidders Array of bidders
|
||||
@param complete Completion block
|
||||
*/
|
||||
- (void)initializeBidders:(NSArray<Class<MPAdvancedBidder>> * _Nonnull)bidders complete:(void(^_Nullable)(void))complete;
|
||||
|
||||
@end
|
|
@ -1,112 +0,0 @@
|
|||
//
|
||||
// MPAdvancedBiddingManager.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPAdvancedBiddingManager.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
// JSON constants
|
||||
static NSString const * kTokenKey = @"token";
|
||||
|
||||
@interface MPAdvancedBiddingManager()
|
||||
|
||||
// Dictionary of Advanced Bidding network name to instance of that Advanced Bidder.
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, id<MPAdvancedBidder>> * bidders;
|
||||
|
||||
// Advanced Bidder initialization queue.
|
||||
@property (nonatomic, strong) dispatch_queue_t queue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdvancedBiddingManager
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (MPAdvancedBiddingManager *)sharedManager {
|
||||
static MPAdvancedBiddingManager * sharedMyManager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedMyManager = [[self alloc] init];
|
||||
});
|
||||
return sharedMyManager;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_advancedBiddingEnabled = YES;
|
||||
_bidders = [NSMutableDictionary dictionary];
|
||||
_queue = dispatch_queue_create("Advanced Bidder Initialization Queue", NULL);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Bidders
|
||||
|
||||
- (NSString *)bidderTokensJson {
|
||||
// No bidders.
|
||||
if (self.bidders.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Advanced Bidding is not enabled.
|
||||
if (!self.advancedBiddingEnabled) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Generate the JSON dictionary for all participating bidders.
|
||||
NSMutableDictionary * tokens = [NSMutableDictionary dictionary];
|
||||
[self.bidders enumerateKeysAndObjectsUsingBlock:^(NSString * network, id<MPAdvancedBidder> bidder, BOOL * stop) {
|
||||
tokens[network] = @{ kTokenKey: bidder.token };
|
||||
}];
|
||||
|
||||
// Serialize the JSON dictionary into a JSON string.
|
||||
NSError * error = nil;
|
||||
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:tokens options:0 error:&error];
|
||||
if (jsonData == nil) {
|
||||
MPLogError(@"Failed to generate a JSON string from\n%@\nReason: %@", tokens, error.localizedDescription);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (void)initializeBidders:(NSArray<Class<MPAdvancedBidder>> * _Nonnull)bidders complete:(void(^_Nullable)(void))complete {
|
||||
// No bidders to initialize, complete immediately
|
||||
if (bidders.count == 0) {
|
||||
if (complete) {
|
||||
complete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Asynchronous dispatch the initialization as it may take some time.
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
dispatch_async(self.queue, ^{
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
for (Class<MPAdvancedBidder> advancedBidderClass in bidders) {
|
||||
// Create an instance of the Advanced Bidder
|
||||
id<MPAdvancedBidder> advancedBidder = (id<MPAdvancedBidder>)[[[advancedBidderClass class] alloc] init];
|
||||
NSString * network = advancedBidder.creativeNetworkName;
|
||||
|
||||
// Verify that the Advanced Bidder has a creative network name and that it's
|
||||
// not already created.
|
||||
if (network != nil && strongSelf.bidders[network] == nil) {
|
||||
strongSelf.bidders[network] = advancedBidder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify completion block handler.
|
||||
if (complete) {
|
||||
complete();
|
||||
}
|
||||
}); // End dispatch_async
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,51 +0,0 @@
|
|||
//
|
||||
// MPConsentAdServerKeys.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Request Keys
|
||||
|
||||
extern NSString * const kIdfaKey;
|
||||
extern NSString * const kAdUnitIdKey;
|
||||
extern NSString * const kBundleKey;
|
||||
extern NSString * const kDoNotTrackIdKey;
|
||||
extern NSString * const kLastChangedMsKey;
|
||||
extern NSString * const kLastSynchronizedConsentStatusKey;
|
||||
extern NSString * const kCurrentConsentStatusKey;
|
||||
extern NSString * const kConsentedVendorListVersionKey;
|
||||
extern NSString * const kConsentedPrivacyPolicyVersionKey;
|
||||
extern NSString * const kCachedIabVendorListHashKey;
|
||||
extern NSString * const kGDPRAppliesKey;
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Shared Keys
|
||||
|
||||
extern NSString * const kConsentChangedReasonKey;
|
||||
extern NSString * const kExtrasKey;
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Response Keys
|
||||
|
||||
extern NSString * const kForceExplicitNoKey;
|
||||
extern NSString * const kInvalidateConsentKey;
|
||||
extern NSString * const kReacquireConsentKey;
|
||||
extern NSString * const kIsWhitelistedKey;
|
||||
extern NSString * const kIsGDPRRegionKey;
|
||||
extern NSString * const kVendorListUrlKey;
|
||||
extern NSString * const kVendorListVersionKey;
|
||||
extern NSString * const kPrivacyPolicyUrlKey;
|
||||
extern NSString * const kPrivacyPolicyVersionKey;
|
||||
extern NSString * const kIabVendorListKey;
|
||||
extern NSString * const kIabVendorListHashKey;
|
||||
extern NSString * const kSyncFrequencyKey;
|
||||
|
||||
#pragma mark - Consent Dialog Endpoint: Request Keys
|
||||
|
||||
extern NSString * const kLanguageKey;
|
||||
extern NSString * const kSDKVersionKey;
|
||||
|
||||
#pragma mark - Consent Dialog Endpoint: Response Keys
|
||||
|
||||
extern NSString * const kDialogHTMLKey;
|
|
@ -1,51 +0,0 @@
|
|||
//
|
||||
// MPConsentAdServerKeys.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPConsentAdServerKeys.h"
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Request Keys
|
||||
|
||||
NSString * const kIdfaKey = @"udid";
|
||||
NSString * const kAdUnitIdKey = @"id";
|
||||
NSString * const kBundleKey = @"bundle";
|
||||
NSString * const kDoNotTrackIdKey = @"dnt";
|
||||
NSString * const kLastChangedMsKey = @"last_changed_ms";
|
||||
NSString * const kLastSynchronizedConsentStatusKey = @"last_consent_status";
|
||||
NSString * const kCurrentConsentStatusKey = @"current_consent_status";
|
||||
NSString * const kConsentedVendorListVersionKey = @"consented_vendor_list_version";
|
||||
NSString * const kConsentedPrivacyPolicyVersionKey = @"consented_privacy_policy_version";
|
||||
NSString * const kCachedIabVendorListHashKey = @"cached_vendor_list_iab_hash";
|
||||
NSString * const kGDPRAppliesKey = @"gdpr_applies";
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Shared Keys
|
||||
|
||||
NSString * const kConsentChangedReasonKey = @"consent_change_reason";
|
||||
NSString * const kExtrasKey = @"extras";
|
||||
|
||||
#pragma mark - Synchronization Endpoint: Response Keys
|
||||
|
||||
NSString * const kForceExplicitNoKey = @"force_explicit_no";
|
||||
NSString * const kInvalidateConsentKey = @"invalidate_consent";
|
||||
NSString * const kReacquireConsentKey = @"reacquire_consent";
|
||||
NSString * const kIsWhitelistedKey = @"is_whitelisted";
|
||||
NSString * const kIsGDPRRegionKey = @"is_gdpr_region";
|
||||
NSString * const kVendorListUrlKey = @"current_vendor_list_link";
|
||||
NSString * const kVendorListVersionKey = @"current_vendor_list_version";
|
||||
NSString * const kPrivacyPolicyUrlKey = @"current_privacy_policy_link";
|
||||
NSString * const kPrivacyPolicyVersionKey = @"current_privacy_policy_version";
|
||||
NSString * const kIabVendorListKey = @"current_vendor_list_iab_format";
|
||||
NSString * const kIabVendorListHashKey = @"current_vendor_list_iab_hash";
|
||||
NSString * const kSyncFrequencyKey = @"call_again_after_secs";
|
||||
|
||||
#pragma mark - Consent Dialog Endpoint: Request Keys
|
||||
|
||||
NSString * const kLanguageKey = @"language";
|
||||
NSString * const kSDKVersionKey = @"nv";
|
||||
|
||||
#pragma mark - Consent Dialog Endpoint: Response Keys
|
||||
|
||||
NSString * const kDialogHTMLKey = @"dialog_html";
|
|
@ -1,117 +0,0 @@
|
|||
//
|
||||
// MPInstanceProvider.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPGlobal.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
|
||||
// MPWebView
|
||||
@class MPWebView;
|
||||
@protocol MPWebViewDelegate;
|
||||
|
||||
// Banners
|
||||
@class MPBannerAdManager;
|
||||
@protocol MPBannerAdManagerDelegate;
|
||||
@class MPBaseBannerAdapter;
|
||||
@protocol MPBannerAdapterDelegate;
|
||||
@class MPBannerCustomEvent;
|
||||
@protocol MPBannerCustomEventDelegate;
|
||||
|
||||
// Interstitials
|
||||
@class MPInterstitialAdManager;
|
||||
@protocol MPInterstitialAdManagerDelegate;
|
||||
@class MPBaseInterstitialAdapter;
|
||||
@protocol MPInterstitialAdapterDelegate;
|
||||
@class MPInterstitialCustomEvent;
|
||||
@protocol MPInterstitialCustomEventDelegate;
|
||||
@class MPHTMLInterstitialViewController;
|
||||
@class MPMRAIDInterstitialViewController;
|
||||
@protocol MPInterstitialViewControllerDelegate;
|
||||
|
||||
// Rewarded Video
|
||||
@class MPRewardedVideoAdManager;
|
||||
@class MPRewardedVideoAdapter;
|
||||
@class MPRewardedVideoCustomEvent;
|
||||
@protocol MPRewardedVideoAdapterDelegate;
|
||||
@protocol MPRewardedVideoCustomEventDelegate;
|
||||
@protocol MPRewardedVideoAdManagerDelegate;
|
||||
|
||||
// HTML Ads
|
||||
@class MPAdWebViewAgent;
|
||||
@protocol MPAdWebViewAgentDelegate;
|
||||
|
||||
// MRAID
|
||||
@class MRController;
|
||||
@protocol MRControllerDelegate;
|
||||
@class MPClosableView;
|
||||
@class MRBridge;
|
||||
@protocol MRBridgeDelegate;
|
||||
@protocol MPClosableViewDelegate;
|
||||
@class MRBundleManager;
|
||||
@class MRVideoPlayerManager;
|
||||
@protocol MRVideoPlayerManagerDelegate;
|
||||
@class MPMoviePlayerViewController;
|
||||
@class MRNativeCommandHandler;
|
||||
@protocol MRNativeCommandHandlerDelegate;
|
||||
|
||||
//Native
|
||||
@protocol MPNativeCustomEventDelegate;
|
||||
@class MPNativeCustomEvent;
|
||||
@class MPNativeAdSource;
|
||||
@protocol MPNativeAdSourceDelegate;
|
||||
@class MPNativePositionSource;
|
||||
@class MPStreamAdPlacementData;
|
||||
@class MPStreamAdPlacer;
|
||||
@class MPAdPositioning;
|
||||
@protocol MPNativeAdRenderer;
|
||||
|
||||
@interface MPInstanceProvider : NSObject
|
||||
|
||||
+(instancetype)sharedProvider;
|
||||
- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider;
|
||||
- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider context:(id)context;
|
||||
|
||||
#pragma mark - Interstitials
|
||||
- (MPInterstitialAdManager *)buildMPInterstitialAdManagerWithDelegate:(id<MPInterstitialAdManagerDelegate>)delegate;
|
||||
- (MPBaseInterstitialAdapter *)buildInterstitialAdapterForConfiguration:(MPAdConfiguration *)configuration
|
||||
delegate:(id<MPInterstitialAdapterDelegate>)delegate;
|
||||
- (MPInterstitialCustomEvent *)buildInterstitialCustomEventFromCustomClass:(Class)customClass
|
||||
delegate:(id<MPInterstitialCustomEventDelegate>)delegate;
|
||||
- (MPHTMLInterstitialViewController *)buildMPHTMLInterstitialViewControllerWithDelegate:(id<MPInterstitialViewControllerDelegate>)delegate
|
||||
orientationType:(MPInterstitialOrientationType)type;
|
||||
- (MPMRAIDInterstitialViewController *)buildMPMRAIDInterstitialViewControllerWithDelegate:(id<MPInterstitialViewControllerDelegate>)delegate
|
||||
configuration:(MPAdConfiguration *)configuration;
|
||||
|
||||
#pragma mark - Rewarded Video
|
||||
- (MPRewardedVideoAdManager *)buildRewardedVideoAdManagerWithAdUnitID:(NSString *)adUnitID delegate:(id<MPRewardedVideoAdManagerDelegate>)delegate;
|
||||
- (MPRewardedVideoAdapter *)buildRewardedVideoAdapterWithDelegate:(id<MPRewardedVideoAdapterDelegate>)delegate;
|
||||
- (MPRewardedVideoCustomEvent *)buildRewardedVideoCustomEventFromCustomClass:(Class)customClass delegate:(id<MPRewardedVideoCustomEventDelegate>)delegate;
|
||||
|
||||
|
||||
#pragma mark - HTML Ads
|
||||
- (MPAdWebViewAgent *)buildMPAdWebViewAgentWithAdWebViewFrame:(CGRect)frame
|
||||
delegate:(id<MPAdWebViewAgentDelegate>)delegate;
|
||||
|
||||
#pragma mark - MRAID
|
||||
- (MPClosableView *)buildMRAIDMPClosableViewWithFrame:(CGRect)frame webView:(MPWebView *)webView delegate:(id<MPClosableViewDelegate>)delegate;
|
||||
- (MRBundleManager *)buildMRBundleManager;
|
||||
- (MRController *)buildBannerMRControllerWithFrame:(CGRect)frame delegate:(id<MRControllerDelegate>)delegate;
|
||||
- (MRController *)buildInterstitialMRControllerWithFrame:(CGRect)frame delegate:(id<MRControllerDelegate>)delegate;
|
||||
- (MRBridge *)buildMRBridgeWithWebView:(MPWebView *)webView delegate:(id<MRBridgeDelegate>)delegate;
|
||||
- (MRVideoPlayerManager *)buildMRVideoPlayerManagerWithDelegate:(id<MRVideoPlayerManagerDelegate>)delegate;
|
||||
- (MPMoviePlayerViewController *)buildMPMoviePlayerViewControllerWithURL:(NSURL *)URL;
|
||||
- (MRNativeCommandHandler *)buildMRNativeCommandHandlerWithDelegate:(id<MRNativeCommandHandlerDelegate>)delegate;
|
||||
|
||||
#pragma mark - Native
|
||||
|
||||
- (MPNativeCustomEvent *)buildNativeCustomEventFromCustomClass:(Class)customClass
|
||||
delegate:(id<MPNativeCustomEventDelegate>)delegate;
|
||||
- (MPNativeAdSource *)buildNativeAdSourceWithDelegate:(id<MPNativeAdSourceDelegate>)delegate;
|
||||
- (MPNativePositionSource *)buildNativePositioningSource;
|
||||
- (MPStreamAdPlacementData *)buildStreamAdPlacementDataWithPositioning:(MPAdPositioning *)positioning;
|
||||
- (MPStreamAdPlacer *)buildStreamAdPlacerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations;
|
||||
|
||||
@end
|
|
@ -1,294 +0,0 @@
|
|||
//
|
||||
// MPInstanceProvider.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPWebView.h"
|
||||
#import "MPAdWebViewAgent.h"
|
||||
#import "MPInterstitialAdManager.h"
|
||||
#import "MPInterstitialCustomEventAdapter.h"
|
||||
#import "MPHTMLInterstitialViewController.h"
|
||||
#import "MPMRAIDInterstitialViewController.h"
|
||||
#import "MPInterstitialCustomEvent.h"
|
||||
#import "MPBaseBannerAdapter.h"
|
||||
#import "MPBannerCustomEventAdapter.h"
|
||||
#import "MPBannerCustomEvent.h"
|
||||
#import "MPBannerAdManager.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MRBundleManager.h"
|
||||
#import "MRVideoPlayerManager.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
#import "MRNativeCommandHandler.h"
|
||||
#import "MRBridge.h"
|
||||
#import "MRController.h"
|
||||
#import "MPClosableView.h"
|
||||
#import "MPRewardedVideoAdManager.h"
|
||||
#import "MPRewardedVideoAdapter.h"
|
||||
#import "MPRewardedVideoCustomEvent.h"
|
||||
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
#import "MPNativeCustomEvent.h"
|
||||
#import "MPNativeAdSource.h"
|
||||
#import "MPNativePositionSource.h"
|
||||
#import "MPStreamAdPlacementData.h"
|
||||
#import "MPStreamAdPlacer.h"
|
||||
#endif
|
||||
|
||||
@interface MPInstanceProvider ()
|
||||
|
||||
// A nested dictionary. The top-level dictionary maps Class objects to second-level dictionaries.
|
||||
// The second level dictionaries map identifiers to singleton objects.
|
||||
//
|
||||
// An example:
|
||||
// {
|
||||
// SomeClass:
|
||||
// {
|
||||
// @"default": <singleton_a>
|
||||
// @"other_context": <singleton_b>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
@property (nonatomic, strong) NSMutableDictionary *singletons;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation MPInstanceProvider
|
||||
|
||||
static MPInstanceProvider *sharedAdProvider = nil;
|
||||
|
||||
+ (instancetype)sharedProvider
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
dispatch_once(&once, ^{
|
||||
sharedAdProvider = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedAdProvider;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.singletons = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider
|
||||
{
|
||||
return [self singletonForClass:klass provider:provider context:@"default"];
|
||||
}
|
||||
|
||||
- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider context:(id)context
|
||||
{
|
||||
id singleton = [[self.singletons objectForKey:klass] objectForKey:context];
|
||||
if (!singleton) {
|
||||
singleton = provider();
|
||||
NSMutableDictionary *singletonsForClass = [self.singletons objectForKey:klass];
|
||||
if (!singletonsForClass) {
|
||||
NSMutableDictionary *singletonsForContext = [NSMutableDictionary dictionaryWithObjectsAndKeys:singleton, context, nil];
|
||||
[self.singletons setObject:singletonsForContext forKey:(id<NSCopying>)klass];
|
||||
} else {
|
||||
[singletonsForClass setObject:singleton forKey:context];
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
#pragma mark - Interstitials
|
||||
|
||||
- (MPInterstitialAdManager *)buildMPInterstitialAdManagerWithDelegate:(id<MPInterstitialAdManagerDelegate>)delegate
|
||||
{
|
||||
return [(MPInterstitialAdManager *)[MPInterstitialAdManager alloc] initWithDelegate:delegate];
|
||||
}
|
||||
|
||||
|
||||
- (MPBaseInterstitialAdapter *)buildInterstitialAdapterForConfiguration:(MPAdConfiguration *)configuration
|
||||
delegate:(id<MPInterstitialAdapterDelegate>)delegate
|
||||
{
|
||||
if (configuration.customEventClass) {
|
||||
return [(MPInterstitialCustomEventAdapter *)[MPInterstitialCustomEventAdapter alloc] initWithDelegate:delegate];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (MPInterstitialCustomEvent *)buildInterstitialCustomEventFromCustomClass:(Class)customClass
|
||||
delegate:(id<MPInterstitialCustomEventDelegate>)delegate
|
||||
{
|
||||
MPInterstitialCustomEvent *customEvent = [[customClass alloc] init];
|
||||
if (![customEvent isKindOfClass:[MPInterstitialCustomEvent class]]) {
|
||||
MPLogError(@"**** Custom Event Class: %@ does not extend MPInterstitialCustomEvent ****", NSStringFromClass(customClass));
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
if ([customEvent respondsToSelector:@selector(customEventDidUnload)]) {
|
||||
MPLogWarn(@"**** Custom Event Class: %@ implements the deprecated -customEventDidUnload method. This is no longer called. Use -dealloc for cleanup instead ****", NSStringFromClass(customClass));
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
customEvent.delegate = delegate;
|
||||
return customEvent;
|
||||
}
|
||||
|
||||
- (MPHTMLInterstitialViewController *)buildMPHTMLInterstitialViewControllerWithDelegate:(id<MPInterstitialViewControllerDelegate>)delegate
|
||||
orientationType:(MPInterstitialOrientationType)type
|
||||
{
|
||||
MPHTMLInterstitialViewController *controller = [[MPHTMLInterstitialViewController alloc] init];
|
||||
controller.delegate = delegate;
|
||||
controller.orientationType = type;
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (MPMRAIDInterstitialViewController *)buildMPMRAIDInterstitialViewControllerWithDelegate:(id<MPInterstitialViewControllerDelegate>)delegate
|
||||
configuration:(MPAdConfiguration *)configuration
|
||||
{
|
||||
MPMRAIDInterstitialViewController *controller = [[MPMRAIDInterstitialViewController alloc] initWithAdConfiguration:configuration];
|
||||
controller.delegate = delegate;
|
||||
return controller;
|
||||
}
|
||||
|
||||
#pragma mark - Rewarded Video
|
||||
|
||||
- (MPRewardedVideoAdManager *)buildRewardedVideoAdManagerWithAdUnitID:(NSString *)adUnitID delegate:(id<MPRewardedVideoAdManagerDelegate>)delegate
|
||||
{
|
||||
return [[MPRewardedVideoAdManager alloc] initWithAdUnitID:adUnitID delegate:delegate];
|
||||
}
|
||||
|
||||
- (MPRewardedVideoAdapter *)buildRewardedVideoAdapterWithDelegate:(id<MPRewardedVideoAdapterDelegate>)delegate
|
||||
{
|
||||
return [[MPRewardedVideoAdapter alloc] initWithDelegate:delegate];
|
||||
}
|
||||
|
||||
- (MPRewardedVideoCustomEvent *)buildRewardedVideoCustomEventFromCustomClass:(Class)customClass delegate:(id<MPRewardedVideoCustomEventDelegate>)delegate
|
||||
{
|
||||
MPRewardedVideoCustomEvent *customEvent = [[customClass alloc] init];
|
||||
|
||||
if (![customEvent isKindOfClass:[MPRewardedVideoCustomEvent class]]) {
|
||||
MPLogError(@"**** Custom Event Class: %@ does not extend MPRewardedVideoCustomEvent ****", NSStringFromClass(customClass));
|
||||
return nil;
|
||||
}
|
||||
|
||||
customEvent.delegate = delegate;
|
||||
return customEvent;
|
||||
}
|
||||
|
||||
#pragma mark - HTML Ads
|
||||
|
||||
- (MPAdWebViewAgent *)buildMPAdWebViewAgentWithAdWebViewFrame:(CGRect)frame delegate:(id<MPAdWebViewAgentDelegate>)delegate
|
||||
{
|
||||
return [[MPAdWebViewAgent alloc] initWithAdWebViewFrame:frame delegate:delegate];
|
||||
}
|
||||
|
||||
#pragma mark - MRAID
|
||||
|
||||
- (MPClosableView *)buildMRAIDMPClosableViewWithFrame:(CGRect)frame webView:(MPWebView *)webView delegate:(id<MPClosableViewDelegate>)delegate
|
||||
{
|
||||
MPClosableView *adView = [[MPClosableView alloc] initWithFrame:frame closeButtonType:MPClosableViewCloseButtonTypeTappableWithImage];
|
||||
adView.delegate = delegate;
|
||||
adView.clipsToBounds = YES;
|
||||
webView.frame = adView.bounds;
|
||||
[adView addSubview:webView];
|
||||
return adView;
|
||||
}
|
||||
|
||||
- (MRBundleManager *)buildMRBundleManager
|
||||
{
|
||||
return [MRBundleManager sharedManager];
|
||||
}
|
||||
|
||||
- (MRController *)buildBannerMRControllerWithFrame:(CGRect)frame delegate:(id<MRControllerDelegate>)delegate
|
||||
{
|
||||
return [self buildMRControllerWithFrame:frame placementType:MRAdViewPlacementTypeInline delegate:delegate];
|
||||
}
|
||||
|
||||
- (MRController *)buildInterstitialMRControllerWithFrame:(CGRect)frame delegate:(id<MRControllerDelegate>)delegate
|
||||
{
|
||||
return [self buildMRControllerWithFrame:frame placementType:MRAdViewPlacementTypeInterstitial delegate:delegate];
|
||||
}
|
||||
|
||||
- (MRController *)buildMRControllerWithFrame:(CGRect)frame placementType:(MRAdViewPlacementType)placementType delegate:(id<MRControllerDelegate>)delegate
|
||||
{
|
||||
MRController *controller = [[MRController alloc] initWithAdViewFrame:frame adPlacementType:placementType];
|
||||
controller.delegate = delegate;
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (MRBridge *)buildMRBridgeWithWebView:(MPWebView *)webView delegate:(id<MRBridgeDelegate>)delegate
|
||||
{
|
||||
MRBridge *bridge = [[MRBridge alloc] initWithWebView:webView];
|
||||
bridge.delegate = delegate;
|
||||
bridge.shouldHandleRequests = YES;
|
||||
return bridge;
|
||||
}
|
||||
|
||||
- (MRVideoPlayerManager *)buildMRVideoPlayerManagerWithDelegate:(id<MRVideoPlayerManagerDelegate>)delegate
|
||||
{
|
||||
return [[MRVideoPlayerManager alloc] initWithDelegate:delegate];
|
||||
}
|
||||
|
||||
- (MPMoviePlayerViewController *)buildMPMoviePlayerViewControllerWithURL:(NSURL *)URL
|
||||
{
|
||||
// ImageContext used to avoid CGErrors
|
||||
// http://stackoverflow.com/questions/13203336/iphone-mpmovieplayerviewcontroller-cgcontext-errors/14669166#14669166
|
||||
UIGraphicsBeginImageContext(CGSizeMake(1,1));
|
||||
MPMoviePlayerViewController *playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:URL];
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return playerViewController;
|
||||
}
|
||||
|
||||
- (MRNativeCommandHandler *)buildMRNativeCommandHandlerWithDelegate:(id<MRNativeCommandHandlerDelegate>)delegate
|
||||
{
|
||||
return [[MRNativeCommandHandler alloc] initWithDelegate:delegate];
|
||||
}
|
||||
|
||||
#pragma mark - Native
|
||||
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
|
||||
- (MPNativeCustomEvent *)buildNativeCustomEventFromCustomClass:(Class)customClass
|
||||
delegate:(id<MPNativeCustomEventDelegate>)delegate
|
||||
{
|
||||
MPNativeCustomEvent *customEvent = [[customClass alloc] init];
|
||||
if (![customEvent isKindOfClass:[MPNativeCustomEvent class]]) {
|
||||
MPLogError(@"**** Custom Event Class: %@ does not extend MPNativeCustomEvent ****", NSStringFromClass(customClass));
|
||||
return nil;
|
||||
}
|
||||
customEvent.delegate = delegate;
|
||||
return customEvent;
|
||||
}
|
||||
|
||||
- (MPNativeAdSource *)buildNativeAdSourceWithDelegate:(id<MPNativeAdSourceDelegate>)delegate
|
||||
{
|
||||
MPNativeAdSource *source = [MPNativeAdSource source];
|
||||
source.delegate = delegate;
|
||||
return source;
|
||||
}
|
||||
|
||||
- (MPNativePositionSource *)buildNativePositioningSource
|
||||
{
|
||||
return [[MPNativePositionSource alloc] init];
|
||||
}
|
||||
|
||||
- (MPStreamAdPlacementData *)buildStreamAdPlacementDataWithPositioning:(MPAdPositioning *)positioning
|
||||
{
|
||||
MPStreamAdPlacementData *placementData = [[MPStreamAdPlacementData alloc] initWithPositioning:positioning];
|
||||
return placementData;
|
||||
}
|
||||
|
||||
- (MPStreamAdPlacer *)buildStreamAdPlacerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations
|
||||
{
|
||||
return [MPStreamAdPlacer placerWithViewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
//
|
||||
// MPMediationManager.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPMediationSdkInitializable.h"
|
||||
|
||||
@interface MPMediationManager : NSObject
|
||||
|
||||
/**
|
||||
Singleton instance of the manager.
|
||||
*/
|
||||
+ (instancetype _Nonnull)sharedManager;
|
||||
|
||||
/**
|
||||
Initializes the inputted mediated network SDKs from the cache.
|
||||
@param networks Networks to initialize. If @c nil, nothing will be done.
|
||||
@param completion Optional completion block.
|
||||
*/
|
||||
- (void)initializeMediatedNetworks:(NSArray<Class<MPMediationSdkInitializable>> * _Nullable)networks
|
||||
completion:(void (^ _Nullable)(NSError * _Nullable error))completion;
|
||||
|
||||
/**
|
||||
Sets the initialization parameters for a given network in the cache.
|
||||
@param params Initialization parameters sent to the @c MPSdkInitializable instance when initialized.
|
||||
@param networkClass Network class.
|
||||
*/
|
||||
- (void)setCachedInitializationParameters:(NSDictionary * _Nullable)params forNetwork:(Class<MPMediationSdkInitializable> _Nonnull)networkClass;
|
||||
|
||||
/**
|
||||
Retrieves the cached initialization parameters for a given network.
|
||||
@param networkClass Network class.
|
||||
@returns The cached parameters or @c nil.
|
||||
*/
|
||||
- (NSDictionary * _Nullable)cachedInitializationParametersForNetwork:(Class<MPMediationSdkInitializable> _Nonnull)networkClass;
|
||||
|
||||
/**
|
||||
Retrieves all of the currently cached networks.
|
||||
@return A list of all cached networks or @c nil.
|
||||
*/
|
||||
- (NSArray<Class<MPMediationSdkInitializable>> * _Nullable)allCachedNetworks;
|
||||
|
||||
/**
|
||||
Clears the cache.
|
||||
*/
|
||||
- (void)clearCache;
|
||||
|
||||
@end
|
|
@ -1,130 +0,0 @@
|
|||
//
|
||||
// MPMediationManager.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMediationManager.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
/**
|
||||
Key of the @c NSUserDefaults entry for the network initialization cache.
|
||||
*/
|
||||
static NSString * const kNetworkSDKInitializationParametersKey = @"com.mopub.mopub-ios-sdk.network-init-info";
|
||||
|
||||
@implementation MPMediationManager
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
static MPMediationManager * sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[MPMediationManager alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
#pragma mark - Cache
|
||||
|
||||
- (void)setCachedInitializationParameters:(NSDictionary * _Nullable)params forNetwork:(Class<MPMediationSdkInitializable> _Nonnull)networkClass {
|
||||
// Empty network names and parameters are invalid.
|
||||
NSString * network = NSStringFromClass(networkClass);
|
||||
if (network.length == 0 || params == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
@synchronized (self) {
|
||||
NSMutableDictionary * cachedParameters = [[[NSUserDefaults standardUserDefaults] objectForKey:kNetworkSDKInitializationParametersKey] mutableCopy];
|
||||
if (cachedParameters == nil) {
|
||||
cachedParameters = [NSMutableDictionary dictionaryWithCapacity:1];
|
||||
}
|
||||
|
||||
cachedParameters[network] = params;
|
||||
[[NSUserDefaults standardUserDefaults] setObject:cachedParameters forKey:kNetworkSDKInitializationParametersKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
MPLogInfo(@"Cached SDK initialization parameters for %@:\n%@", network, params);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary * _Nullable)cachedInitializationParametersForNetwork:(Class<MPMediationSdkInitializable>)networkClass {
|
||||
// Empty network names are invalid.
|
||||
NSString * network = NSStringFromClass(networkClass);
|
||||
if (network.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary * cachedParameters = [[NSUserDefaults standardUserDefaults] objectForKey:kNetworkSDKInitializationParametersKey];
|
||||
if (cachedParameters == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [cachedParameters objectForKey:network];
|
||||
}
|
||||
|
||||
- (NSArray<Class<MPMediationSdkInitializable>> * _Nullable)allCachedNetworks {
|
||||
NSDictionary * cachedParameters = [[NSUserDefaults standardUserDefaults] objectForKey:kNetworkSDKInitializationParametersKey];
|
||||
NSArray * cacheKeys = [cachedParameters allKeys];
|
||||
if (cacheKeys == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Convert the strings of class names into class types.
|
||||
NSMutableArray<Class<MPMediationSdkInitializable>> * cachedNetworks = [NSMutableArray array];
|
||||
[cacheKeys enumerateObjectsUsingBlock:^(NSString * key, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
Class c = NSClassFromString(key);
|
||||
if ([c conformsToProtocol:@protocol(MPMediationSdkInitializable)]) {
|
||||
[cachedNetworks addObject:c];
|
||||
}
|
||||
}];
|
||||
|
||||
return cachedNetworks;
|
||||
}
|
||||
|
||||
- (void)clearCache {
|
||||
@synchronized (self) {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kNetworkSDKInitializationParametersKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
MPLogInfo(@"Cleared cached SDK initialization parameters");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Mediation
|
||||
|
||||
- (void)initializeMediatedNetworks:(NSArray<Class<MPMediationSdkInitializable>> *)networks
|
||||
completion:(void (^ _Nullable)(NSError * _Nullable error))completion {
|
||||
// Nothing to initialize
|
||||
if (networks.count == 0) {
|
||||
if (completion != nil) {
|
||||
completion(nil);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Network SDK initializations should occur on the main thread since
|
||||
// some of those SDKs require it.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (Class<MPMediationSdkInitializable> mediationClass in networks) {
|
||||
id<MPMediationSdkInitializable> mediationNetwork = (id<MPMediationSdkInitializable>)[[mediationClass class] new];
|
||||
NSDictionary * cachedInitializationParams = [self cachedInitializationParametersForNetwork:mediationClass];
|
||||
|
||||
// Only attempt initialization if they exist. Otherwise, we should wait for the
|
||||
// on-demand initialization to occur with the correct parameters.
|
||||
if (cachedInitializationParams != nil) {
|
||||
[mediationNetwork initializeSdkWithParameters:cachedInitializationParams];
|
||||
MPLogInfo(@"Loaded mediated network: %@", NSStringFromClass(mediationClass));
|
||||
}
|
||||
}
|
||||
|
||||
if (completion != nil) {
|
||||
completion(nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,125 +0,0 @@
|
|||
//
|
||||
// MPURLRequest.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPURLRequest.h"
|
||||
#import "MPAPIEndpoints.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
// All requests have a 10 second timeout.
|
||||
const NSTimeInterval kRequestTimeoutInterval = 10.0;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@interface MPURLRequest()
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPURLRequest
|
||||
|
||||
- (instancetype)initWithURL:(NSURL *)URL {
|
||||
// Requests sent to MoPub should always be in POST format. All other requests
|
||||
// should be sent as a normal GET.
|
||||
BOOL isMoPubRequest = [URL.host isEqualToString:MOPUB_BASE_HOSTNAME];
|
||||
NSURL * requestUrl = URL;
|
||||
if (isMoPubRequest) {
|
||||
// The incoming URL may contain query parameters; we will need to strip them out.
|
||||
NSURLComponents * components = [[NSURLComponents alloc] init];
|
||||
components.scheme = URL.scheme;
|
||||
components.host = URL.host;
|
||||
components.path = URL.path;
|
||||
requestUrl = components.URL;
|
||||
}
|
||||
|
||||
if (self = [super initWithURL:requestUrl]) {
|
||||
// Generate the request
|
||||
[self setHTTPShouldHandleCookies:NO];
|
||||
[self setValue:MPURLRequest.userAgent forHTTPHeaderField:@"User-Agent"];
|
||||
[self setCachePolicy:NSURLRequestReloadIgnoringCacheData];
|
||||
[self setTimeoutInterval:kRequestTimeoutInterval];
|
||||
|
||||
// Request is a MoPub specific request and should be sent as POST with a UTF8 JSON payload.
|
||||
if (isMoPubRequest) {
|
||||
[self setHTTPMethod:@"POST"];
|
||||
[self setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
|
||||
|
||||
// Generate the JSON body from the query parameters
|
||||
NSURLComponents * components = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
|
||||
NSDictionary * json = [MPURLRequest jsonFromURLComponents:components];
|
||||
|
||||
NSError * error = nil;
|
||||
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:json options:0 error:&error];
|
||||
|
||||
// Set the request body with the query parameter key/value pairs if there was no
|
||||
// error in generating a JSON from the dictionary.
|
||||
if (error == nil) {
|
||||
[self setValue:[NSString stringWithFormat:@"%lu", (unsigned long)jsonData.length] forHTTPHeaderField:@"Content-Length"];
|
||||
[self setHTTPBody:jsonData];
|
||||
}
|
||||
else {
|
||||
MPLogError(@"Could not generate JSON body for %@", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (MPURLRequest *)requestWithURL:(NSURL *)URL {
|
||||
return [[MPURLRequest alloc] initWithURL:URL];
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves the current user agent as determined by @c UIWebView.
|
||||
@returns The user agent.
|
||||
*/
|
||||
+ (NSString *)userAgent {
|
||||
static NSString * ua = nil;
|
||||
|
||||
if (ua == nil) {
|
||||
ua = [[[UIWebView alloc] init] stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
|
||||
}
|
||||
|
||||
return ua;
|
||||
}
|
||||
|
||||
/**
|
||||
Generates the POST body as a JSON dictionary. The keys to the dictionary
|
||||
are the query parameter keys, and the values are the associated values.
|
||||
In the event that there are multiple keys present, they will be combined into
|
||||
a comma-seperated list string.
|
||||
@remark The values will be URL-decoded before being set in the JSON dictionary
|
||||
@param components URL components to generate the JSON
|
||||
@returns A JSON dictionary
|
||||
*/
|
||||
+ (NSDictionary *)jsonFromURLComponents:(NSURLComponents *)components {
|
||||
NSMutableDictionary * json = [NSMutableDictionary new];
|
||||
|
||||
// If there are no components, just give back an empty JSON
|
||||
if (components == nil) {
|
||||
return json;
|
||||
}
|
||||
|
||||
// Iterate over every query parameter and rationalize them into
|
||||
// the JSON dictionary.
|
||||
for (NSURLQueryItem * queryItem in components.queryItems) {
|
||||
NSString * key = queryItem.name;
|
||||
NSString * decodedValue = [queryItem.value stringByRemovingPercentEncoding];
|
||||
decodedValue = decodedValue != nil ? decodedValue : @"";
|
||||
|
||||
if ([json objectForKey:key] != nil) {
|
||||
json[key] = [@[json[key], decodedValue] componentsJoinedByString:@","];
|
||||
}
|
||||
// Key doesn't exist; add it.
|
||||
else {
|
||||
json[key] = decodedValue;
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@end
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,37 +0,0 @@
|
|||
//
|
||||
// MPVASTTracking.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class MPVideoConfig;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPVideoEventType) {
|
||||
MPVideoEventTypeTimeUpdate = 0,
|
||||
MPVideoEventTypeMuted,
|
||||
MPVideoEventTypeUnmuted,
|
||||
MPVideoEventTypePause,
|
||||
MPVideoEventTypeResume,
|
||||
MPVideoEventTypeFullScreen,
|
||||
MPVideoEventTypeExitFullScreen,
|
||||
MPVideoEventTypeExpand,
|
||||
MPVideoEventTypeCollapse,
|
||||
MPVideoEventTypeCompleted,
|
||||
MPVideoEventTypeImpression,
|
||||
MPVideoEventTypeClick,
|
||||
MPVideoEventTypeError
|
||||
};
|
||||
|
||||
@interface MPVASTTracking : NSObject
|
||||
|
||||
@property (nonatomic, readonly) MPVideoConfig *videoConfig;
|
||||
@property (nonatomic) NSTimeInterval videoDuration;
|
||||
|
||||
- (instancetype)initWithMPVideoConfig:(MPVideoConfig *)videoConfig videoView:(UIView *)videoView;
|
||||
- (void)handleVideoEvent:(MPVideoEventType)videoEventType videoTimeOffset:(NSTimeInterval)timeOffset;
|
||||
- (void)handleNewVideoView:(UIView *)videoView;
|
||||
|
||||
@end
|
|
@ -1,253 +0,0 @@
|
|||
//
|
||||
// MPVASTTracking.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MOPUBNativeVideoImpressionAgent.h"
|
||||
#import "MPAnalyticsTracker.h"
|
||||
#import "MPCoreInstanceProvider.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPVASTMacroProcessor.h"
|
||||
#import "MPVASTTracking.h"
|
||||
#import "MPVideoConfig.h"
|
||||
|
||||
// Do not fire the start tracker until this time has been reached in the video
|
||||
static const NSInteger kStartTrackerTime = 0;
|
||||
|
||||
@interface VASTTrackingURL : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSURL *url;
|
||||
@property (nonatomic) MPVASTDurationOffset *progressOffset;
|
||||
|
||||
@end
|
||||
|
||||
@implementation VASTTrackingURL
|
||||
|
||||
@end
|
||||
|
||||
@interface VASTEventTracker : NSObject
|
||||
|
||||
@property (nonatomic, assign) BOOL trackersFired;
|
||||
@property (nonatomic) NSArray *trackingEvents; // NSArray<VASTTrackingURL>
|
||||
|
||||
@end
|
||||
|
||||
@implementation VASTEventTracker
|
||||
|
||||
+ (VASTEventTracker *)eventTrackerWithMPVastTrackingEvents:(NSArray *)events
|
||||
{
|
||||
VASTEventTracker *result = [[VASTEventTracker alloc] init];
|
||||
NSMutableArray *trackingEvents = [NSMutableArray array];
|
||||
for (MPVASTTrackingEvent *event in events) {
|
||||
VASTTrackingURL *tracker = [[VASTTrackingURL alloc] init];
|
||||
tracker.url = event.URL;
|
||||
tracker.progressOffset = event.progressOffset;
|
||||
[trackingEvents addObject:tracker];
|
||||
}
|
||||
|
||||
result.trackingEvents = trackingEvents;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (VASTEventTracker *)eventTrackerWithURLs:(NSArray *)urls
|
||||
{
|
||||
VASTEventTracker *result = [[VASTEventTracker alloc] init];
|
||||
NSMutableArray *trackingEvents = [NSMutableArray array];
|
||||
for (NSURL *url in urls) {
|
||||
VASTTrackingURL *tracker = [[VASTTrackingURL alloc] init];
|
||||
tracker.url = url;
|
||||
tracker.progressOffset = nil;
|
||||
[trackingEvents addObject:tracker];
|
||||
}
|
||||
|
||||
result.trackingEvents = trackingEvents;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface MPVASTTracking()
|
||||
|
||||
@property (nonatomic) VASTEventTracker *errorTracker;
|
||||
@property (nonatomic) VASTEventTracker *impressionTracker;
|
||||
@property (nonatomic) VASTEventTracker *clickTracker;
|
||||
@property (nonatomic) VASTEventTracker *customViewabilityTracker;
|
||||
|
||||
@property (nonatomic) VASTEventTracker *startTracker;
|
||||
@property (nonatomic) VASTEventTracker *firstQuartileTracker;
|
||||
@property (nonatomic) VASTEventTracker *midPointTracker;
|
||||
@property (nonatomic) VASTEventTracker *thirdQuartileTracker;
|
||||
@property (nonatomic) VASTEventTracker *completionTracker;
|
||||
|
||||
@property (nonatomic) NSMutableArray *variableProgressTrackers; //NSMutableArray<VASTEventTracker>
|
||||
|
||||
@property (nonatomic) VASTEventTracker *muteTracker;
|
||||
@property (nonatomic) VASTEventTracker *unmuteTracker;
|
||||
@property (nonatomic) VASTEventTracker *pauseTracker;
|
||||
@property (nonatomic) VASTEventTracker *rewindTracker;
|
||||
@property (nonatomic) VASTEventTracker *resumeTracker;
|
||||
@property (nonatomic) VASTEventTracker *fullscreenTracker;
|
||||
@property (nonatomic) VASTEventTracker *exitFullscreenTracker;
|
||||
@property (nonatomic) VASTEventTracker *expandTracker;
|
||||
@property (nonatomic) VASTEventTracker *collapseTracker;
|
||||
|
||||
@property (nonatomic) MOPUBNativeVideoImpressionAgent *customViewabilityTrackingAgent;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPVASTTracking
|
||||
|
||||
- (instancetype)initWithMPVideoConfig:(MPVideoConfig *)videoConfig videoView:(UIView *)videoView;
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_videoConfig = videoConfig;
|
||||
_videoDuration = -1;
|
||||
|
||||
_errorTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.errorURLs];
|
||||
_impressionTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.impressionURLs];
|
||||
_clickTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.clickTrackingURLs];
|
||||
|
||||
_startTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.startTrackers];
|
||||
_firstQuartileTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.firstQuartileTrackers];
|
||||
_midPointTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.midpointTrackers];
|
||||
_thirdQuartileTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.thirdQuartileTrackers];
|
||||
_completionTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.completionTrackers];
|
||||
|
||||
_variableProgressTrackers = [NSMutableArray array];
|
||||
for (MPVASTTrackingEvent *event in _videoConfig.otherProgressTrackers) {
|
||||
[_variableProgressTrackers addObject:[VASTEventTracker eventTrackerWithMPVastTrackingEvents:[NSArray arrayWithObject:event]]];
|
||||
}
|
||||
|
||||
_muteTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.muteTrackers];
|
||||
_unmuteTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.unmuteTrackers];
|
||||
_pauseTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.pauseTrackers];
|
||||
_rewindTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.rewindTrackers];
|
||||
_resumeTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.resumeTrackers];
|
||||
_fullscreenTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.fullscreenTrackers];
|
||||
_exitFullscreenTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.exitFullscreenTrackers];
|
||||
_expandTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.expandTrackers];
|
||||
_collapseTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.collapseTrackers];
|
||||
|
||||
if (_videoConfig.viewabilityTrackingURL) {
|
||||
_customViewabilityTracker = [VASTEventTracker eventTrackerWithURLs:[NSArray arrayWithObject:_videoConfig.viewabilityTrackingURL]];
|
||||
_customViewabilityTrackingAgent = [[MOPUBNativeVideoImpressionAgent alloc] initWithVideoView:videoView requiredVisibilityPercentage:videoConfig.minimumFractionOfVideoVisible requiredPlaybackDuration:videoConfig.minimumViewabilityTimeInterval];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleVideoEvent:(MPVideoEventType)videoEventType videoTimeOffset:(NSTimeInterval)timeOffset
|
||||
{
|
||||
if (self.videoConfig && (self.videoDuration > 0 || videoEventType == MPVideoEventTypeError)) {
|
||||
if (videoEventType == MPVideoEventTypeTimeUpdate) {
|
||||
[self handleProgressTrackers:timeOffset];
|
||||
} else {
|
||||
VASTEventTracker *eventTrackerToFire;
|
||||
switch (videoEventType) {
|
||||
case MPVideoEventTypeMuted:
|
||||
eventTrackerToFire = self.muteTracker;
|
||||
break;
|
||||
case MPVideoEventTypeUnmuted:
|
||||
eventTrackerToFire = self.unmuteTracker;
|
||||
break;
|
||||
case MPVideoEventTypePause:
|
||||
eventTrackerToFire = self.pauseTracker;
|
||||
break;
|
||||
case MPVideoEventTypeResume:
|
||||
eventTrackerToFire = self.resumeTracker;
|
||||
break;
|
||||
case MPVideoEventTypeFullScreen:
|
||||
eventTrackerToFire = self.fullscreenTracker;
|
||||
break;
|
||||
case MPVideoEventTypeExitFullScreen:
|
||||
eventTrackerToFire = self.exitFullscreenTracker;
|
||||
break;
|
||||
case MPVideoEventTypeExpand:
|
||||
eventTrackerToFire = self.expandTracker;
|
||||
break;
|
||||
case MPVideoEventTypeCollapse:
|
||||
eventTrackerToFire = self.collapseTracker;
|
||||
break;
|
||||
case MPVideoEventTypeError:
|
||||
eventTrackerToFire = self.errorTracker;
|
||||
break;
|
||||
case MPVideoEventTypeImpression:
|
||||
if (!self.impressionTracker.trackersFired) {
|
||||
eventTrackerToFire = self.impressionTracker;
|
||||
}
|
||||
break;
|
||||
case MPVideoEventTypeClick:
|
||||
if (!self.clickTracker.trackersFired) {
|
||||
eventTrackerToFire = self.clickTracker;
|
||||
}
|
||||
break;
|
||||
case MPVideoEventTypeCompleted:
|
||||
if (!self.completionTracker.trackersFired) {
|
||||
eventTrackerToFire = self.completionTracker;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
eventTrackerToFire = nil;
|
||||
}
|
||||
// Only fire event trackers after the video has started playing
|
||||
if (eventTrackerToFire && (self.startTracker.trackersFired || videoEventType == MPVideoEventTypeError)) {
|
||||
[self cleanAndSendTrackingEvents:eventTrackerToFire timeOffset:timeOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleProgressTrackers:(NSTimeInterval)timeOffset
|
||||
{
|
||||
if (timeOffset >= kStartTrackerTime && !self.startTracker.trackersFired) {
|
||||
[self cleanAndSendTrackingEvents:self.startTracker timeOffset:timeOffset];
|
||||
}
|
||||
|
||||
if ((0.75 * self.videoDuration) <= timeOffset && !self.thirdQuartileTracker.trackersFired) {
|
||||
[self cleanAndSendTrackingEvents:self.thirdQuartileTracker timeOffset:timeOffset];
|
||||
}
|
||||
|
||||
if ((0.50 * self.videoDuration) <= timeOffset && !self.midPointTracker.trackersFired) {
|
||||
[self cleanAndSendTrackingEvents:self.midPointTracker timeOffset:timeOffset];
|
||||
}
|
||||
|
||||
if ((0.25 * self.videoDuration) <= timeOffset && !self.firstQuartileTracker.trackersFired) {
|
||||
[self cleanAndSendTrackingEvents:self.firstQuartileTracker timeOffset:timeOffset];
|
||||
}
|
||||
|
||||
for (VASTEventTracker *progressTracker in self.variableProgressTrackers) {
|
||||
VASTTrackingURL *progressTrackingURL = progressTracker.trackingEvents[0]; // there's only one
|
||||
if (!progressTracker.trackersFired && [progressTrackingURL.progressOffset timeIntervalForVideoWithDuration:self.videoDuration] <= timeOffset) {
|
||||
[self cleanAndSendTrackingEvents:progressTracker timeOffset:timeOffset];
|
||||
}
|
||||
}
|
||||
|
||||
if (self.customViewabilityTracker && !self.customViewabilityTracker.trackersFired &&
|
||||
[self.customViewabilityTrackingAgent shouldTrackImpressionWithCurrentPlaybackTime:timeOffset]) {
|
||||
[self cleanAndSendTrackingEvents:self.customViewabilityTracker timeOffset:timeOffset];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cleanAndSendTrackingEvents:(VASTEventTracker *)vastEventTracker timeOffset:(NSTimeInterval)timeOffset
|
||||
{
|
||||
if (vastEventTracker && [vastEventTracker.trackingEvents count]) {
|
||||
NSMutableArray *cleanedTrackingURLs = [NSMutableArray array];
|
||||
for (VASTTrackingURL *vastTrackingURL in vastEventTracker.trackingEvents) {
|
||||
[cleanedTrackingURLs addObject:[MPVASTMacroProcessor macroExpandedURLForURL:vastTrackingURL.url errorCode:nil videoTimeOffset:timeOffset videoAssetURL:self.videoConfig.mediaURL]];
|
||||
}
|
||||
[[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] sendTrackingRequestForURLs:cleanedTrackingURLs];
|
||||
}
|
||||
vastEventTracker.trackersFired = YES;
|
||||
}
|
||||
|
||||
- (void)handleNewVideoView:(UIView *)videoView
|
||||
{
|
||||
self.customViewabilityTrackingAgent = [[MOPUBNativeVideoImpressionAgent alloc] initWithVideoView:videoView requiredVisibilityPercentage:self.videoConfig.minimumFractionOfVideoVisible requiredPlaybackDuration:self.videoConfig.minimumViewabilityTimeInterval];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
Copyright (c) 2011, The ORMMA.org project authors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the ORMMA.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS MR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER MR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, MR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS MR SERVICES; LOSS OF USE, DATA, MR PROFITS; MR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, MR TORT (INCLUDING NEGLIGENCE MR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,100 +0,0 @@
|
|||
//
|
||||
// MPMRAIDBannerCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMRAIDBannerCustomEvent.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPAdConfiguration.h"
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MRController.h"
|
||||
#import "MPWebView.h"
|
||||
#import "MPViewabilityTracker.h"
|
||||
|
||||
@interface MPMRAIDBannerCustomEvent () <MRControllerDelegate>
|
||||
|
||||
@property (nonatomic, strong) MRController *mraidController;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPMRAIDBannerCustomEvent
|
||||
|
||||
- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info
|
||||
{
|
||||
MPLogInfo(@"Loading MoPub MRAID banner");
|
||||
MPAdConfiguration *configuration = [self.delegate configuration];
|
||||
|
||||
CGRect adViewFrame = CGRectZero;
|
||||
if ([configuration hasPreferredSize]) {
|
||||
adViewFrame = CGRectMake(0, 0, configuration.preferredSize.width,
|
||||
configuration.preferredSize.height);
|
||||
}
|
||||
|
||||
self.mraidController = [[MPInstanceProvider sharedProvider] buildBannerMRControllerWithFrame:adViewFrame delegate:self];
|
||||
[self.mraidController loadAdWithConfiguration:configuration];
|
||||
}
|
||||
|
||||
#pragma mark - MRControllerDelegate
|
||||
|
||||
- (CLLocation *)location
|
||||
{
|
||||
return [self.delegate location];
|
||||
}
|
||||
|
||||
- (NSString *)adUnitId
|
||||
{
|
||||
return [self.delegate adUnitId];
|
||||
}
|
||||
|
||||
- (MPAdConfiguration *)adConfiguration
|
||||
{
|
||||
return [self.delegate configuration];
|
||||
}
|
||||
|
||||
- (UIViewController *)viewControllerForPresentingModalView
|
||||
{
|
||||
return [self.delegate viewControllerForPresentingModalView];
|
||||
}
|
||||
|
||||
- (void)adDidLoad:(UIView *)adView
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID banner did load");
|
||||
[self.delegate bannerCustomEvent:self didLoadAd:adView];
|
||||
}
|
||||
|
||||
- (void)adDidFailToLoad:(UIView *)adView
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID banner did fail");
|
||||
[self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
}
|
||||
|
||||
- (void)closeButtonPressed
|
||||
{
|
||||
//don't care
|
||||
}
|
||||
|
||||
- (void)appShouldSuspendForAd:(UIView *)adView
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID banner will begin action");
|
||||
[self.delegate bannerCustomEventWillBeginAction:self];
|
||||
}
|
||||
|
||||
- (void)appShouldResumeFromAd:(UIView *)adView
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID banner did end action");
|
||||
[self.delegate bannerCustomEventDidFinishAction:self];
|
||||
}
|
||||
|
||||
- (void)trackMPXAndThirdPartyImpressions
|
||||
{
|
||||
[self.mraidController.mraidWebView stringByEvaluatingJavaScriptFromString:@"webviewDidAppear();"];
|
||||
}
|
||||
|
||||
- (void)startViewabilityTracker
|
||||
{
|
||||
[self.mraidController.viewabilityTracker startTracking];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// MPMRAIDInterstitialCustomEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMRAIDInterstitialCustomEvent.h"
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
@interface MPMRAIDInterstitialCustomEvent ()
|
||||
|
||||
@property (nonatomic, strong) MPMRAIDInterstitialViewController *interstitial;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPMRAIDInterstitialCustomEvent
|
||||
|
||||
@synthesize interstitial = _interstitial;
|
||||
|
||||
- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info
|
||||
{
|
||||
MPLogInfo(@"Loading MoPub MRAID interstitial");
|
||||
self.interstitial = [[MPInstanceProvider sharedProvider] buildMPMRAIDInterstitialViewControllerWithDelegate:self
|
||||
configuration:[self.delegate configuration]];
|
||||
|
||||
// The MRAID ad view will handle the close button so we don't need the MPInterstitialViewController's close button.
|
||||
[self.interstitial setCloseButtonStyle:MPInterstitialCloseButtonStyleAlwaysHidden];
|
||||
[self.interstitial startLoading];
|
||||
}
|
||||
|
||||
- (void)showInterstitialFromRootViewController:(UIViewController *)controller
|
||||
{
|
||||
[self.interstitial presentInterstitialFromViewController:controller];
|
||||
}
|
||||
|
||||
#pragma mark - MPMRAIDInterstitialViewControllerDelegate
|
||||
|
||||
- (CLLocation *)location
|
||||
{
|
||||
return [self.delegate location];
|
||||
}
|
||||
|
||||
- (NSString *)adUnitId
|
||||
{
|
||||
return [self.delegate adUnitId];
|
||||
}
|
||||
|
||||
- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial did load");
|
||||
[self.delegate interstitialCustomEvent:self didLoadAd:self.interstitial];
|
||||
}
|
||||
|
||||
- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial did fail");
|
||||
[self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil];
|
||||
}
|
||||
|
||||
- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial will appear");
|
||||
[self.delegate interstitialCustomEventWillAppear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial did appear");
|
||||
[self.delegate interstitialCustomEventDidAppear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial will disappear");
|
||||
[self.delegate interstitialCustomEventWillDisappear:self];
|
||||
}
|
||||
|
||||
- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial did disappear");
|
||||
[self.delegate interstitialCustomEventDidDisappear:self];
|
||||
|
||||
// Deallocate the interstitial as we don't need it anymore. If we don't deallocate the interstitial after dismissal,
|
||||
// then the html in the webview will continue to run which could lead to bugs such as continuing to play the sound of an inline
|
||||
// video since the app may hold onto the interstitial ad controller. Moreover, we keep an array of controllers around as well.
|
||||
self.interstitial = nil;
|
||||
}
|
||||
|
||||
- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial did receive tap event");
|
||||
[self.delegate interstitialCustomEventDidReceiveTapEvent:self];
|
||||
}
|
||||
|
||||
- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial
|
||||
{
|
||||
MPLogInfo(@"MoPub MRAID interstitial will leave application");
|
||||
[self.delegate interstitialCustomEventWillLeaveApplication:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,10 +0,0 @@
|
|||
//
|
||||
// MRError.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MRError.h"
|
||||
|
||||
NSString * const MoPubMRAIDAdsSDKDomain = @"com.mopub.iossdk.mraid";
|
|
@ -1,41 +0,0 @@
|
|||
//
|
||||
// MRExpandModalViewController.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPClosableView.h"
|
||||
#import "MPForceableOrientationProtocol.h"
|
||||
@protocol MRExpandModalViewControllerDelegate;
|
||||
|
||||
/**
|
||||
* `MRExpandModalViewController` is specifically for presenting expanded MRAID ads. Its orientation can be
|
||||
* forced via the orientationMask property.
|
||||
*/
|
||||
@interface MRExpandModalViewController : UIViewController <MPClosableViewDelegate, MPForceableOrientationProtocol>
|
||||
|
||||
/**
|
||||
* Initializes the view controller with an orientation mask that defines what orientation
|
||||
* the view controller supports. When using an orientation mask on initialization, the view controlller
|
||||
* will force the orientation of the device to match the orientation mask if the app supports it.
|
||||
*/
|
||||
- (instancetype)initWithOrientationMask:(UIInterfaceOrientationMask)orientationMask;
|
||||
|
||||
/**
|
||||
* Hides the status bar when called. Every call to hideStatusBar should be matched with a call to
|
||||
* restoreStatusBarVisibility. That is, each time hideStatusBar is called, restoreStatusBarVisibility
|
||||
* must be called before calling hideStatusBar again. If the methods aren't called in the correct order,
|
||||
* consecutive calls to this method become no ops.
|
||||
*/
|
||||
- (void)hideStatusBar;
|
||||
|
||||
/**
|
||||
* This will set the visibility of the status bar based on whether or not the status bar was hidden when hideStatusBar was called.
|
||||
* A call to this method should be matched with a call to hideStatusBar. That is, each call to restoreStatusBarVisibility should
|
||||
* be preceded by a call to hideStatusBar. Calling this method consecutively will not affect the status bar beyond the first call.
|
||||
*/
|
||||
- (void)restoreStatusBarVisibility;
|
||||
|
||||
@end
|
|
@ -1,104 +0,0 @@
|
|||
//
|
||||
// MRExpandModalViewController.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MRExpandModalViewController.h"
|
||||
#import "MPGlobal.h"
|
||||
|
||||
@interface MRExpandModalViewController ()
|
||||
|
||||
@property (nonatomic, assign) BOOL statusBarHidden;
|
||||
@property (nonatomic, assign) BOOL applicationHidesStatusBar;
|
||||
@property (nonatomic, assign) UIInterfaceOrientationMask supportedOrientationMask;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MRExpandModalViewController
|
||||
|
||||
- (instancetype)initWithOrientationMask:(UIInterfaceOrientationMask)orientationMask
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_supportedOrientationMask = orientationMask;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
|
||||
- (void)hideStatusBar
|
||||
{
|
||||
if (!self.statusBarHidden) {
|
||||
self.statusBarHidden = YES;
|
||||
self.applicationHidesStatusBar = [UIApplication sharedApplication].statusBarHidden;
|
||||
|
||||
// pre-ios 7 hiding status bar
|
||||
[[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:YES];
|
||||
|
||||
// In the event we come back to this view controller from another modal, we need to update the status bar's
|
||||
// visibility again in ios 7/8.
|
||||
if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)restoreStatusBarVisibility
|
||||
{
|
||||
self.statusBarHidden = self.applicationHidesStatusBar;
|
||||
|
||||
// pre-ios 7 restoring the status bar
|
||||
[[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:self.applicationHidesStatusBar];
|
||||
|
||||
// ios 7/8 restoring status bar
|
||||
if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
// ios 7 hiding status bar
|
||||
return self.statusBarHidden;
|
||||
}
|
||||
|
||||
- (void)setSupportedOrientationMask:(UIInterfaceOrientationMask)supportedOrientationMask
|
||||
{
|
||||
_supportedOrientationMask = supportedOrientationMask;
|
||||
|
||||
[UIViewController attemptRotationToDeviceOrientation];
|
||||
}
|
||||
|
||||
// supportedInterfaceOrientations and shouldAutorotate are for ios 6, 7, and 8.
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_9_0
|
||||
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
|
||||
#else
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
#endif
|
||||
{
|
||||
return ([[UIApplication sharedApplication] mp_supportsOrientationMask:self.supportedOrientationMask]) ? self.supportedOrientationMask : UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - <MPClosableViewDelegate>
|
||||
|
||||
// We transfer closable view delegation to the expand view controller in the event MRController is deallocated and the expand modal is presented.
|
||||
- (void)closeButtonPressed:(MPClosableView *)closableView
|
||||
{
|
||||
// All we need to do is dismiss ourself.
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,57 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MRVideoPlayerManager.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
#import "MPInstanceProvider.h"
|
||||
|
||||
@implementation MRVideoPlayerManager
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
- (id)initWithDelegate:(id<MRVideoPlayerManagerDelegate>)delegate
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:MPMoviePlayerPlaybackDidFinishNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)playVideo:(NSURL *)url
|
||||
{
|
||||
if (!url) {
|
||||
[self.delegate videoPlayerManager:self didFailToPlayVideoWithErrorMessage:@"URI was not valid."];
|
||||
return;
|
||||
}
|
||||
|
||||
MPMoviePlayerViewController *controller = [[MPInstanceProvider sharedProvider] buildMPMoviePlayerViewControllerWithURL:url];
|
||||
|
||||
[self.delegate videoPlayerManagerWillPresentVideo:self];
|
||||
[[self.delegate viewControllerForPresentingVideoPlayer] presentViewController:controller animated:MP_ANIMATED completion:nil];
|
||||
|
||||
// Avoid subscribing to the notification multiple times in the event the user plays the video more than once.
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:MPMoviePlayerPlaybackDidFinishNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(moviePlayerPlaybackDidFinish:)
|
||||
name:MPMoviePlayerPlaybackDidFinishNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)moviePlayerPlaybackDidFinish:(NSNotification *)notification
|
||||
{
|
||||
[self.delegate videoPlayerManagerDidDismissVideo:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// NSString+MPAdditions.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSString+MPAdditions.h"
|
||||
|
||||
@implementation NSString (MPAdditions)
|
||||
|
||||
- (NSString *)mp_URLEncodedString {
|
||||
NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
|
||||
(CFStringRef)self,
|
||||
NULL,
|
||||
(CFStringRef)@"!*'();:@&=+$,/?%#[]<>",
|
||||
kCFStringEncodingUTF8));
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSNumber *)safeIntegerValue {
|
||||
// Reusable number formatter since reallocating this is expensive.
|
||||
static NSNumberFormatter * formatter = nil;
|
||||
if (formatter == nil) {
|
||||
formatter = [[NSNumberFormatter alloc] init];
|
||||
formatter.numberStyle = NSNumberFormatterNoStyle;
|
||||
}
|
||||
|
||||
return [formatter numberFromString:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// UIButton+MPAdditions.h
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIButton (MPAdditions)
|
||||
|
||||
@property (nonatomic) UIEdgeInsets mp_TouchAreaInsets;
|
||||
|
||||
@end
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// UIButton+MPAdditions.m
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIButton+MPAdditions.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation UIButton (MPAdditions)
|
||||
|
||||
- (UIEdgeInsets)mp_TouchAreaInsets
|
||||
{
|
||||
return [objc_getAssociatedObject(self, @selector(mp_TouchAreaInsets)) UIEdgeInsetsValue];
|
||||
}
|
||||
|
||||
- (void)setMp_TouchAreaInsets:(UIEdgeInsets)touchAreaInsets
|
||||
{
|
||||
NSValue *value = [NSValue valueWithUIEdgeInsets:touchAreaInsets];
|
||||
objc_setAssociatedObject(self, @selector(mp_TouchAreaInsets), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
UIEdgeInsets touchAreaInsets = self.mp_TouchAreaInsets;
|
||||
CGRect bounds = self.bounds;
|
||||
bounds = CGRectMake(bounds.origin.x - touchAreaInsets.left,
|
||||
bounds.origin.y - touchAreaInsets.top,
|
||||
bounds.size.width + touchAreaInsets.left + touchAreaInsets.right,
|
||||
bounds.size.height + touchAreaInsets.top + touchAreaInsets.bottom);
|
||||
return CGRectContainsPoint(bounds, point);
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// UIView+MPAdditions.h
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIView (MPAdditions)
|
||||
|
||||
@property (nonatomic) CGFloat mp_x;
|
||||
@property (nonatomic) CGFloat mp_y;
|
||||
@property (nonatomic) CGFloat mp_height;
|
||||
@property (nonatomic) CGFloat mp_width;
|
||||
|
||||
- (void)setMp_x:(CGFloat)mp_x;
|
||||
- (void)setMp_y:(CGFloat)mp_y;
|
||||
- (void)setMp_width:(CGFloat)mp_width;
|
||||
- (void)setMp_height:(CGFloat)mp_height;
|
||||
|
||||
- (UIView *)mp_snapshotView;
|
||||
|
||||
// convert any UIView to UIImage view. We can apply blur effect on UIImage.
|
||||
- (UIImage *)mp_snapshot:(BOOL)usePresentationLayer;
|
||||
|
||||
@end
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// UIWebView+MPAdditions.h
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 11/6/11.
|
||||
// Copyright (c) 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
extern NSString *const kJavaScriptDisableDialogSnippet;
|
||||
|
||||
@interface UIWebView (MPAdditions)
|
||||
|
||||
- (void)mp_setScrollable:(BOOL)scrollable;
|
||||
- (void)disableJavaScriptDialogs;
|
||||
|
||||
@end
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// UIWebView+MPAdditions.m
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 11/6/11.
|
||||
// Copyright (c) 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIWebView+MPAdditions.h"
|
||||
|
||||
NSString *const kJavaScriptDisableDialogSnippet = @"window.alert = function() { }; window.prompt = function() { }; window.confirm = function() { };";
|
||||
|
||||
@implementation UIWebView (MPAdditions)
|
||||
|
||||
/*
|
||||
* Find all subviews that are UIScrollViews or subclasses and set their scrolling and bounce.
|
||||
*/
|
||||
- (void)mp_setScrollable:(BOOL)scrollable {
|
||||
if ([self respondsToSelector:@selector(scrollView)])
|
||||
{
|
||||
UIScrollView *scrollView = self.scrollView;
|
||||
scrollView.scrollEnabled = scrollable;
|
||||
scrollView.bounces = scrollable;
|
||||
}
|
||||
else
|
||||
{
|
||||
UIScrollView *scrollView = nil;
|
||||
for (UIView *v in self.subviews)
|
||||
{
|
||||
if ([v isKindOfClass:[UIScrollView class]])
|
||||
{
|
||||
scrollView = (UIScrollView *)v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scrollView.scrollEnabled = scrollable;
|
||||
scrollView.bounces = scrollable;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Redefine alert, prompt, and confirm to do nothing
|
||||
*/
|
||||
- (void)disableJavaScriptDialogs
|
||||
{
|
||||
[self stringByEvaluatingJavaScriptFromString:kJavaScriptDisableDialogSnippet];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// MOPUBExperimentProvider.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdDestinationDisplayAgent.h"
|
||||
|
||||
@interface MOPUBExperimentProvider : NSObject
|
||||
|
||||
+ (void)setDisplayAgentType:(MOPUBDisplayAgentType)displayAgentType;
|
||||
+ (void)setDisplayAgentFromAdServer:(MOPUBDisplayAgentType)displayAgentType;
|
||||
+ (MOPUBDisplayAgentType)displayAgentType;
|
||||
|
||||
@end
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// MOPUBExperimentProvider.m
|
||||
// MoPubSampleApp
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MOPUBExperimentProvider.h"
|
||||
|
||||
@implementation MOPUBExperimentProvider
|
||||
|
||||
static BOOL gIsDisplayAgentOverriddenByClient = NO;
|
||||
static MOPUBDisplayAgentType gDisplayAgentType = MOPUBDisplayAgentTypeInApp;
|
||||
|
||||
+ (void)setDisplayAgentType:(MOPUBDisplayAgentType)displayAgentType
|
||||
{
|
||||
gIsDisplayAgentOverriddenByClient = YES;
|
||||
gDisplayAgentType = displayAgentType;
|
||||
}
|
||||
|
||||
+ (void)setDisplayAgentFromAdServer:(MOPUBDisplayAgentType)displayAgentType
|
||||
{
|
||||
if (!gIsDisplayAgentOverriddenByClient) {
|
||||
gDisplayAgentType = displayAgentType;
|
||||
}
|
||||
}
|
||||
|
||||
+ (MOPUBDisplayAgentType)displayAgentType
|
||||
{
|
||||
return gDisplayAgentType;
|
||||
}
|
||||
|
||||
// used in test only
|
||||
+ (void)setDisplayAgentOverriddenByClientFlag:(BOOL)flag
|
||||
{
|
||||
gIsDisplayAgentOverriddenByClient = flag;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// MPAnalyticsTracker.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class MPAdConfiguration;
|
||||
|
||||
@interface MPAnalyticsTracker : NSObject
|
||||
|
||||
+ (MPAnalyticsTracker *)tracker;
|
||||
|
||||
- (void)trackImpressionForConfiguration:(MPAdConfiguration *)configuration;
|
||||
- (void)trackClickForConfiguration:(MPAdConfiguration *)configuration;
|
||||
- (void)sendTrackingRequestForURLs:(NSArray *)URLs;
|
||||
|
||||
@end
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// MPError.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString * const kMOPUBErrorDomain;
|
||||
|
||||
typedef enum {
|
||||
MOPUBErrorUnknown = -1,
|
||||
MOPUBErrorNoInventory = 0,
|
||||
MOPUBErrorAdUnitWarmingUp = 1,
|
||||
MOPUBErrorNetworkTimedOut = 4,
|
||||
MOPUBErrorServerError = 8,
|
||||
MOPUBErrorAdapterNotFound = 16,
|
||||
MOPUBErrorAdapterInvalid = 17,
|
||||
MOPUBErrorAdapterHasNoInventory = 18,
|
||||
MOPUBErrorUnableToParseJSONAdResponse,
|
||||
MOPUBErrorUnexpectedNetworkResponse,
|
||||
MOPUBErrorNoNetworkData,
|
||||
} MOPUBErrorCode;
|
||||
|
||||
@interface MOPUBError : NSError
|
||||
|
||||
+ (MOPUBError *)errorWithCode:(MOPUBErrorCode)code;
|
||||
|
||||
@end
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// MPError.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2012 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPError.h"
|
||||
|
||||
NSString * const kMOPUBErrorDomain = @"com.mopub.iossdk";
|
||||
|
||||
@implementation MOPUBError
|
||||
|
||||
+ (MOPUBError *)errorWithCode:(MOPUBErrorCode)code
|
||||
{
|
||||
return [self errorWithDomain:kMOPUBErrorDomain code:code userInfo:nil];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// MPInternalUtils.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define SUPPRESS_PERFORM_SELECTOR_LEAK_WARNING(code) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
|
||||
code; \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
|
||||
@interface MPInternalUtils : NSObject
|
||||
|
||||
@end
|
||||
|
||||
@interface NSMutableDictionary (MPInternalUtils)
|
||||
|
||||
- (void)mp_safeSetObject:(id)obj forKey:(id<NSCopying>)key;
|
||||
- (void)mp_safeSetObject:(id)obj forKey:(id<NSCopying>)key withDefault:(id)defaultObj;
|
||||
|
||||
@end
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// MPInternalUtils.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPInternalUtils.h"
|
||||
|
||||
@implementation MPInternalUtils
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSMutableDictionary (MPInternalUtils)
|
||||
|
||||
- (void)mp_safeSetObject:(id)obj forKey:(id<NSCopying>)key
|
||||
{
|
||||
if (obj != nil) {
|
||||
[self setObject:obj forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mp_safeSetObject:(id)obj forKey:(id<NSCopying>)key withDefault:(id)defaultObj
|
||||
{
|
||||
if (obj != nil) {
|
||||
[self setObject:obj forKey:key];
|
||||
} else {
|
||||
[self setObject:defaultObj forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// MPLogProvider.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPLogging.h"
|
||||
|
||||
@protocol MPLogger;
|
||||
|
||||
@interface MPLogProvider : NSObject
|
||||
|
||||
+ (MPLogProvider *)sharedLogProvider;
|
||||
- (void)addLogger:(id<MPLogger>)logger;
|
||||
- (void)removeLogger:(id<MPLogger>)logger;
|
||||
- (void)logMessage:(NSString *)message atLogLevel:(MPLogLevel)logLevel;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MPLogger <NSObject>
|
||||
|
||||
- (MPLogLevel)logLevel;
|
||||
- (void)logMessage:(NSString *)message;
|
||||
|
||||
@end
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// MPLogProvider.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPLogProvider.h"
|
||||
|
||||
@interface MPLogProvider ()
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *loggers;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPSystemLogger : NSObject <MPLogger>
|
||||
@end
|
||||
|
||||
@implementation MPLogProvider
|
||||
|
||||
#pragma mark - Singleton instance
|
||||
|
||||
+ (MPLogProvider *)sharedLogProvider
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
static MPLogProvider *sharedLogProvider;
|
||||
dispatch_once(&once, ^{
|
||||
sharedLogProvider = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedLogProvider;
|
||||
}
|
||||
|
||||
#pragma mark - Object Lifecycle
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_loggers = [NSMutableArray array];
|
||||
[self addLogger:[[MPSystemLogger alloc] init]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Loggers
|
||||
|
||||
- (void)addLogger:(id<MPLogger>)logger
|
||||
{
|
||||
[self.loggers addObject:logger];
|
||||
}
|
||||
|
||||
- (void)removeLogger:(id<MPLogger>)logger
|
||||
{
|
||||
[self.loggers removeObject:logger];
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
- (void)logMessage:(NSString *)message atLogLevel:(MPLogLevel)logLevel
|
||||
{
|
||||
[self.loggers enumerateObjectsUsingBlock:^(id<MPLogger> logger, NSUInteger idx, BOOL *stop) {
|
||||
if ([logger logLevel] <= logLevel) {
|
||||
[logger logMessage:message];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPSystemLogger
|
||||
|
||||
- (void)logMessage:(NSString *)message
|
||||
{
|
||||
NSLog(@"%@", message);
|
||||
}
|
||||
|
||||
- (MPLogLevel)logLevel
|
||||
{
|
||||
return MPLogGetLevel();
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,42 +0,0 @@
|
|||
//
|
||||
// MPLogging.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPConstants.h"
|
||||
#import "MPLogLevel.h"
|
||||
|
||||
extern NSString * const kMPClearErrorLogFormatWithAdUnitID;
|
||||
extern NSString * const kMPWarmingUpErrorLogFormatWithAdUnitID;
|
||||
|
||||
MPLogLevel MPLogGetLevel(void);
|
||||
void MPLogSetLevel(MPLogLevel level);
|
||||
void _MPLogTrace(NSString *format, ...);
|
||||
void _MPLogDebug(NSString *format, ...);
|
||||
void _MPLogInfo(NSString *format, ...);
|
||||
void _MPLogWarn(NSString *format, ...);
|
||||
void _MPLogError(NSString *format, ...);
|
||||
void _MPLogFatal(NSString *format, ...);
|
||||
|
||||
#if MP_DEBUG_MODE && !SPECS
|
||||
|
||||
#define MPLogTrace(...) _MPLogTrace(__VA_ARGS__)
|
||||
#define MPLogDebug(...) _MPLogDebug(__VA_ARGS__)
|
||||
#define MPLogInfo(...) _MPLogInfo(__VA_ARGS__)
|
||||
#define MPLogWarn(...) _MPLogWarn(__VA_ARGS__)
|
||||
#define MPLogError(...) _MPLogError(__VA_ARGS__)
|
||||
#define MPLogFatal(...) _MPLogFatal(__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define MPLogTrace(...) {}
|
||||
#define MPLogDebug(...) {}
|
||||
#define MPLogInfo(...) {}
|
||||
#define MPLogWarn(...) {}
|
||||
#define MPLogError(...) {}
|
||||
#define MPLogFatal(...) {}
|
||||
|
||||
#endif
|
|
@ -1,101 +0,0 @@
|
|||
//
|
||||
// MPLogging.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPLogging.h"
|
||||
#import "MPIdentityProvider.h"
|
||||
#import "MPLogProvider.h"
|
||||
|
||||
NSString * const kMPClearErrorLogFormatWithAdUnitID = @"No ads found for ad unit: %@";
|
||||
NSString * const kMPWarmingUpErrorLogFormatWithAdUnitID = @"Ad unit %@ is currently warming up. Please try again in a few minutes.";
|
||||
NSString * const kMPSystemLogPrefix = @"MOPUB: %@";
|
||||
|
||||
static MPLogLevel systemLogLevel = MPLogLevelInfo;
|
||||
|
||||
MPLogLevel MPLogGetLevel()
|
||||
{
|
||||
return systemLogLevel;
|
||||
}
|
||||
|
||||
void MPLogSetLevel(MPLogLevel level)
|
||||
{
|
||||
systemLogLevel = level;
|
||||
}
|
||||
|
||||
void _MPLog(MPLogLevel level, NSString *format, va_list args)
|
||||
{
|
||||
static NSString *sIdentifier;
|
||||
static NSString *sObfuscatedIdentifier;
|
||||
|
||||
if (!sIdentifier) {
|
||||
sIdentifier = [[MPIdentityProvider identifier] copy];
|
||||
}
|
||||
|
||||
if (!sObfuscatedIdentifier) {
|
||||
sObfuscatedIdentifier = [[MPIdentityProvider obfuscatedIdentifier] copy];
|
||||
}
|
||||
|
||||
NSString *logString = [[NSString alloc] initWithFormat:format arguments:args];
|
||||
|
||||
// Replace identifier with a obfuscated version when logging.
|
||||
logString = [logString stringByReplacingOccurrencesOfString:sIdentifier withString:sObfuscatedIdentifier];
|
||||
|
||||
[[MPLogProvider sharedLogProvider] logMessage:logString atLogLevel:level];
|
||||
}
|
||||
|
||||
void _MPLogTrace(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelTrace, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void _MPLogDebug(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelDebug, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void _MPLogWarn(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelWarn, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void _MPLogInfo(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelInfo, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void _MPLogError(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelError, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void _MPLogFatal(NSString *format, ...)
|
||||
{
|
||||
format = [NSString stringWithFormat:kMPSystemLogPrefix, format];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_MPLog(MPLogLevelFatal, format, args);
|
||||
va_end(args);
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
File: Reachability.h
|
||||
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
|
||||
Version: 3.5
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#import <netinet/in.h>
|
||||
|
||||
|
||||
typedef enum : NSInteger {
|
||||
MPNotReachable = 0,
|
||||
MPReachableViaWiFi,
|
||||
MPReachableViaWWAN
|
||||
} MPNetworkStatus;
|
||||
|
||||
|
||||
extern NSString *kMPReachabilityChangedNotification;
|
||||
|
||||
|
||||
@interface MPReachability : NSObject
|
||||
|
||||
/*!
|
||||
* Use to check the reachability of a given host name.
|
||||
*/
|
||||
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
|
||||
|
||||
/*!
|
||||
* Use to check the reachability of a given IP address.
|
||||
*/
|
||||
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
|
||||
|
||||
/*!
|
||||
* Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
|
||||
*/
|
||||
+ (instancetype)reachabilityForInternetConnection;
|
||||
|
||||
/*!
|
||||
* Checks whether a local WiFi connection is available.
|
||||
*/
|
||||
+ (instancetype)reachabilityForLocalWiFi;
|
||||
|
||||
/*!
|
||||
* Start listening for reachability notifications on the current run loop.
|
||||
*/
|
||||
- (BOOL)startNotifier;
|
||||
- (void)stopNotifier;
|
||||
|
||||
- (MPNetworkStatus)currentReachabilityStatus;
|
||||
|
||||
/*!
|
||||
* WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
|
||||
*/
|
||||
- (BOOL)connectionRequired;
|
||||
- (BOOL)hasWifi;
|
||||
- (BOOL)hasCellular;
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// MPSessionTracker.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPSessionTracker : NSObject
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// MPFeatureDetector.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPGlobal.h"
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
@class SKStoreProductViewController;
|
||||
|
||||
@interface MPStoreKitProvider : NSObject
|
||||
|
||||
+ (BOOL)deviceHasStoreKit;
|
||||
+ (SKStoreProductViewController *)buildController;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MPSKStoreProductViewControllerDelegate <SKStoreProductViewControllerDelegate>
|
||||
@end
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// MPFeatureDetector.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2013 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPStoreKitProvider.h"
|
||||
#import "MPGlobal.h"
|
||||
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
/*
|
||||
* On iOS 7 and above, SKStoreProductViewController can cause a crash if the application does not list Portrait as a supported
|
||||
* interface orientation. Specifically, SKStoreProductViewController's shouldAutorotate returns YES, even though
|
||||
* the SKStoreProductViewController's supported interface orientations does not intersect with the application's list.
|
||||
*
|
||||
* To fix, we disallow autorotation so the SKStoreProductViewController will use its supported orientation on iOS 7 devices.
|
||||
*/
|
||||
@interface MPiOS7SafeStoreProductViewController : SKStoreProductViewController
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPiOS7SafeStoreProductViewController
|
||||
|
||||
- (BOOL)shouldAutorotate
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPStoreKitProvider
|
||||
|
||||
+ (BOOL)deviceHasStoreKit
|
||||
{
|
||||
return !!NSClassFromString(@"SKStoreProductViewController");
|
||||
}
|
||||
|
||||
+ (SKStoreProductViewController *)buildController
|
||||
{
|
||||
// use our safe subclass on iOS 7 and above
|
||||
if ([[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) {
|
||||
return [[MPiOS7SafeStoreProductViewController alloc] init];
|
||||
} else {
|
||||
return [[SKStoreProductViewController alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// MPTimer.h
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 3/8/11.
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/*
|
||||
* MPTimer wraps an NSTimer and adds pause/resume functionality.
|
||||
*/
|
||||
@interface MPTimer : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *runLoopMode;
|
||||
|
||||
+ (MPTimer *)timerWithTimeInterval:(NSTimeInterval)seconds
|
||||
target:(id)target
|
||||
selector:(SEL)aSelector
|
||||
repeats:(BOOL)repeats;
|
||||
|
||||
- (BOOL)isValid;
|
||||
- (void)invalidate;
|
||||
- (BOOL)isScheduled;
|
||||
- (BOOL)scheduleNow;
|
||||
- (BOOL)pause;
|
||||
- (BOOL)resume;
|
||||
- (NSTimeInterval)initialTimeInterval;
|
||||
|
||||
@end
|
|
@ -1,177 +0,0 @@
|
|||
//
|
||||
// MPTimer.m
|
||||
// MoPub
|
||||
//
|
||||
// Created by Andrew He on 3/8/11.
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPTimer.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPInternalUtils.h"
|
||||
|
||||
@interface MPTimer ()
|
||||
@property (nonatomic, assign) NSTimeInterval timeInterval;
|
||||
@property (nonatomic, strong) NSTimer *timer;
|
||||
@property (nonatomic, copy) NSDate *pauseDate;
|
||||
@property (nonatomic, assign) BOOL isPaused;
|
||||
@end
|
||||
|
||||
@interface MPTimer ()
|
||||
|
||||
@property (nonatomic, weak) id target;
|
||||
@property (nonatomic, assign) SEL selector;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPTimer
|
||||
|
||||
@synthesize timeInterval = _timeInterval;
|
||||
@synthesize timer = _timer;
|
||||
@synthesize pauseDate = _pauseDate;
|
||||
@synthesize target = _target;
|
||||
@synthesize selector = _selector;
|
||||
@synthesize isPaused = _isPaused;
|
||||
|
||||
+ (MPTimer *)timerWithTimeInterval:(NSTimeInterval)seconds
|
||||
target:(id)target
|
||||
selector:(SEL)aSelector
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
MPTimer *timer = [[MPTimer alloc] init];
|
||||
timer.target = target;
|
||||
timer.selector = aSelector;
|
||||
timer.timer = [NSTimer timerWithTimeInterval:seconds
|
||||
target:timer
|
||||
selector:@selector(timerDidFire)
|
||||
userInfo:nil
|
||||
repeats:repeats];
|
||||
timer.timeInterval = seconds;
|
||||
timer.runLoopMode = NSDefaultRunLoopMode;
|
||||
return timer;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.timer invalidate];
|
||||
}
|
||||
|
||||
- (void)timerDidFire
|
||||
{
|
||||
SUPPRESS_PERFORM_SELECTOR_LEAK_WARNING(
|
||||
[self.target performSelector:self.selector withObject:nil]
|
||||
);
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return [self.timer isValid];
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
self.target = nil;
|
||||
self.selector = nil;
|
||||
[self.timer invalidate];
|
||||
self.timer = nil;
|
||||
}
|
||||
|
||||
- (BOOL)isScheduled
|
||||
{
|
||||
if (!self.timer) {
|
||||
return NO;
|
||||
}
|
||||
CFRunLoopRef runLoopRef = [[NSRunLoop currentRunLoop] getCFRunLoop];
|
||||
CFArrayRef arrayRef = CFRunLoopCopyAllModes(runLoopRef);
|
||||
CFIndex count = CFArrayGetCount(arrayRef);
|
||||
|
||||
for (CFIndex i = 0; i < count; ++i) {
|
||||
CFStringRef runLoopMode = CFArrayGetValueAtIndex(arrayRef, i);
|
||||
if (CFRunLoopContainsTimer(runLoopRef, (__bridge CFRunLoopTimerRef)self.timer, runLoopMode)) {
|
||||
CFRelease(arrayRef);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(arrayRef);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)scheduleNow
|
||||
{
|
||||
if (![self.timer isValid]) {
|
||||
MPLogDebug(@"Could not schedule invalidated MPTimer (%p).", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:self.runLoopMode];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)pause
|
||||
{
|
||||
NSTimeInterval secondsLeft;
|
||||
if (self.isPaused) {
|
||||
MPLogDebug(@"No-op: tried to pause an MPTimer (%p) that was already paused.", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (![self.timer isValid]) {
|
||||
MPLogDebug(@"Cannot pause invalidated MPTimer (%p).", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (![self isScheduled]) {
|
||||
MPLogDebug(@"No-op: tried to pause an MPTimer (%p) that was never scheduled.", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSDate *fireDate = [self.timer fireDate];
|
||||
self.pauseDate = [NSDate date];
|
||||
secondsLeft = [fireDate timeIntervalSinceDate:self.pauseDate];
|
||||
if (secondsLeft <= 0) {
|
||||
MPLogWarn(@"An MPTimer was somehow paused after it was supposed to fire.");
|
||||
} else {
|
||||
MPLogDebug(@"Paused MPTimer (%p) %.1f seconds left before firing.", self, secondsLeft);
|
||||
}
|
||||
|
||||
// Pause the timer by setting its fire date far into the future.
|
||||
[self.timer setFireDate:[NSDate distantFuture]];
|
||||
self.isPaused = YES;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)resume
|
||||
{
|
||||
if (![self.timer isValid]) {
|
||||
MPLogDebug(@"Cannot resume invalidated MPTimer (%p).", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!self.isPaused) {
|
||||
MPLogDebug(@"No-op: tried to resume an MPTimer (%p) that was never paused.", self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
MPLogDebug(@"Resumed MPTimer (%p), should fire in %.1f seconds.", self.timeInterval);
|
||||
|
||||
// Resume the timer.
|
||||
NSDate *newFireDate = [NSDate dateWithTimeInterval:self.timeInterval sinceDate:[NSDate date]];
|
||||
[self.timer setFireDate:newFireDate];
|
||||
|
||||
if (![self isScheduled]) {
|
||||
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:self.runLoopMode];
|
||||
}
|
||||
|
||||
self.isPaused = NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)initialTimeInterval
|
||||
{
|
||||
return self.timeInterval;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// MPVASTCompanionAd.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPVASTModel.h"
|
||||
|
||||
@interface MPVASTCompanionAd : MPVASTModel
|
||||
|
||||
@property (nonatomic, readonly) CGFloat assetHeight;
|
||||
@property (nonatomic, readonly) CGFloat assetWidth;
|
||||
@property (nonatomic, copy, readonly) NSURL *clickThroughURL;
|
||||
@property (nonatomic, readonly) NSArray *clickTrackingURLs;
|
||||
@property (nonatomic, readonly) CGFloat height;
|
||||
@property (nonatomic, readonly) NSArray *HTMLResources;
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
@property (nonatomic, readonly) NSArray *iframeResources;
|
||||
@property (nonatomic, readonly) NSArray *staticResources;
|
||||
@property (nonatomic, readonly) NSDictionary *trackingEvents;
|
||||
@property (nonatomic, readonly) CGFloat width;
|
||||
|
||||
@end
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// MPVASTLinearAd.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPVASTModel.h"
|
||||
|
||||
@class MPVASTDurationOffset;
|
||||
@class MPVASTMediaFile;
|
||||
|
||||
@interface MPVASTLinearAd : MPVASTModel
|
||||
|
||||
@property (nonatomic, copy, readonly) NSURL *clickThroughURL;
|
||||
@property (nonatomic, readonly) NSArray *clickTrackingURLs;
|
||||
@property (nonatomic, readonly) NSArray *customClickURLs;
|
||||
@property (nonatomic, readonly) NSTimeInterval duration;
|
||||
@property (nonatomic, readonly) NSArray *industryIcons;
|
||||
@property (nonatomic, readonly) NSArray *mediaFiles;
|
||||
@property (nonatomic, readonly) MPVASTDurationOffset *skipOffset;
|
||||
@property (nonatomic, readonly) NSDictionary *trackingEvents;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPVASTLinearAd (Media)
|
||||
@property (nonatomic, readonly) MPVASTMediaFile *highestBitrateMediaFile;
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// MPVASTManager.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPVASTResponse.h"
|
||||
|
||||
typedef enum {
|
||||
MPVASTErrorXMLParseFailure,
|
||||
MPVASTErrorExceededMaximumWrapperDepth,
|
||||
MPVASTErrorNoAdsFound
|
||||
} MPVASTError;
|
||||
|
||||
@interface MPVASTManager : NSObject
|
||||
|
||||
+ (void)fetchVASTWithURL:(NSURL *)URL completion:(void (^)(MPVASTResponse *, NSError *))completion;
|
||||
+ (void)fetchVASTWithData:(NSData *)data completion:(void (^)(MPVASTResponse *, NSError *))completion;
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// MPVASTMediaFile.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MPVASTModel.h"
|
||||
|
||||
@interface MPVASTMediaFile : MPVASTModel
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
@property (nonatomic, copy, readonly) NSString *delivery;
|
||||
@property (nonatomic, copy, readonly) NSString *mimeType;
|
||||
@property (nonatomic, readonly) double bitrate;
|
||||
@property (nonatomic, readonly) CGFloat width;
|
||||
@property (nonatomic, readonly) CGFloat height;
|
||||
@property (nonatomic, copy, readonly) NSURL *URL;
|
||||
|
||||
@end
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// MPVASTMediaFile.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPVASTMediaFile.h"
|
||||
#import "MPVASTStringUtilities.h"
|
||||
|
||||
@implementation MPVASTMediaFile
|
||||
|
||||
+ (NSDictionary *)modelMap
|
||||
{
|
||||
return @{@"bitrate": @[@"bitrate", MPParseNumberFromString(NSNumberFormatterDecimalStyle)],
|
||||
@"height": @[@"height", MPParseNumberFromString(NSNumberFormatterDecimalStyle)],
|
||||
@"width": @[@"width", MPParseNumberFromString(NSNumberFormatterDecimalStyle)],
|
||||
@"identifier": @"id",
|
||||
@"delivery": @"delivery",
|
||||
@"mimeType": @"type",
|
||||
@"URL": @[@"text", MPParseURLFromString()]};
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// MPVASTResource.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPVASTModel.h"
|
||||
|
||||
@interface MPVASTResource : MPVASTModel
|
||||
|
||||
@property (nonatomic, readonly) NSString *content;
|
||||
@property (nonatomic, readonly) NSString *staticCreativeType;
|
||||
|
||||
@end
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// MPVASTResource.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPVASTResource.h"
|
||||
|
||||
@implementation MPVASTResource
|
||||
|
||||
+ (NSDictionary *)modelMap
|
||||
{
|
||||
return @{@"content": @"text",
|
||||
@"staticCreativeType": @"creativeType"};
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// MPVASTTrackingEvent.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPVASTModel.h"
|
||||
|
||||
@class MPVASTDurationOffset;
|
||||
|
||||
extern NSString * const MPVASTTrackingEventTypeCreativeView;
|
||||
extern NSString * const MPVASTTrackingEventTypeStart;
|
||||
extern NSString * const MPVASTTrackingEventTypeFirstQuartile;
|
||||
extern NSString * const MPVASTTrackingEventTypeMidpoint;
|
||||
extern NSString * const MPVASTTrackingEventTypeThirdQuartile;
|
||||
extern NSString * const MPVASTTrackingEventTypeComplete;
|
||||
extern NSString * const MPVASTTrackingEventTypeMute;
|
||||
extern NSString * const MPVASTTrackingEventTypeUnmute;
|
||||
extern NSString * const MPVASTTrackingEventTypePause;
|
||||
extern NSString * const MPVASTTrackingEventTypeRewind;
|
||||
extern NSString * const MPVASTTrackingEventTypeResume;
|
||||
extern NSString * const MPVASTTrackingEventTypeFullscreen;
|
||||
extern NSString * const MPVASTTrackingEventTypeExitFullscreen;
|
||||
extern NSString * const MPVASTTrackingEventTypeExpand;
|
||||
extern NSString * const MPVASTTrackingEventTypeCollapse;
|
||||
extern NSString * const MPVASTTrackingEventTypeAcceptInvitationLinear;
|
||||
extern NSString * const MPVASTTrackingEventTypeCloseLinear;
|
||||
extern NSString * const MPVASTTrackingEventTypeSkip;
|
||||
extern NSString * const MPVASTTrackingEventTypeProgress;
|
||||
|
||||
@interface MPVASTTrackingEvent : MPVASTModel
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *eventType;
|
||||
@property (nonatomic, copy, readonly) NSURL *URL;
|
||||
@property (nonatomic, readonly) MPVASTDurationOffset *progressOffset;
|
||||
|
||||
@end
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// MPVASTTrackingEvent.m
|
||||
// MoPub
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPVASTTrackingEvent.h"
|
||||
#import "MPVASTDurationOffset.h"
|
||||
|
||||
NSString * const MPVASTTrackingEventTypeCreativeView = @"creativeView";
|
||||
NSString * const MPVASTTrackingEventTypeStart = @"start";
|
||||
NSString * const MPVASTTrackingEventTypeFirstQuartile = @"firstQuartile";
|
||||
NSString * const MPVASTTrackingEventTypeMidpoint = @"midpoint";
|
||||
NSString * const MPVASTTrackingEventTypeThirdQuartile = @"thirdQuartile";
|
||||
NSString * const MPVASTTrackingEventTypeComplete = @"complete";
|
||||
NSString * const MPVASTTrackingEventTypeMute = @"mute";
|
||||
NSString * const MPVASTTrackingEventTypeUnmute = @"unmute";
|
||||
NSString * const MPVASTTrackingEventTypePause = @"pause";
|
||||
NSString * const MPVASTTrackingEventTypeRewind = @"rewind";
|
||||
NSString * const MPVASTTrackingEventTypeResume = @"resume";
|
||||
NSString * const MPVASTTrackingEventTypeFullscreen = @"fullscreen";
|
||||
NSString * const MPVASTTrackingEventTypeExitFullscreen = @"exitFullscreen";
|
||||
NSString * const MPVASTTrackingEventTypeExpand = @"expand";
|
||||
NSString * const MPVASTTrackingEventTypeCollapse = @"collapse";
|
||||
NSString * const MPVASTTrackingEventTypeAcceptInvitationLinear = @"acceptInvitationLinear";
|
||||
NSString * const MPVASTTrackingEventTypeCloseLinear = @"closeLinear";
|
||||
NSString * const MPVASTTrackingEventTypeSkip = @"skip";
|
||||
NSString * const MPVASTTrackingEventTypeProgress = @"progress";
|
||||
|
||||
@implementation MPVASTTrackingEvent
|
||||
|
||||
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
|
||||
{
|
||||
self = [super initWithDictionary:dictionary];
|
||||
if (self) {
|
||||
_eventType = dictionary[@"event"];
|
||||
|
||||
_URL = [self generateModelFromDictionaryValue:dictionary
|
||||
modelProvider:^id(NSDictionary *dictionary) {
|
||||
return [NSURL URLWithString:[dictionary[@"text"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
|
||||
}];
|
||||
// a tracker that does not specify a URL is not valid
|
||||
if (_URL == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_progressOffset = [self generateModelFromDictionaryValue:dictionary
|
||||
modelProvider:^id(NSDictionary *dictionary) {
|
||||
return [[MPVASTDurationOffset alloc] initWithDictionary:dictionary];
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// MOPUBDisplayAgentType.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
typedef NS_ENUM(NSInteger, MOPUBDisplayAgentType) {
|
||||
MOPUBDisplayAgentTypeInApp = 0,
|
||||
MOPUBDisplayAgentTypeNativeSafari,
|
||||
MOPUBDisplayAgentTypeSafariViewController
|
||||
};
|
|
@ -1,186 +0,0 @@
|
|||
//
|
||||
// MPAdView.m
|
||||
// MoPub
|
||||
//
|
||||
// Created by Nafis Jamal on 1/19/11.
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAdView.h"
|
||||
#import "MPClosableView.h"
|
||||
#import "MPBannerAdManager.h"
|
||||
#import "MPInstanceProvider.h"
|
||||
#import "MPBannerAdManagerDelegate.h"
|
||||
#import "MPLogging.h"
|
||||
|
||||
@interface MPAdView () <MPBannerAdManagerDelegate>
|
||||
|
||||
@property (nonatomic, strong) MPBannerAdManager *adManager;
|
||||
@property (nonatomic, weak) UIView *adContentView;
|
||||
@property (nonatomic, assign) CGSize originalSize;
|
||||
@property (nonatomic, assign) MPNativeAdOrientation allowedNativeAdOrientation;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPAdView
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Lifecycle
|
||||
|
||||
- (id)initWithAdUnitId:(NSString *)adUnitId size:(CGSize)size
|
||||
{
|
||||
CGRect f = (CGRect){{0, 0}, size};
|
||||
if (self = [super initWithFrame:f])
|
||||
{
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.clipsToBounds = YES;
|
||||
self.originalSize = size;
|
||||
self.allowedNativeAdOrientation = MPNativeAdOrientationAny;
|
||||
self.adUnitId = (adUnitId) ? adUnitId : DEFAULT_PUB_ID;
|
||||
self.adManager = [[MPBannerAdManager alloc] initWithDelegate:self];
|
||||
self.userInteractionEnabled = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
self.adManager.delegate = nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setAdContentView:(UIView *)view
|
||||
{
|
||||
[self.adContentView removeFromSuperview];
|
||||
_adContentView = view;
|
||||
[self addSubview:view];
|
||||
|
||||
if (view != nil) {
|
||||
self.userInteractionEnabled = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)adContentViewSize
|
||||
{
|
||||
// MPClosableView represents an MRAID ad.
|
||||
if (!self.adContentView || [self.adContentView isKindOfClass:[MPClosableView class]]) {
|
||||
return self.originalSize;
|
||||
} else {
|
||||
return self.adContentView.bounds.size;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation
|
||||
{
|
||||
[self.adManager rotateToOrientation:newOrientation];
|
||||
}
|
||||
|
||||
- (void)loadAd
|
||||
{
|
||||
[self.adManager loadAd];
|
||||
}
|
||||
|
||||
- (void)refreshAd
|
||||
{
|
||||
[self loadAd];
|
||||
}
|
||||
|
||||
- (void)forceRefreshAd
|
||||
{
|
||||
[self.adManager forceRefreshAd];
|
||||
}
|
||||
|
||||
- (void)stopAutomaticallyRefreshingContents
|
||||
{
|
||||
[self.adManager stopAutomaticallyRefreshingContents];
|
||||
}
|
||||
|
||||
- (void)startAutomaticallyRefreshingContents
|
||||
{
|
||||
[self.adManager startAutomaticallyRefreshingContents];
|
||||
}
|
||||
|
||||
- (void)lockNativeAdsToOrientation:(MPNativeAdOrientation)orientation
|
||||
{
|
||||
self.allowedNativeAdOrientation = orientation;
|
||||
}
|
||||
|
||||
- (void)unlockNativeAdsOrientation
|
||||
{
|
||||
self.allowedNativeAdOrientation = MPNativeAdOrientationAny;
|
||||
}
|
||||
|
||||
- (MPNativeAdOrientation)allowedNativeAdsOrientation
|
||||
{
|
||||
return self.allowedNativeAdOrientation;
|
||||
}
|
||||
|
||||
#pragma mark - <MPBannerAdManagerDelegate>
|
||||
|
||||
- (MPAdView *)banner
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<MPAdViewDelegate>)bannerDelegate
|
||||
{
|
||||
return self.delegate;
|
||||
}
|
||||
|
||||
- (CGSize)containerSize
|
||||
{
|
||||
return self.originalSize;
|
||||
}
|
||||
|
||||
- (UIViewController *)viewControllerForPresentingModalView
|
||||
{
|
||||
return [self.delegate viewControllerForPresentingModalView];
|
||||
}
|
||||
|
||||
- (void)invalidateContentView
|
||||
{
|
||||
[self setAdContentView:nil];
|
||||
}
|
||||
|
||||
- (void)managerDidFailToLoadAd
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(adViewDidFailToLoadAd:)]) {
|
||||
// make sure we are not released synchronously as objects owned by us
|
||||
// may do additional work after this callback
|
||||
[[MPCoreInstanceProvider sharedProvider] keepObjectAliveForCurrentRunLoopIteration:self];
|
||||
|
||||
[self.delegate adViewDidFailToLoadAd:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)managerDidLoadAd:(UIView *)ad
|
||||
{
|
||||
[self setAdContentView:ad];
|
||||
if ([self.delegate respondsToSelector:@selector(adViewDidLoadAd:)]) {
|
||||
[self.delegate adViewDidLoadAd:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)userActionWillBegin
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(willPresentModalViewForAd:)]) {
|
||||
[self.delegate willPresentModalViewForAd:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)userActionDidFinish
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(didDismissModalViewForAd:)]) {
|
||||
[self.delegate didDismissModalViewForAd:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)userWillLeaveApplication
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(willLeaveApplicationFromAd:)]) {
|
||||
[self.delegate willLeaveApplicationFromAd:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// MPAdvancedBidder.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol MPAdvancedBidder <NSObject>
|
||||
@required
|
||||
/**
|
||||
* The name of the network that generated the token.
|
||||
* @remark This value should correspond to `creative_network_name` in the dashboard.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSString * _Nonnull creativeNetworkName;
|
||||
|
||||
/**
|
||||
* An identity token needed for ORTB requests to the bidder.
|
||||
*/
|
||||
@property (nonatomic, copy, readonly) NSString * _Nonnull token;
|
||||
@end
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// MPConstants.h
|
||||
// MoPub
|
||||
//
|
||||
// Copyright 2011 MoPub, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define MP_DEBUG_MODE 1
|
||||
|
||||
#define MP_HAS_NATIVE_PACKAGE 1
|
||||
|
||||
#define DEFAULT_PUB_ID @"agltb3B1Yi1pbmNyDAsSBFNpdGUYkaoMDA"
|
||||
#define MP_SERVER_VERSION @"8"
|
||||
#define MP_BUNDLE_IDENTIFIER @"com.mopub.mopub"
|
||||
#define MP_SDK_VERSION @"5.0.0"
|
||||
|
||||
// Sizing constants.
|
||||
extern CGSize const MOPUB_BANNER_SIZE;
|
||||
extern CGSize const MOPUB_MEDIUM_RECT_SIZE;
|
||||
extern CGSize const MOPUB_LEADERBOARD_SIZE;
|
||||
extern CGSize const MOPUB_WIDE_SKYSCRAPER_SIZE;
|
||||
|
||||
// Miscellaneous constants.
|
||||
#define MINIMUM_REFRESH_INTERVAL 10.0
|
||||
#define DEFAULT_BANNER_REFRESH_INTERVAL 60
|
||||
#define BANNER_TIMEOUT_INTERVAL 10
|
||||
#define INTERSTITIAL_TIMEOUT_INTERVAL 30
|
||||
#define REWARDED_VIDEO_TIMEOUT_INTERVAL 30
|
||||
#define MOPUB_ADS_EXPIRATION_INTERVAL 14400 // 4 hours converted to seconds
|
||||
|
||||
// Feature Flags
|
||||
#define SESSION_TRACKING_ENABLED 1
|
||||
|
||||
@interface MPConstants : NSObject
|
||||
|
||||
+ (NSTimeInterval)adsExpirationInterval;
|
||||
|
||||
@end
|
|
@ -1,21 +0,0 @@
|
|||
//
|
||||
// MPConstants.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPConstants.h"
|
||||
|
||||
CGSize const MOPUB_BANNER_SIZE = { .width = 320.0f, .height = 50.0f };
|
||||
CGSize const MOPUB_MEDIUM_RECT_SIZE = { .width = 300.0f, .height = 250.0f };
|
||||
CGSize const MOPUB_LEADERBOARD_SIZE = { .width = 728.0f, .height = 90.0f };
|
||||
CGSize const MOPUB_WIDE_SKYSCRAPER_SIZE = { .width = 160.0f, .height = 600.0f };
|
||||
|
||||
@implementation MPConstants
|
||||
|
||||
+ (NSTimeInterval)adsExpirationInterval {
|
||||
return MOPUB_ADS_EXPIRATION_INTERVAL;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// MPLogLevel.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* SDK logging level.
|
||||
* @remark Lower values equate to more detailed logs.
|
||||
*/
|
||||
typedef enum {
|
||||
MPLogLevelAll = 0,
|
||||
MPLogLevelTrace = 10,
|
||||
MPLogLevelDebug = 20,
|
||||
MPLogLevelInfo = 30,
|
||||
MPLogLevelWarn = 40,
|
||||
MPLogLevelError = 50,
|
||||
MPLogLevelFatal = 60,
|
||||
MPLogLevelOff = 70
|
||||
} MPLogLevel;
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// MPMediationSdkInitializable.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright © 2018 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
Indicates that the implementer is initializable by the MoPub SDK when
|
||||
@c initializeSdkWithConfiguration:complete: is called, or whenever the
|
||||
mediated network needs to be initialized.
|
||||
*/
|
||||
@protocol MPMediationSdkInitializable <NSObject>
|
||||
|
||||
/**
|
||||
Called when the MoPub SDK requires the underlying mediation SDK to be initialized.
|
||||
|
||||
@param parameters A dictionary containing any mediation SDK-specific information
|
||||
needed for initialization, such as app IDs and placement IDs.
|
||||
*/
|
||||
- (void)initializeSdkWithParameters:(NSDictionary * _Nullable)parameters;
|
||||
|
||||
@end
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// MPMoPubConfiguration.h
|
||||
// MoPubSampleApp
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPAdvancedBidder.h"
|
||||
#import "MPMediationSdkInitializable.h"
|
||||
#import "MPMediationSettingsProtocol.h"
|
||||
#import "MPRewardedVideo.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MPMoPubConfiguration : NSObject
|
||||
/**
|
||||
Any valid ad unit ID used within the app used for app initialization.
|
||||
@remark This is a required field.
|
||||
*/
|
||||
@property (nonatomic, strong, nonnull) NSString * adUnitIdForAppInitialization;
|
||||
|
||||
/**
|
||||
Optional list of advanced bidders to initialize.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSArray<Class<MPAdvancedBidder>> * advancedBidders;
|
||||
|
||||
/**
|
||||
Optional global configurations for all ad networks your app supports.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSArray<id<MPMediationSettingsProtocol>> * globalMediationSettings;
|
||||
|
||||
/**
|
||||
Optional list of mediated network SDKs to pre-initialize from the cache. If the mediated network
|
||||
SDK has no cache entry, nothing will be done. If set to @c nil or empty array, no network
|
||||
SDKs will be preinitialized.
|
||||
|
||||
To initialize all existing cached networks use @c MoPub.sharedInstance.allCachedNetworks
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSArray<Class<MPMediationSdkInitializable>> * mediatedNetworks;
|
||||
|
||||
/**
|
||||
Initializes the @c MPMoPubConfiguration object with the required fields.
|
||||
@param adUnitId Any valid ad unit ID used within the app used for app initialization.
|
||||
@return A configuration instance.
|
||||
*/
|
||||
- (instancetype)initWithAdUnitIdForAppInitialization:(NSString *)adUnitId NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
Usage of default initializer is disallowed. Use @c initWithAdUnitIdForAppInitialization: instead.
|
||||
*/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
Usage of @c new is disallowed. Use @c initWithAdUnitIdForAppInitialization: instead.
|
||||
*/
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// MPMoPubConfiguration.m
|
||||
// MoPubSampleApp
|
||||
//
|
||||
// Copyright © 2017 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMoPubConfiguration.h"
|
||||
|
||||
@implementation MPMoPubConfiguration
|
||||
|
||||
- (instancetype)initWithAdUnitIdForAppInitialization:(NSString * _Nonnull)adUnitId {
|
||||
if (self = [super init]) {
|
||||
_adUnitIdForAppInitialization = adUnitId;
|
||||
_advancedBidders = nil;
|
||||
_globalMediationSettings = nil;
|
||||
_mediatedNetworks = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,51 +0,0 @@
|
|||
//
|
||||
// MoPub-Bridging-Header.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MoPub.h"
|
||||
|
||||
#import "MPAdConversionTracker.h"
|
||||
#import "MPAdView.h"
|
||||
#import "MPBannerCustomEvent.h"
|
||||
#import "MPBannerCustomEventDelegate.h"
|
||||
#import "MPConstants.h"
|
||||
#import "MPInterstitialAdController.h"
|
||||
#import "MPInterstitialCustomEvent.h"
|
||||
#import "MPInterstitialCustomEventDelegate.h"
|
||||
|
||||
#if MP_HAS_NATIVE_PACKAGE
|
||||
|
||||
#import "MPNativeAd.h"
|
||||
#import "MPNativeAdAdapter.h"
|
||||
#import "MPNativeAdConstants.h"
|
||||
#import "MPNativeCustomEvent.h"
|
||||
#import "MPNativeCustomEventDelegate.h"
|
||||
#import "MPNativeAdDelegate.h"
|
||||
#import "MPNativeAdError.h"
|
||||
#import "MPNativeAdRendering.h"
|
||||
#import "MPNativeAdRequest.h"
|
||||
#import "MPNativeAdRequestTargeting.h"
|
||||
#import "MPStaticNativeAdRendererSettings.h"
|
||||
#import "MPNativeAdRendererConfiguration.h"
|
||||
#import "MPNativeAdRendererSettings.h"
|
||||
#import "MPNativeAdRenderer.h"
|
||||
#import "MPStaticNativeAdRenderer.h"
|
||||
#import "MOPUBNativeVideoAdRendererSettings.h"
|
||||
#import "MOPUBNativeVideoAdRenderer.h"
|
||||
#import "MPNativeAdRenderingImageLoader.h"
|
||||
#import "MPClientAdPositioning.h"
|
||||
#import "MPServerAdPositioning.h"
|
||||
#import "MPCollectionViewAdPlacer.h"
|
||||
#import "MPTableViewAdPlacer.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#import "MPMediationSettingsProtocol.h"
|
||||
#import "MPRewardedVideo.h"
|
||||
#import "MPRewardedVideoReward.h"
|
||||
#import "MPRewardedVideoCustomEvent.h"
|
||||
#import "MPRewardedVideoError.h"
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Mopub.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// MPCollectionViewAdPlacerCell.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MPCollectionViewAdPlacerCell : UICollectionViewCell
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// MPCollectionViewAdPlacerCell.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2015 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPCollectionViewAdPlacerCell.h"
|
||||
|
||||
@implementation MPCollectionViewAdPlacerCell
|
||||
|
||||
@end
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// MPImageDownloadQueue.h
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef void (^MPImageDownloadQueueCompletionBlock)(NSArray *errors);
|
||||
|
||||
@interface MPImageDownloadQueue : NSObject
|
||||
|
||||
// pass useCachedImage:NO to force download of images. default is YES, cached images will not be re-downloaded
|
||||
- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock;
|
||||
- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock useCachedImage:(BOOL)useCachedImage;
|
||||
|
||||
- (void)cancelAllDownloads;
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
//
|
||||
// MPMoPubNativeCustomEvent.h
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPNativeCustomEvent.h"
|
||||
|
||||
@interface MPMoPubNativeCustomEvent : MPNativeCustomEvent
|
||||
|
||||
@end
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// MPMoPubNativeCustomEvent.m
|
||||
// MoPubSDK
|
||||
//
|
||||
// Copyright (c) 2014 MoPub. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPMoPubNativeCustomEvent.h"
|
||||
#import "MPMoPubNativeAdAdapter.h"
|
||||
#import "MPNativeAd+Internal.h"
|
||||
#import "MPNativeAdError.h"
|
||||
#import "MPLogging.h"
|
||||
#import "MPNativeAdUtils.h"
|
||||
|
||||
@implementation MPMoPubNativeCustomEvent
|
||||
|
||||
- (void)requestAdWithCustomEventInfo:(NSDictionary *)info
|
||||
{
|
||||
MPMoPubNativeAdAdapter *adAdapter = [[MPMoPubNativeAdAdapter alloc] initWithAdProperties:[info mutableCopy]];
|
||||
|
||||
if (adAdapter.properties) {
|
||||
MPNativeAd *interfaceAd = [[MPNativeAd alloc] initWithAdAdapter:adAdapter];
|
||||
[interfaceAd.impressionTrackerURLs addObjectsFromArray:adAdapter.impressionTrackerURLs];
|
||||
[interfaceAd.clickTrackerURLs addObjectsFromArray:adAdapter.clickTrackerURLs];
|
||||
|
||||
// Get the image urls so we can download them prior to returning the ad.
|
||||
NSMutableArray *imageURLs = [NSMutableArray array];
|
||||
for (NSString *key in [info allKeys]) {
|
||||
if ([[key lowercaseString] hasSuffix:@"image"] && [[info objectForKey:key] isKindOfClass:[NSString class]]) {
|
||||
if (![MPNativeAdUtils addURLString:[info objectForKey:key] toURLArray:imageURLs]) {
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidImageURL()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[super precacheImagesWithURLs:imageURLs completionBlock:^(NSArray *errors) {
|
||||
if (errors) {
|
||||
MPLogDebug(@"%@", errors);
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForImageDownloadFailure()];
|
||||
} else {
|
||||
[self.delegate nativeCustomEvent:self didLoadAd:interfaceAd];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(nil)];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue