From 9022c511016761eaf6599779fb9b9c783820082b Mon Sep 17 00:00:00 2001 From: Ron Lissack Date: Thu, 3 Apr 2014 14:27:29 -0400 Subject: [PATCH 1/8] AppStore version 1.13 --- .../AppNexusSDKApp.xcodeproj/project.pbxproj | 12 +++--------- .../AppNexusSDKApp/AppNexusSDKApp.plist | 4 ++-- .../xcschemes/ANMediatedViewsLibrary.xcscheme | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj b/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj index cd331d0f4..8abded540 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj +++ b/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj @@ -692,7 +692,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = Preview; - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0510; ORGANIZATIONNAME = AppNexus; TargetAttributes = { 8A9EFB0417CFD49200FCF79F = { @@ -891,10 +891,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - "armv7,", - armv7s, - ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -922,6 +918,7 @@ ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; SDKROOT = iphoneos; + VALID_ARCHS = "armv7 armv7s"; }; name = Debug; }; @@ -929,10 +926,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - "armv7,", - armv7s, - ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -954,6 +947,7 @@ OTHER_LDFLAGS = "-ObjC"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + VALID_ARCHS = "armv7 armv7s"; }; name = Release; }; diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist b/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist index f3ee9cbd1..dfd41f524 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist +++ b/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.12 + 1.13 CFBundleSignature ???? CFBundleURLTypes @@ -36,7 +36,7 @@ CFBundleVersion - 5 + 6 LSRequiresIPhoneOS UIMainStoryboardFile diff --git a/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/xcshareddata/xcschemes/ANMediatedViewsLibrary.xcscheme b/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/xcshareddata/xcschemes/ANMediatedViewsLibrary.xcscheme index 75ac6a62c..bf208120b 100644 --- a/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/xcshareddata/xcschemes/ANMediatedViewsLibrary.xcscheme +++ b/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/xcshareddata/xcschemes/ANMediatedViewsLibrary.xcscheme @@ -1,6 +1,6 @@ Date: Fri, 28 Mar 2014 14:47:37 -0400 Subject: [PATCH 2/8] MS-632 safer implementation of MRAID removeEventListeners --- sdk/Resources/MRAID.bundle/mraid.js | 86 +++++++++++++++-------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/sdk/Resources/MRAID.bundle/mraid.js b/sdk/Resources/MRAID.bundle/mraid.js index a741eb4e5..16fadfe94 100644 --- a/sdk/Resources/MRAID.bundle/mraid.js +++ b/sdk/Resources/MRAID.bundle/mraid.js @@ -363,43 +363,50 @@ placement_type=type; }; - mraid.util.readyEvent=function(){ - for(var i=0;i Date: Wed, 2 Apr 2014 15:18:44 -0400 Subject: [PATCH 3/8] MS-636 valid MediationController cleared when no resultCB --- sdk/internal/ANAdFetcher.m | 2 +- tests/TestClasses/MediationCallbacksTests.m | 13 ++++++++++++ tests/TestClasses/TestUtils/ANTestResponses.h | 2 ++ tests/TestClasses/TestUtils/ANTestResponses.m | 20 +++++++++++++++++++ tests/TestClasses/TestViews/ANTimeout.h | 2 +- tests/TestClasses/TestViews/ANTimeout.m | 10 +++++++++- 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/sdk/internal/ANAdFetcher.m b/sdk/internal/ANAdFetcher.m index 4e109d045..c7c29b040 100644 --- a/sdk/internal/ANAdFetcher.m +++ b/sdk/internal/ANAdFetcher.m @@ -332,8 +332,8 @@ - (void)handleMediatedAds:(NSMutableArray *)mediatedAds } } if (errorCode != ANDefaultCode) { - [self fireResultCB:currentAd.resultCB reason:errorCode adObject:nil]; [self clearMediationController]; + [self fireResultCB:currentAd.resultCB reason:errorCode adObject:nil]; return; } diff --git a/tests/TestClasses/MediationCallbacksTests.m b/tests/TestClasses/MediationCallbacksTests.m index a25f27dd2..d104af344 100644 --- a/tests/TestClasses/MediationCallbacksTests.m +++ b/tests/TestClasses/MediationCallbacksTests.m @@ -14,6 +14,7 @@ */ #import "ANBaseTestCase.h" +#import "ANTimeout.h" static NSString *const kANLoadedMultiple = @"ANLoadedMultiple"; static NSString *const kANTimeout = @"ANTimeout"; @@ -22,6 +23,7 @@ static NSString *const kANLoadAndHitOtherCallbacks = @"ANLoadAndHitOtherCallbacks"; static NSString *const kANFailAndHitOtherCallbacks = @"ANFailAndHitOtherCallbacks"; static NSString *const kANFailedMultiple = @"ANFailedMultiple"; +static NSString *const kClassDoesNotExist = @"ClassDoesNotExist"; @interface MediationCallbacksTests : ANBaseTestCase @property (nonatomic, readwrite, assign) BOOL adLoadedMultiple; @@ -69,6 +71,16 @@ - (void)checkCallbacks:(BOOL)called { #pragma mark MediationCallback tests +- (void)test17 +{ + [ANTimeout setTimeout:CALLBACKS_TIMEOUT - 1]; + [self stubWithBody:[ANTestResponses mediationWaterfallBanners:kClassDoesNotExist firstResult:@"" + secondClass:kANTimeout secondResult:@""]]; + [self stubResultCBResponses:@""]; + [self runBasicTest:YES waitTime:CALLBACKS_TIMEOUT]; + [self clearTest]; +} + - (void)test18LoadedMultiple { [self stubWithBody:[ANTestResponses createMediatedBanner:kANLoadedMultiple]]; @@ -79,6 +91,7 @@ - (void)test18LoadedMultiple - (void)test19Timeout { + [ANTimeout setTimeout:kAppNexusMediationNetworkTimeoutInterval + 1]; [self stubWithBody:[ANTestResponses createMediatedBanner:kANTimeout]]; [self stubResultCBResponses:@""]; [self runBasicTest:NO waitTime:kAppNexusMediationNetworkTimeoutInterval + CALLBACKS_TIMEOUT]; diff --git a/tests/TestClasses/TestUtils/ANTestResponses.h b/tests/TestClasses/TestUtils/ANTestResponses.h index 0adff9415..6bf88cb24 100644 --- a/tests/TestClasses/TestUtils/ANTestResponses.h +++ b/tests/TestClasses/TestUtils/ANTestResponses.h @@ -27,6 +27,8 @@ static NSString *const OK_RESULT_CB_URL = @"http://result"; + (NSString *)mediationWaterfallBanners:(NSString *)firstClass secondClass:(NSString *)secondClass; ++ (NSString *)mediationWaterfallBanners:(NSString *)firstClass firstResult:(NSString *)firstResult + secondClass:(NSString *)secondClass secondResult:(NSString *)secondResult; + (NSString *)mediationWaterfallBanners:(NSString *)firstClass firstResult:(NSString *)firstResult secondClass:(NSString *)secondClass secondResult:(NSString *)secondResult thirdClass:(NSString *)thirdClass thirdResult:(NSString *)thirdResult; diff --git a/tests/TestClasses/TestUtils/ANTestResponses.m b/tests/TestClasses/TestUtils/ANTestResponses.m index a7184df32..66ad6c0c0 100644 --- a/tests/TestClasses/TestUtils/ANTestResponses.m +++ b/tests/TestClasses/TestUtils/ANTestResponses.m @@ -71,6 +71,26 @@ + (NSString *)mediationWaterfallBanners:(NSString *)firstClass secondClass:(NSSt return [ANTestResponses createMediatedResponse:mediatedField]; } ++ (NSString *)mediationWaterfallBanners:(NSString *)firstClass firstResult:(NSString *)firstResult + secondClass:(NSString *)secondClass secondResult:(NSString *)secondResult { + ANMediatedAd *firstAd = [ANMediatedAd dummy]; + firstAd.className = firstClass; + NSString *firstHandler = [ANTestResponses createHandlerObjectFromMediatedAds: + [[NSMutableArray alloc] initWithObjects:firstAd, nil] + withResultCB:firstResult]; + + ANMediatedAd *secondAd = [ANMediatedAd dummy]; + secondAd.className = secondClass; + NSString *secondHandler = [ANTestResponses createHandlerObjectFromMediatedAds: + [[NSMutableArray alloc] initWithObjects:secondAd, nil] + withResultCB:secondResult]; + + NSString *mediatedField = [ANTestResponses createMediatedArrayFromHandlers: + [[NSMutableArray alloc] initWithObjects:firstHandler, + secondHandler, nil]]; + return [ANTestResponses createMediatedResponse:mediatedField]; +} + + (NSString *)mediationWaterfallBanners:(NSString *)firstClass firstResult:(NSString *)firstResult secondClass:(NSString *)secondClass secondResult:(NSString *)secondResult thirdClass:(NSString *)thirdClass thirdResult:(NSString *)thirdResult { diff --git a/tests/TestClasses/TestViews/ANTimeout.h b/tests/TestClasses/TestViews/ANTimeout.h index a319aaa7a..628764c18 100644 --- a/tests/TestClasses/TestViews/ANTimeout.h +++ b/tests/TestClasses/TestViews/ANTimeout.h @@ -17,5 +17,5 @@ #import "ANCustomAdapter.h" @interface ANTimeout : NSObject - ++ (void)setTimeout:(CGFloat)timeout; @end diff --git a/tests/TestClasses/TestViews/ANTimeout.m b/tests/TestClasses/TestViews/ANTimeout.m index 5b74da644..e158a4b0f 100644 --- a/tests/TestClasses/TestViews/ANTimeout.m +++ b/tests/TestClasses/TestViews/ANTimeout.m @@ -19,6 +19,8 @@ @implementation ANTimeout @synthesize delegate; +static CGFloat waitTime; + #pragma mark ANCustomAdapterBanner - (void)requestBannerAdWithSize:(CGSize)size @@ -27,12 +29,18 @@ - (void)requestBannerAdWithSize:(CGSize)size adUnitId:(NSString *)idString targetingParameters:(ANTargetingParameters *)targetingParameters { + NSLog(@"ANTimeout request"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, - (kAppNexusMediationNetworkTimeoutInterval + 1) + (waitTime) * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + NSLog(@"ANTimeout call loaded on %@", NSStringFromClass([self.delegate class])); [self.delegate didLoadBannerAd:[UIView new]]; }); } ++ (void)setTimeout:(CGFloat)timeout { + waitTime = timeout; +} + @end From 796eb645abc41455820ef4168d1c42a2670a9964 Mon Sep 17 00:00:00 2001 From: Mark Ha Date: Wed, 23 Apr 2014 14:38:53 -0400 Subject: [PATCH 4/8] MS-637 Improve consistency of AdFailed callback --- .../Classes/Controllers/AdPreviewTVC.m | 2 +- sdk/internal/ANAdFetcher.m | 155 ++++++++---------- sdk/internal/ANMediationAdViewController.m | 4 + 3 files changed, 76 insertions(+), 85 deletions(-) diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m b/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m index 6087ab55a..0d7368b59 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m +++ b/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m @@ -303,7 +303,7 @@ - (void)adFailedToDisplay:(ANInterstitialAd *)ad { } - (void)ad:(id)ad requestFailedWithError:(NSError *)error { - ANLogDebug(@"adFailed: %@", [error localizedDescription]); + ANLogDebug(@"adFailed with code %i: %@", [error code], [error localizedDescription]); [self.delegate ad:ad requestFailedWithError:error]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:kAppNexusSDKAppErrorTitle message:[error localizedDescription] diff --git a/sdk/internal/ANAdFetcher.m b/sdk/internal/ANAdFetcher.m index c7c29b040..83f2477e8 100644 --- a/sdk/internal/ANAdFetcher.m +++ b/sdk/internal/ANAdFetcher.m @@ -385,97 +385,84 @@ - (void)startAutoRefreshTimer { # pragma mark - # pragma mark NSURLConnectionDataDelegate -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response -{ - @synchronized(self) - { - if (connection == self.connection) - { - if ([response isKindOfClass:[NSHTTPURLResponse class]]) - { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - NSInteger status = [httpResponse statusCode]; - - if (status >= 400) - { - [connection cancel]; - NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat: - NSLocalizedString(@"Request failed with status code %d", @"Error Description: server request came back with error code."), - status] - forKey:NSLocalizedDescriptionKey]; - NSError *statusError = [NSError errorWithDomain:AN_ERROR_DOMAIN - code:status - userInfo:errorInfo]; - [self connection:connection didFailWithError:statusError]; - return; - } - } - - self.data = [NSMutableData data]; - - ANLogDebug(@"Received response: %@", response); - - [self setupAutoRefreshTimerIfNecessary]; - } - // don't process the success resultCB response, just log it. - else if (connection == self.successResultConnection) - { - if ([response isKindOfClass:[NSHTTPURLResponse class]]) - { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - NSInteger status = [httpResponse statusCode]; - - ANLogDebug(@"Received response with code %ld from response URL request.", status); - } - } else { - ANLogDebug(@"Received response from unknown"); +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + if (connection == self.connection) { + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + NSInteger status = [httpResponse statusCode]; + + if (status >= 400) { + [connection cancel]; + NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat: + NSLocalizedString(@"Request failed with status code %d", @"Error Description: server request came back with error code."), + status] + forKey:NSLocalizedDescriptionKey]; + NSError *statusError = [NSError errorWithDomain:AN_ERROR_DOMAIN + code:ANAdResponseNetworkError + userInfo:errorInfo]; + [self connection:connection didFailWithError:statusError]; + return; + } } - } + + self.data = [NSMutableData data]; + + ANLogDebug(@"Received response: %@", response); + + [self setupAutoRefreshTimerIfNecessary]; + } + // don't process the success resultCB response, just log it. + else if (connection == self.successResultConnection) { + if ([response isKindOfClass:[NSHTTPURLResponse class]]) + { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + NSInteger status = [httpResponse statusCode]; + + ANLogDebug(@"Received response with code %ld from response URL request.", status); + } + } else { + ANLogDebug(@"Received response from unknown"); + } } -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d -{ - @synchronized(self) - { - if (connection == self.connection) - { - [self.data appendData:d]; - } - } +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d { + if (connection == self.connection) { + [self.data appendData:d]; + } } -- (void)connectionDidFinishLoading:(NSURLConnection *)connection -{ - @synchronized(self) - { - if (connection == self.connection) - { - ANAdResponse *adResponse = [[ANAdResponse alloc] init]; - adResponse = [adResponse processResponseData:self.data]; - [self processAdResponse:adResponse]; - } - // don't do anything for a succcessful resultCB - else if (connection == self.successResultConnection) { - ANLogDebug(@"Success resultCB finished loading"); - } - } +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + if (connection == self.connection) { + ANAdResponse *adResponse = [[ANAdResponse alloc] init]; + adResponse = [adResponse processResponseData:self.data]; + [self processAdResponse:adResponse]; + } + // don't do anything for a succcessful resultCB + else if (connection == self.successResultConnection) { + ANLogDebug(@"Success resultCB finished loading"); + } } -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error -{ - @synchronized(self) - { - if (connection == self.connection) - { - ANLogError(@"Ad view connection %@ failed with error %@", connection, error); - - self.loading = NO; - - [self setupAutoRefreshTimerIfNecessary]; - ANAdResponse *failureResponse = [ANAdResponse adResponseFailWithError:error]; - [self processFinalResponse:failureResponse]; - } - } +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + if (connection == self.connection) { + NSString *errorMessage = [NSString stringWithFormat: + @"Ad request %@ failed with error %@", + connection, [error localizedDescription]]; + ANLogError(errorMessage); + + self.loading = NO; + + [self setupAutoRefreshTimerIfNecessary]; + + NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:errorMessage + forKey:NSLocalizedDescriptionKey]; + NSError *ANError = [NSError errorWithDomain:AN_ERROR_DOMAIN + code:ANAdResponseNetworkError + userInfo:errorInfo]; + + ANAdResponse *failureResponse = [ANAdResponse adResponseFailWithError:ANError]; + [self processFinalResponse:failureResponse]; + } } #pragma mark handling resultCB diff --git a/sdk/internal/ANMediationAdViewController.m b/sdk/internal/ANMediationAdViewController.m index 75344fffe..1d724ce56 100644 --- a/sdk/internal/ANMediationAdViewController.m +++ b/sdk/internal/ANMediationAdViewController.m @@ -169,6 +169,10 @@ - (BOOL)checkIfHasResponded { - (void)didReceiveAd:(id)adObject { if ([self checkIfHasResponded]) return; + if (!adObject) { + [self didFailToReceiveAd:ANAdResponseInternalError]; + return; + } self.hasSucceeded = YES; ANLogDebug(@"received an ad from the adapter"); From dbdc7551a881678b2e2eb9d006d219363c4371de Mon Sep 17 00:00:00 2001 From: Mark Ha Date: Mon, 7 Apr 2014 12:02:46 -0400 Subject: [PATCH 5/8] MS-571 ANJAM clientside implementation --- ANSDK.xcodeproj/project.pbxproj | 10 +- .../AppNexusSDKApp.xcodeproj/project.pbxproj | 18 +- .../Classes/Controllers/AdPreviewTVC.m | 8 +- .../project.pbxproj | 6 +- sdk/ANAdProtocol.h | 14 + sdk/ANBannerAdView.h | 6 + sdk/ANInterstitialAd.h | 6 + sdk/Categories/NSString+ANCategory.h | 1 + sdk/Categories/NSString+ANCategory.m | 36 +- sdk/Categories/UIView+ANCategory.h | 4 +- sdk/Categories/UIView+ANCategory.m | 8 + sdk/Resources/MRAID.bundle/mraid.js | 94 +-- sdk/Resources/anjam.js | 581 ++++++++++++++++++ sdk/Resources/sdkjs.js | 249 ++++++++ sdk/internal/ANANJAMImplementation.h | 25 + sdk/internal/ANANJAMImplementation.m | 205 ++++++ sdk/internal/ANAdFetcher.h | 3 +- sdk/internal/ANAdFetcher.m | 45 +- sdk/internal/ANAdRequestUrl.m | 3 +- sdk/internal/ANAdView.m | 15 +- sdk/internal/ANAdViewDelegate.h | 1 + sdk/internal/ANAdWebViewController.m | 41 +- sdk/internal/ANBrowserViewController.h | 2 + sdk/internal/ANBrowserViewController.m | 22 +- sdk/internal/ANGlobal.h | 6 +- sdk/internal/ANGlobal.m | 12 +- sdk/internal/ANInstallTrackerPixel.m | 3 +- sdk/internal/ANInterstitialAdViewController.m | 5 +- sdk/internal/ANMediationAdViewController.m | 2 +- sdk/internal/ANWebView.h | 6 +- sdk/internal/ANWebView.m | 26 +- 31 files changed, 1313 insertions(+), 150 deletions(-) create mode 100644 sdk/Resources/anjam.js create mode 100644 sdk/Resources/sdkjs.js create mode 100644 sdk/internal/ANANJAMImplementation.h create mode 100644 sdk/internal/ANANJAMImplementation.m diff --git a/ANSDK.xcodeproj/project.pbxproj b/ANSDK.xcodeproj/project.pbxproj index c0426becc..1f165bfa5 100644 --- a/ANSDK.xcodeproj/project.pbxproj +++ b/ANSDK.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ EC3E5E221843F0400070315E /* ANCustomAdapter.h in Copy Files */ = {isa = PBXBuildFile; fileRef = EC3E5E201843EFEF0070315E /* ANCustomAdapter.h */; }; EC3E5E231843F0400070315E /* ANLocation.h in Copy Files */ = {isa = PBXBuildFile; fileRef = EC3E5E211843EFEF0070315E /* ANLocation.h */; }; EC3E5E951843FDEC0070315E /* ANAdView.h in Copy Files */ = {isa = PBXBuildFile; fileRef = EC3E5E941843FDE20070315E /* ANAdView.h */; }; + EC4340651906F09200AC2D84 /* sdkjs.js in Resources */ = {isa = PBXBuildFile; fileRef = EC4340631906F08900AC2D84 /* sdkjs.js */; }; + EC43406B1908167400AC2D84 /* anjam.js in Resources */ = {isa = PBXBuildFile; fileRef = EC43406A1908167400AC2D84 /* anjam.js */; }; EC4817881845047A0066BBFE /* ANBrowserViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC48175E1845042A0066BBFE /* ANBrowserViewController.xib */; }; EC4817891845047A0066BBFE /* ANInterstitialAdViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC48175F1845042A0066BBFE /* ANInterstitialAdViewController.xib */; }; EC48178A1845047A0066BBFE /* errors.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC4817601845042A0066BBFE /* errors.strings */; }; @@ -136,6 +138,8 @@ EC3E5E201843EFEF0070315E /* ANCustomAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANCustomAdapter.h; sourceTree = ""; }; EC3E5E211843EFEF0070315E /* ANLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANLocation.h; sourceTree = ""; }; EC3E5E941843FDE20070315E /* ANAdView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANAdView.h; sourceTree = ""; }; + EC4340631906F08900AC2D84 /* sdkjs.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = sdkjs.js; sourceTree = ""; }; + EC43406A1908167400AC2D84 /* anjam.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = anjam.js; sourceTree = ""; }; EC48175E1845042A0066BBFE /* ANBrowserViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ANBrowserViewController.xib; sourceTree = ""; }; EC48175F1845042A0066BBFE /* ANInterstitialAdViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ANInterstitialAdViewController.xib; sourceTree = ""; }; EC4817601845042A0066BBFE /* errors.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = errors.strings; sourceTree = ""; }; @@ -149,9 +153,9 @@ EC4817691845042A0066BBFE /* UIButtonBarArrowRight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "UIButtonBarArrowRight@2x.png"; sourceTree = ""; }; EC48176A1845042A0066BBFE /* MRAID.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MRAID.bundle; sourceTree = ""; }; EC48177B1845046A0066BBFE /* ANSDKResources.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ANSDKResources.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + EC6AAEC61884B62300CD2FDC /* ANMRAIDProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANMRAIDProperties.h; sourceTree = ""; }; EC7AB08118887E4600C27B1E /* ANLogManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANLogManager.h; sourceTree = ""; }; EC7AB08218887E5300C27B1E /* ANLogManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANLogManager.m; sourceTree = ""; }; - EC6AAEC61884B62300CD2FDC /* ANMRAIDProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANMRAIDProperties.h; sourceTree = ""; }; EC9B33CA187DA9F300013F79 /* ANWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANWebView.h; sourceTree = ""; }; EC9B33CB187DA9F300013F79 /* ANWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANWebView.m; sourceTree = ""; }; EC9B3448187DEB6900013F79 /* ANAdRequestUrl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANAdRequestUrl.m; sourceTree = ""; }; @@ -283,6 +287,8 @@ EC48175D1845042A0066BBFE /* Resources */ = { isa = PBXGroup; children = ( + EC43406A1908167400AC2D84 /* anjam.js */, + EC4340631906F08900AC2D84 /* sdkjs.js */, EC48175E1845042A0066BBFE /* ANBrowserViewController.xib */, EC48175F1845042A0066BBFE /* ANInterstitialAdViewController.xib */, EC4817601845042A0066BBFE /* errors.strings */, @@ -378,6 +384,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + EC4340651906F09200AC2D84 /* sdkjs.js in Resources */, + EC43406B1908167400AC2D84 /* anjam.js in Resources */, EC4817881845047A0066BBFE /* ANBrowserViewController.xib in Resources */, EC4817891845047A0066BBFE /* ANInterstitialAdViewController.xib in Resources */, EC48178A1845047A0066BBFE /* errors.strings in Resources */, diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj b/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj index 8abded540..11a885ed3 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj +++ b/examples/AppNexusSDKApp/AppNexusSDKApp.xcodeproj/project.pbxproj @@ -82,7 +82,10 @@ EC3FD7611822213C00B25418 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = EC3FD7281822213C00B25418 /* Default.png */; }; EC3FD7621822213C00B25418 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EC3FD7291822213C00B25418 /* Default@2x.png */; }; EC4055EE183C07F9006A1D09 /* ANDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = EC4055ED183C07F9006A1D09 /* ANDocument.m */; }; + EC434069190815C700AC2D84 /* anjam.js in Resources */ = {isa = PBXBuildFile; fileRef = EC434068190815C700AC2D84 /* anjam.js */; }; + EC5D88B918F451FE0001E0B2 /* ANANJAMImplementation.m in Sources */ = {isa = PBXBuildFile; fileRef = EC5D88B818F451FE0001E0B2 /* ANANJAMImplementation.m */; }; EC70ED8D18316B2000BDF92F /* ANMRAIDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC70ED8C18316B2000BDF92F /* ANMRAIDViewController.m */; }; + EC75D2AB1906E888002A694A /* sdkjs.js in Resources */ = {isa = PBXBuildFile; fileRef = EC75D2AA1906E888002A694A /* sdkjs.js */; }; EC77B0A718170D8E002123CB /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC77B0A618170D8E002123CB /* StoreKit.framework */; }; EC7AB07F18887C2D00C27B1E /* ANLogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EC7AB07E18887C2D00C27B1E /* ANLogManager.m */; }; EC7DC2631817404600B813D1 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC7DC2621817404600B813D1 /* MediaPlayer.framework */; }; @@ -250,9 +253,13 @@ EC3FD7291822213C00B25418 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; EC4055EC183C07F9006A1D09 /* ANDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANDocument.h; sourceTree = ""; }; EC4055ED183C07F9006A1D09 /* ANDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANDocument.m; sourceTree = ""; }; + EC434068190815C700AC2D84 /* anjam.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = anjam.js; sourceTree = ""; }; + EC5D88B718F451FE0001E0B2 /* ANANJAMImplementation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANANJAMImplementation.h; sourceTree = ""; }; + EC5D88B818F451FE0001E0B2 /* ANANJAMImplementation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANANJAMImplementation.m; sourceTree = ""; }; EC6AAEC5188479C700CD2FDC /* ANMRAIDProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ANMRAIDProperties.h; sourceTree = ""; }; EC70ED8B18316B2000BDF92F /* ANWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANWebView.h; sourceTree = ""; }; EC70ED8C18316B2000BDF92F /* ANMRAIDViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANMRAIDViewController.m; sourceTree = ""; }; + EC75D2AA1906E888002A694A /* sdkjs.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = sdkjs.js; sourceTree = ""; }; EC77B0A618170D8E002123CB /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; EC7AB07E18887C2D00C27B1E /* ANLogManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANLogManager.m; sourceTree = ""; }; EC7AB08018887E2B00C27B1E /* ANLogManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANLogManager.h; sourceTree = ""; }; @@ -607,6 +614,8 @@ ECB124931821A25D00CB4BE8 /* ANAdViewDelegate.h */, ECB124941821A25D00CB4BE8 /* ANAdWebViewController.h */, ECB124951821A25D00CB4BE8 /* ANAdWebViewController.m */, + EC5D88B718F451FE0001E0B2 /* ANANJAMImplementation.h */, + EC5D88B818F451FE0001E0B2 /* ANANJAMImplementation.m */, ECB124961821A25D00CB4BE8 /* ANBannerAdView.m */, ECB124971821A25D00CB4BE8 /* ANBrowserViewController.h */, ECB124981821A25D00CB4BE8 /* ANBrowserViewController.m */, @@ -640,6 +649,8 @@ ECCF547618451FE40000E37C /* Resources */ = { isa = PBXGroup; children = ( + EC434068190815C700AC2D84 /* anjam.js */, + EC75D2AA1906E888002A694A /* sdkjs.js */, ECCF547718451FE40000E37C /* ANBrowserViewController.xib */, ECCF547818451FE40000E37C /* ANInterstitialAdViewController.xib */, ECCF547918451FE40000E37C /* errors.strings */, @@ -790,6 +801,8 @@ EC3FD7521822213C00B25418 /* appnexus_launch_image_ipad_landscape@2x.png in Resources */, EC3FD7591822213C00B25418 /* appnexus_settings_ipad.png in Resources */, ECCF548F18451FE40000E37C /* MRAID.bundle in Resources */, + EC75D2AB1906E888002A694A /* sdkjs.js in Resources */, + EC434069190815C700AC2D84 /* anjam.js in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -849,6 +862,7 @@ EC70ED8D18316B2000BDF92F /* ANMRAIDViewController.m in Sources */, ECB124CE1821A25D00CB4BE8 /* ANLocation.m in Sources */, EC3FD7361822213C00B25418 /* ANLog+Make.m in Sources */, + EC5D88B918F451FE0001E0B2 /* ANANJAMImplementation.m in Sources */, ECAFB02D1864EE25007F1973 /* ANTargetingParameters.m in Sources */, EC3FD7371822213C00B25418 /* ANLog.m in Sources */, ECB124BD1821A25D00CB4BE8 /* UIView+ANCategory.m in Sources */, @@ -965,7 +979,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = AppNexusSDKApp/AppNexusSDKApp.pch; INFOPLIST_FILE = AppNexusSDKApp/AppNexusSDKApp.plist; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = AppNexusSDKApp; PROVISIONING_PROFILE = ""; @@ -989,7 +1003,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = AppNexusSDKApp/AppNexusSDKApp.pch; INFOPLIST_FILE = AppNexusSDKApp/AppNexusSDKApp.plist; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = AppNexusSDKApp; PROVISIONING_PROFILE = ""; diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m b/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m index 0d7368b59..20f348448 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m +++ b/examples/AppNexusSDKApp/AppNexusSDKApp/Classes/Controllers/AdPreviewTVC.m @@ -31,7 +31,7 @@ NSString *const kAppNexusSDKAppNewInterstitialTitle = @"Load New Interstitial"; NSString *const KAppNexusSDKAppShowInterstitialTitle = @"Display Interstitial"; -@interface AdPreviewTVC () +@interface AdPreviewTVC () @property (strong, nonatomic) ANBannerAdView *bannerAdView; @property (strong, nonatomic) ANInterstitialAd *interstitialAd; @@ -158,6 +158,7 @@ - (void)loadBannerAd { self.bannerAdView = [[ANBannerAdView alloc] initWithFrame:CGRectMake(centerX, centerY, settingsBannerWidth, settingsBannerHeight)]; self.bannerAdView.delegate = self; + self.bannerAdView.appEventDelegate = self; self.bannerAdView.rootViewController = self; self.bannerAdView.adSize = CGSizeMake(settingsBannerWidth, settingsBannerHeight); self.bannerAdView.placementId = settingsPlacementID; @@ -180,6 +181,7 @@ - (void)loadInterstitialAd { self.interstitialAd = [[ANInterstitialAd alloc] initWithPlacementId:settingsPlacementID]; self.interstitialAd.delegate = self; + self.interstitialAd.appEventDelegate = self; self.interstitialAd.closeDelay = 0.5f; self.interstitialAd.backgroundColor = [AppNexusSDKAppGlobal colorFromString:backgroundColor]; [self loadAdvancedSettingsOnAdView:self.interstitialAd]; @@ -350,6 +352,10 @@ - (void)adWillLeaveApplication:(id)ad { ANLogDebug(@"adWillLeaveApplication"); } +- (void)ad:(id)ad didReceiveAppEvent:(NSString *)name withData:(NSString *)data { + ANLogDebug(@"adDidReceiveAppEvent: %@, %@", name, data); +} + /* Explictly deallocating ad views on controller deallocation to avoid a memory leak. */ diff --git a/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/project.pbxproj b/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/project.pbxproj index 6e7bcf81b..6f2eacf3c 100644 --- a/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/project.pbxproj +++ b/mediation/mediatedviews/ANMediatedViewsLibrary/ANMediatedViewsLibrary.xcodeproj/project.pbxproj @@ -317,7 +317,7 @@ ECB1236818219C9D00CB4BE8 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0510; ORGANIZATIONNAME = AppNexus; }; buildConfigurationList = ECB1236B18219C9D00CB4BE8 /* Build configuration list for PBXProject "ANMediatedViewsLibrary" */; @@ -361,7 +361,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -390,7 +389,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 7.0; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; @@ -399,7 +398,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; diff --git a/sdk/ANAdProtocol.h b/sdk/ANAdProtocol.h index e0c342ae3..72f97bbc5 100644 --- a/sdk/ANAdProtocol.h +++ b/sdk/ANAdProtocol.h @@ -166,3 +166,17 @@ typedef enum _ANGender - (void)adWillLeaveApplication:(id)ad; @end + +/** + Delegate to receive app events from the ad. + */ +@protocol ANAppEventDelegate + +/** + Called when the ad has sent the app an event via the AppNexus + Javascript API for Mobile + */ +- (void)ad:(id)ad +didReceiveAppEvent:(NSString *)name withData:(NSString *)data; + +@end diff --git a/sdk/ANBannerAdView.h b/sdk/ANBannerAdView.h index 1473a1363..3e9aef07e 100644 --- a/sdk/ANBannerAdView.h +++ b/sdk/ANBannerAdView.h @@ -45,6 +45,12 @@ */ @property (nonatomic, readwrite, weak) id delegate; +/** + Delegate object that receives custom app event notifications from this + ANBannerAdView. + */ +@property (nonatomic, readwrite, weak) id appEventDelegate; + /** Required reference to the root view controller. Used as shown in the example above to set the banner ad view's controller to your diff --git a/sdk/ANInterstitialAd.h b/sdk/ANInterstitialAd.h index 23bf056cb..ea3eb99b9 100644 --- a/sdk/ANInterstitialAd.h +++ b/sdk/ANInterstitialAd.h @@ -46,6 +46,12 @@ @property (nonatomic, readwrite, weak) id delegate; +/** + Delegate object that receives custom app event notifications from this + ANInterstitialAd. + */ +@property (nonatomic, readwrite, weak) id appEventDelegate; + /** The ad view's background color. */ diff --git a/sdk/Categories/NSString+ANCategory.h b/sdk/Categories/NSString+ANCategory.h index 9b8512876..72415726d 100644 --- a/sdk/Categories/NSString+ANCategory.h +++ b/sdk/Categories/NSString+ANCategory.h @@ -18,6 +18,7 @@ @interface NSString (ANCategory) - (NSDictionary *)queryComponents; +- (NSString *)encodeAsURIComponent; - (NSString *)stringByAppendingUrlParameter:(NSString *)name value:(NSString*)value; @end diff --git a/sdk/Categories/NSString+ANCategory.m b/sdk/Categories/NSString+ANCategory.m index cfa2f50fc..893aa7c03 100644 --- a/sdk/Categories/NSString+ANCategory.m +++ b/sdk/Categories/NSString+ANCategory.m @@ -56,28 +56,24 @@ - (NSString*)encodeAsURIComponent return result; } -- (NSString *)stringByAppendingUrlParameter:(NSString *)name value:(NSString*)value -{ - NSMutableString *string =[self mutableCopy]; - - if ([string rangeOfString:@"="].length!=0) - { - [string appendFormat:@"&%@=%@", name, [value encodeAsURIComponent]]; - } - else - { - if ([string rangeOfString:@"?"].location != [string length] - 1) - { - [string appendFormat:@"?%@=%@", name, [value encodeAsURIComponent]]; - - } - else - { - [string appendFormat:@"%@=%@", name, [value encodeAsURIComponent]]; - } +- (NSString *)stringByAppendingUrlParameter:(NSString *)name + value:(NSString *)value { + // don't append anything if either field is empty + if (([name length] < 1) || ([value length] < 1)) { + return self; } + + NSMutableString *parameter = [NSMutableString stringWithFormat:@"%@=%@", + name, [value encodeAsURIComponent]]; + + // add the proper prefix depending on the current string + if ([self rangeOfString:@"="].length != 0) { + [parameter insertString:@"&" atIndex:0]; + } else if ([self rangeOfString:@"?"].location != ([self length] - 1)) { + [parameter insertString:@"?" atIndex:0]; + } // otherwise, keep the string as it is - return string; + return [self stringByAppendingString:parameter]; } @end diff --git a/sdk/Categories/UIView+ANCategory.h b/sdk/Categories/UIView+ANCategory.h index 1565b9292..709c7a22a 100644 --- a/sdk/Categories/UIView+ANCategory.h +++ b/sdk/Categories/UIView+ANCategory.h @@ -22,4 +22,6 @@ - (void)dismissFromPresentingViewAnimated:(BOOL)animated; -@end \ No newline at end of file +- (void)removeSubviews; + +@end diff --git a/sdk/Categories/UIView+ANCategory.m b/sdk/Categories/UIView+ANCategory.m index 15d95ef2d..6aa92ead0 100644 --- a/sdk/Categories/UIView+ANCategory.m +++ b/sdk/Categories/UIView+ANCategory.m @@ -51,4 +51,12 @@ - (void)dismissFromPresentingViewAnimated:(BOOL)animated }]; } +- (void)removeSubviews { + for (UIView *view in [self subviews]) { + if ([view respondsToSelector:@selector(removeFromSuperview)]) { + [view performSelector:@selector(removeFromSuperview)]; + } + } +} + @end diff --git a/sdk/Resources/MRAID.bundle/mraid.js b/sdk/Resources/MRAID.bundle/mraid.js index 16fadfe94..41c2ea444 100644 --- a/sdk/Resources/MRAID.bundle/mraid.js +++ b/sdk/Resources/MRAID.bundle/mraid.js @@ -52,7 +52,24 @@ var current_position={}; var size_event_width = 0; var size_event_height = 0; - + var supports = []; + supports['sms'] = false; + supports['tel'] = false; + supports['calendar'] = false; + supports['storePicture'] = false; + supports['inlineVideo'] = false; + + // constants for interaction with anjam.js + var MRAID_STATE = "state"; + var MRAID_PLACEMENT_TYPE = "placementType"; + var MRAID_VIEWABLE = "viewable"; + var MRAID_EXPAND_PROPERTIES = "expandProperties"; + var MRAID_RESIZE_PROPERTIES = "resizeProperties"; + var MRAID_ORIENTATION_PROPERTIES = "orientationProperties"; + var MRAID_SCREEN_SIZE = "screenSize"; + var MRAID_MAX_SIZE = "maxSize"; + var MRAID_DEFAULT_POSITION = "defaultPosition"; + var MRAID_CURRENT_POSITION = "currentPosition"; // ----- MRAID AD API FUNCTIONS ----- @@ -179,6 +196,9 @@ } properties.isModal = true; expand_properties = properties; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_EXPAND_PROPERTIES, expand_properties); + } }; //returns a json object... {width:300, height:250, useCustomClose:false, isModal:false}; @@ -233,6 +253,9 @@ props.allowOffscreen = true; } resize_properties = props; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_RESIZE_PROPERTIES, resize_properties); + } } } @@ -264,6 +287,9 @@ } orientation_properties=properties; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_ORIENTATION_PROPERTIES, orientation_properties); + } mraid.util.nativeCall("mraid://setOrientationProperties/?allow_orientation_change="+orientation_properties.allowOrientationChange +"&force_orientation="+orientation_properties.forceOrientation); @@ -299,21 +325,12 @@ mraid.util.errorEvent("Method 'mraid.supports()' called during loading state.", "mraid.supports()"); return; } - switch(feature){ - case 'sms': - return supports_sms; - case 'tel': - return supports_tel; - case 'calendar': - return supports_calendar; - case 'storePicture': - return supports_storePicture; - case 'inlineVideo': - return supports_inlineVideo; - } - mraid.util.errorEvent("Unknown feature to check for support: "+feature, "mraid.supports()"); + if (supports[feature] !== "boolean") { + mraid.util.errorEvent("Unknown feature to check for support: " + feature, "mraid.supports()"); return false; } + return supports[feature]; + } // Gets the screen size of the device mraid.getScreenSize=function(){ @@ -361,6 +378,9 @@ mraid.util.setPlacementType=function(type){ placement_type=type; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_PLACEMENT_TYPE, placement_type); + } }; mraid.util.fireEvent = function (event) { @@ -395,12 +415,18 @@ mraid.util.setIsViewable = function (is_it_viewable) { if (is_viewable === is_it_viewable) return; is_viewable = is_it_viewable; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_VIEWABLE, is_viewable); + } mraid.util.viewableChangeEvent(is_viewable); }; mraid.util.stateChangeEvent = function (new_state) { if (state === new_state && state != 'resized') return; state = new_state; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_STATE, state); + } if (new_state === 'hidden') { mraid.util.setIsViewable(false); } @@ -452,41 +478,27 @@ if(nativeCallQueue.length == 1) setTimeout(dequeue, 0); } - var supports_sms = false; - var supports_tel = false; - var supports_calendar = false; - var supports_storePicture = false; - var supports_inlineVideo = false; - - mraid.util.setSupportsSMS=function(val){ - supports_sms = val; + mraid.util.setSupports = function(feature, value) { + supports[feature] = value; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateSupports(feature, value); } - - - mraid.util.setSupportsTel=function(val){ - supports_tel=val; - } - - mraid.util.setSupportsCalendar=function(val){ - supports_calendar=val; - } - - mraid.util.setSupportsStorePicture=function(val){ - supports_storePicture=val; - } - - mraid.util.setSupportsInlineVideo=function(val){ - supports_inlineVideo=val; } mraid.util.setScreenSize=function(width, height){ screen_size={"width":width, "height": height}; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_SCREEN_SIZE, screen_size); + } } mraid.util.setMaxSize=function(width, height){ max_size={"width":width, "height": height}; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_MAX_SIZE, max_size); + } } mraid.util.setDefaultPosition=function(x, y, width, height){ @@ -495,6 +507,9 @@ "width":width, "height": height }; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_DEFAULT_POSITION, default_position); + } } mraid.util.setCurrentPosition=function(x, y, width, height){ @@ -503,6 +518,9 @@ "width":width, "height": height }; + if ((typeof window.sdkjs) !== "undefined") { + window.sdkjs.mraidUpdateProperty(MRAID_CURRENT_POSITION, current_position); + } } }()); diff --git a/sdk/Resources/anjam.js b/sdk/Resources/anjam.js new file mode 100644 index 000000000..97b029335 --- /dev/null +++ b/sdk/Resources/anjam.js @@ -0,0 +1,581 @@ +/* + * Copyright 2013 APPNEXUS INC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function () { + + if ((typeof window.anjam) !== "undefined") { + return; + } + + // constants + var DEBUG = false; + var VERSION_NO = "1.0"; + var ANJAM_PROTOCOL = "anjam:"; + var SDKJS_PROTOCOL = "sdkjs:"; + var WINDOW_NAME_PREFIX = "anjam_"; + var CALL_INIT = "init"; + var CALL_MAYDEEPLINK = "MayDeepLink"; + var CALL_DEEPLINK = "DeepLink"; + var CALL_EXTERNALBROWSER = "ExternalBrowser"; + var CALL_INTERNALBROWSER = "InternalBrowser"; + var CALL_RECORDEVENT = "RecordEvent"; + var CALL_DISPATCHAPPEVENT = "DispatchAppEvent"; + var CALL_GETVERSION = "GetVersion"; + var CALL_GETDEVICEID = "GetDeviceID"; + var CALL_READY = "ready"; + var CALL_RESULT = "result"; + var CALL_MRAID = "mraid"; + var MRAID_EVENT_PREFIX = "mraid_"; + + var MRAID_STATE = "state"; + var MRAID_PLACEMENT_TYPE = "placementType"; + var MRAID_VIEWABLE = "viewable"; + var MRAID_EXPAND_PROPERTIES = "expandProperties"; + var MRAID_RESIZE_PROPERTIES = "resizeProperties"; + var MRAID_ORIENTATION_PROPERTIES = "orientationProperties"; + var MRAID_SCREEN_SIZE = "screenSize"; + var MRAID_MAX_SIZE = "maxSize"; + var MRAID_DEFAULT_POSITION = "defaultPosition"; + var MRAID_CURRENT_POSITION = "currentPosition"; + + // public window variables + var anjam = window.anjam = {}; + var mraid = null; + // for ready event + anjam.ready = false; + + // internal ANJAM variables + var listeners = []; // event listeners + var callbacks = []; // function callbacks + var callbacksCounter = Math.ceil(Math.random() * 1e+10); + var isIFrame = window !== window.top; // determine the context + + // mraid shell variables + var mraidProperties = []; + // supports is an array so handle it separately + var mraidSupports = []; + + // ----- + // ----- HELPER FUNCTIONS ----- + // ----- + + // Pair Object + anjam.pair = function (first, second) { + this.first = first; + this.second = second; + } + + // Convenient logging with flag + anjam.anlog = function (message) { + if (DEBUG) console.log(message); + } + + // Cross-window communication helper + anjam.postMessageToTop = function (message) { + if (typeof message !== "string") { + return; + } + window.top.postMessage(message, "*"); + }; + + // Protocol definition + anjam.constructMessage = function (command, paramsList) { + var params = ""; + for (var i = 0; i < paramsList.length; i++) { + var paramToAdd = paramsList[i].first + "=" + paramsList[i].second; + if (i == 0) { + params = paramToAdd; + } else { + params = params + "&" + paramToAdd; + } + } + + return ANJAM_PROTOCOL + command + "?" + params; + } + + anjam.fireMessage = function (command, paramsList) { + anjam.postMessageToTop(anjam.constructMessage(command, paramsList)); + }; + + // ----- + // ----- INTERNAL SETUP ----- + // ----- + + // window event listener to receive messages from SDKJS + anjam.listener = function (event) { + // accept all event.origin values, filter based on protocol + + // use anchor element for convenient parsing + var a = document.createElement("a"); + a.href = event.data; + + if (a.protocol === SDKJS_PROTOCOL) { + anjam.anlog("ANJAM received: " + event.data); + + // use pathname because host doesn't work + var path = a.pathname; + var search = a.search.substr(1); // drop the '?' at the front + var query = search.split("&"); + var queryParameters = {}; + var length = query.length; + for (var i = 0; i < length; i++) { + var values = query[i].split("="); + queryParameters[values[0]] = decodeURIComponent(values[1]); + } + + if (path === CALL_READY) { + anjam.onReadyEvent(); + } else if (path === CALL_RESULT) { + anjam.onResult(queryParameters); + } else if (path === CALL_MRAID) { + anjam.onMraidCall(queryParameters); + } + + } + } + + anjam.fireInit = function () { + anjam.fireMessage(CALL_INIT, [new anjam.pair("name", window.name)]); + }; + + // create mraid shell if necessary + anjam.setupMraid = function () { + if (!isIFrame) { + return; + } + + anjam.anlog("Creating Mraid shell"); + mraid = window.mraid = {}; + + //set default values for properties + mraidProperties[MRAID_STATE] = "loading"; + mraidProperties[MRAID_PLACEMENT_TYPE] = "inline"; + mraidProperties[MRAID_VIEWABLE] = false; + mraidProperties[MRAID_EXPAND_PROPERTIES] = { + width: -1, + height: -1, + useCustomClose: false, + isModal: true + }; + mraidProperties[MRAID_RESIZE_PROPERTIES] = { + customClosePosition: 'top-right', + allowOffscreen: true + }; + mraidProperties[MRAID_ORIENTATION_PROPERTIES] = { + allowOrientationChange: true, + forceOrientation: "none" + }; + mraidProperties[MRAID_SCREEN_SIZE] = {}; + mraidProperties[MRAID_MAX_SIZE] = {}; + mraidProperties[MRAID_DEFAULT_POSITION] = {}; + mraidProperties[MRAID_CURRENT_POSITION] = {}; + + // mraid event listeners + + mraid.addEventListener = function (eventName, method) { + anjam.addEventListener(MRAID_EVENT_PREFIX + eventName, method); + } + + mraid.removeEventListener = function (eventName, method) { + anjam.removeEventListener(MRAID_EVENT_PREFIX + eventName, + method); + } + + // mraid methods with return values + + mraid.getVersion = function () { + return "2.0"; + } + + mraid.getVendor = function () { + return "appnexus"; + } + + mraid.getState = function () { + return mraidProperties[MRAID_STATE]; + } + + mraid.getPlacementType = function () { + return mraidProperties[MRAID_PLACEMENT_TYPE]; + } + + mraid.isViewable = function () { + return mraidProperties[MRAID_VIEWABLE]; + } + + mraid.getExpandProperties = function () { + return mraidProperties[MRAID_EXPAND_PROPERTIES]; + } + + mraid.getResizeProperties = function () { + return mraidProperties[MRAID_RESIZE_PROPERTIES]; + } + + mraid.getOrientationProperties = function () { + return mraidProperties[MRAID_ORIENTATION_PROPERTIES]; + } + + mraid.supports = function (feature) { + if (typeof mraidSupports[feature] !== "boolean") { + return false; + } + return mraidSupports[feature]; + } + + mraid.getScreenSize = function () { + return mraidProperties[MRAID_SCREEN_SIZE]; + } + + mraid.getMaxSize = function () { + return mraidProperties[MRAID_MAX_SIZE]; + } + + mraid.getDefaultPosition = function () { + return mraidProperties[MRAID_DEFAULT_POSITION]; + } + + mraid.getCurrentPosition = function () { + return mraidProperties[MRAID_CURRENT_POSITION]; + } + + // mraid methods that need to be forwarded to main + + mraid.forward = function (method, args) { + var paramsList = [new anjam.pair("method", method)]; + var length = args.length; + + for (var i = 0; i < length; i++) { + paramsList.push(new anjam.pair("p" + i, encodeURIComponent( + JSON.stringify(args[i])))); + } + + anjam.fireMessage(CALL_MRAID, paramsList); + } + + mraid.open = function () { + mraid.forward("open", arguments); + } + + mraid.close = function () { + mraid.forward("close", arguments); + } + + mraid.expand = function () { + mraid.forward("expand", arguments); + } + + mraid.setExpandProperties = function () { + mraid.forward("setExpandProperties", arguments); + } + + mraid.resize = function () { + mraid.forward("resize", arguments); + } + + mraid.setResizeProperties = function () { + mraid.forward("setResizeProperties", arguments); + } + + mraid.setOrientationProperties = function () { + mraid.forward("setOrientationProperties", arguments); + } + + mraid.createCalendarEvent = function (event) { + mraid.forward("createCalendarEvent", arguments); + } + + mraid.playVideo = function (uri) { + mraid.forward("playVideo", arguments); + } + + mraid.storePicture = function (uri) { + mraid.forward("storePicture", arguments); + } + + mraid.useCustomClose = function (value) { + mraid.forward("useCustomClose", arguments); + } + + mraid.enable = function () { + mraid.forward("enable", arguments); + } + + mraid.enable(); + } + + // Initial setup on first load on ANJAM.js + anjam.setup = function () { + anjam.setupMraid(); + + // if the window doesn't have a name, give a unique name + if (typeof window.name !== "string" || window.name === "") { + var time = new Date().getTime(); + window.name = WINDOW_NAME_PREFIX + time; + } + + // register a window listener + if (window.addEventListener) { + window.addEventListener("message", anjam.listener, false); + } else { + window.attachEvent("onmessage", anjam.listener); + } + + anjam.anlog("ANJAM instance created: name(" + window.name + + "), counter(" + callbacksCounter + "), IFrame(" + isIFrame + + ")"); + + // register this window in SDKJS + anjam.fireInit(); + } + + // call setup() + anjam.setup(); + + // ----- + // ----- INTERNAL API UTILITY FUNCTIONS ----- + // ----- + + anjam.fireEvent = function (eventName) { + var eventListeners = listeners[eventName]; + if (eventListeners) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + var length = eventListeners.length; + for (var i = 0; i < length; i++) { + if ((typeof eventListeners[i]) === "function") { + eventListeners[i].apply(null, args); + } + } + } + } + + anjam.onReadyEvent = function () { + // only fire the ready event once + if (!anjam.ready) { + anjam.ready = true; + anjam.fireEvent(CALL_READY); + } + } + + anjam.onResult = function (queryParameters) { + var cb = -1; + if (queryParameters.cb) { + cb = parseInt(queryParameters.cb); + } + + // remove the cb param + queryParameters.cb = null; + if ((cb > -1) && (typeof callbacks[cb] === "function")) { + // invoke the callback, then release it + callbacks[cb](queryParameters); + callbacks[cb] = null; + } + } + + anjam.onMraidCall = function (params) { + // forward all mraid events to anjam-mraid listeners + if (params.event) { + anjam.fireEvent(MRAID_EVENT_PREFIX + params.event, params.p0, + params.p1); + return; + } else if (params.method) { + if (params.method === "updateProperty") { + mraidProperties[params.propertyName] = JSON.parse( + decodeURIComponent(params.value)); + } else if (params.method === "updateSupports") { + mraidSupports[params.feature] = params.value; + } + } + + } + + anjam.addCallback = function (callback) { + callbacksCounter++; + callbacks[callbacksCounter] = callback; + } + + anjam.validateString = function (s) { + return (s && ((typeof s) === "string")); + } + + anjam.validateHttpString = function (url) { + return (((typeof url) === "string") + && (url.lastIndexOf("http", 0) === 0)); + } + + // ----- + // ----- PUBLIC API FUNCTIONS ----- + // ----- + + anjam.addEventListener = function (eventName, method) { + anjam.anlog("adding listener on " + eventName + " for method: " + + method) + + listeners[eventName] = listeners[eventName] || []; + + var length = listeners[eventName].length; + for (var i = 0; i < length; i++) { + if (listeners[eventName][i] == method) { + anjam.anlog("Already added"); + return; + } + } + + listeners[eventName].push(method); + } + + anjam.removeEventListener = function (eventName, method) { + anjam.anlog("remove listener on " + eventName + " for method: " + + method) + var eventListeners = listeners[eventName]; + if (eventListeners) { + var index = eventListeners.indexOf(method); + if (index > -1) { + eventListeners[index] = null; + } + } + } + + // required: url, callback + anjam.MayDeepLink = function (url, callback) { + if (typeof callback !== "function") { + anjam.anlog("MayDeepLink error: callback parameter should be a function"); + return; + } + anjam.addCallback(callback); + + if (!anjam.validateString(url)) { + anjam.anlog("MayDeepLink error: url should be a string"); + // call the callback function for failure + var failureResult = {}; + failureResult.caller = CALL_MAYDEEPLINK; + failureResult.cb = callbacksCounter; + failureResult.mayDeepLink = false; + anjam.onResult(failureResult); + return; + } + + anjam.fireMessage(CALL_MAYDEEPLINK, [new anjam.pair( + "cb", callbacksCounter), new anjam.pair("url", + encodeURIComponent(url))]); + } + + // required: url, optional: callback + anjam.DeepLink = function (url, callback) { + var index = -1; + if (typeof callback === "function") { + anjam.addCallback(callback); + index = callbacksCounter; + } + + if (!anjam.validateString(url)) { + anjam.anlog("DeepLink error: url should be a string"); + // call the callback function for failure + if (index > -1) { + var failureResult = {}; + failureResult.caller = CALL_DEEPLINK; + failureResult.cb = callbacksCounter; + anjam.onResult(failureResult); + } + return; + } + + anjam.fireMessage(CALL_DEEPLINK, [new anjam.pair( + "cb", index), new anjam.pair("url", + encodeURIComponent(url))]); + } + + // required: url + anjam.ExternalBrowser = function (url) { + if (!anjam.validateHttpString(url)) { + anjam.anlog("ExternalBrowser error: url should be a string"); + return; + } + + anjam.fireMessage(CALL_EXTERNALBROWSER, [new anjam.pair("url", + encodeURIComponent(url))]); + } + + // required: url + anjam.InternalBrowser = function (url) { + if (!anjam.validateHttpString(url)) { + anjam.anlog("InternalBrowser error: url should be a string"); + return; + } + + anjam.fireMessage(CALL_INTERNALBROWSER, [new anjam.pair("url", + encodeURIComponent(url))]); + } + + // required: url + anjam.RecordEvent = function (url) { + if (!anjam.validateHttpString(url)) { + anjam.anlog("RecordEvent error: url should be a string"); + return; + } + + anjam.fireMessage(CALL_RECORDEVENT, [new anjam.pair("url", + encodeURIComponent(url))]); + } + + // required: at least one of event or data must be a non-empty string + anjam.DispatchAppEvent = function (event, data) { + // if not valid strings, set the parameters to empty string + if (!anjam.validateString(event)) { + event = ""; + } + if (!anjam.validateString(data)) { + data = ""; + } + + // validate that at least one is valid + if (!event && !data) { + anjam.anlog("DispatchAppEvent error: at least one of event or data must be a non-empty string"); + return; + } + + anjam.fireMessage(CALL_DISPATCHAPPEVENT, [new anjam.pair( + "event", event), new anjam.pair("data", data)]); + } + + // required: callback + anjam.GetVersion = function (callback) { + if (typeof callback !== "function") { + anjam.anlog("GetVersion error: callback parameter should be a function"); + return; + } + anjam.addCallback(callback); + + // call the callback function with version number + var result = {}; + result.caller = CALL_GETVERSION; + result.cb = callbacksCounter; + result.version = VERSION_NO; + anjam.onResult(result); + } + + // required: callback + anjam.GetDeviceID = function (callback) { + if (typeof callback !== "function") { + anjam.anlog("GetDeviceID error: callback parameter should be a function"); + return; + } + anjam.addCallback(callback); + + anjam.fireMessage(CALL_GETDEVICEID, [new anjam.pair( + "cb", callbacksCounter)]); + } + +}()); \ No newline at end of file diff --git a/sdk/Resources/sdkjs.js b/sdk/Resources/sdkjs.js new file mode 100644 index 000000000..8a1e26f23 --- /dev/null +++ b/sdk/Resources/sdkjs.js @@ -0,0 +1,249 @@ +/* + * Copyright 2013 APPNEXUS INC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function () { + + if ((typeof window.sdkjs) !== "undefined") { + return; + } + + // constants + var DEBUG = false; + var NATIVE_CALL_PREFIX = "anjam://"; + var ANJAM_PROTOCOL = "anjam:"; + var SDKJS_PROTOCOL = "sdkjs:"; + var CALL_INIT = "init"; + var CALL_MAYDEEPLINK = "MayDeepLink"; + var CALL_DEEPLINK = "DeepLink"; + var CALL_EXTERNALBROWSER = "ExternalBrowser"; + var CALL_INTERNALBROWSER = "InternalBrowser"; + var CALL_RECORDEVENT = "RecordEvent"; + var CALL_DISPATCHAPPEVENT = "DispatchAppEvent"; + var CALL_GETDEVICEID = "GetDeviceID"; + var CALL_READY = "ready"; + var CALL_RESULT = "result"; + var CALL_MRAID = "mraid"; + + // public window variable to be invoked by mraid.js + var sdkjs = window.sdkjs = {}; + sdkjs.client = {}; + + // internal SDKJS variables + var anjamFrames = []; + var nativeCallQueue = []; + + sdkjs.anlog = function (message) { + if (DEBUG) { + console.log(message); + } + } + + // window event listener to receive messages from SDKJS + sdkjs.listener = function (event) { + // accept all event.origin values, filter based on protocol + + // use anchor element for convenient parsing + var a = document.createElement("a"); + a.href = event.data; + + if (a.protocol === ANJAM_PROTOCOL) { + // use pathname because host doesn't work + var path = a.pathname; + + // parameters + var search = a.search.substr(1); // drop the '?' at the front + var query = search.split("&"); + var queryParameters = {}; + for (var i = 0; i < query.length; i++) { + var values = query[i].split("="); + queryParameters[values[0]] = values[1]; + } + + // commands handler + sdkjs.anlog("SDKJS received: call(" + path + ") params:(" + + JSON.stringify(queryParameters) + ")"); + + if (path === CALL_INIT) { + sdkjs.callInit(queryParameters); + } else if (path === CALL_MAYDEEPLINK) { + sdkjs.callMayDeepLink(queryParameters); + } else if (path === CALL_DEEPLINK) { + sdkjs.callDeepLink(queryParameters); + } else if (path === CALL_EXTERNALBROWSER) { + sdkjs.callExternalBrowser(queryParameters); + } else if (path === CALL_INTERNALBROWSER) { + sdkjs.callInternalBrowser(queryParameters); + } else if (path === CALL_RECORDEVENT) { + sdkjs.callRecordEvent(queryParameters); + } else if (path === CALL_DISPATCHAPPEVENT) { + sdkjs.callDispatchAppEvent(queryParameters); + } else if (path === CALL_GETDEVICEID) { + sdkjs.callGetDeviceID(queryParameters); + } else if (path === CALL_MRAID) { + sdkjs.callMraid(queryParameters); + } + } + } + + sdkjs.setup = function () { + if (window.addEventListener) { + window.addEventListener("message", sdkjs.listener, false); + } else { + window.attachEvent("onmessage", sdkjs.listener); + } + } + + sdkjs.setup(); + + sdkjs.postMessageToFrames = function (message) { + for (var i = 0; i < anjamFrames.length; i++) { + var w = window.open("", anjamFrames[i], null, false); + w.postMessage(message, "*"); + } + } + + sdkjs.fireMessage = function (call, params) { + params = params || ""; + sdkjs.postMessageToFrames(SDKJS_PROTOCOL + call + "?" + params); + } + + sdkjs.callInit = function (queryParameters) { + var name = queryParameters.name; + anjamFrames.push(name); + sdkjs.fireMessage(CALL_READY); + } + + sdkjs.dequeue = function () { + window.location = nativeCallQueue.shift(); + if (nativeCallQueue.length > 0) { + setTimeout(sdkjs.dequeue, 0); + } + } + + sdkjs.makeNativeCall = function (uri) { + nativeCallQueue.push(NATIVE_CALL_PREFIX + uri); + if (nativeCallQueue.length == 1) { + setTimeout(sdkjs.dequeue, 0); + } + } + + sdkjs.callMayDeepLink = function (queryParameters) { + var cb = queryParameters.cb; + var url = queryParameters.url; + + sdkjs.makeNativeCall("MayDeepLink?cb=" + cb + "&url=" + url); + } + + sdkjs.callDeepLink = function (queryParameters) { + var cb = queryParameters.cb; + var url = queryParameters.url; + + sdkjs.makeNativeCall("DeepLink?cb=" + cb + "&url=" + url); + } + + sdkjs.callExternalBrowser = function (queryParameters) { + var url = queryParameters.url; + + sdkjs.makeNativeCall("ExternalBrowser?url=" + url); + } + + sdkjs.callInternalBrowser = function (queryParameters) { + var url = queryParameters.url; + + sdkjs.makeNativeCall("InternalBrowser?url=" + url); + } + + sdkjs.callRecordEvent = function (queryParameters) { + var url = queryParameters.url; + + sdkjs.makeNativeCall("RecordEvent?url=" + url); + } + + sdkjs.callDispatchAppEvent = function (queryParameters) { + var event = queryParameters.event; + var data = queryParameters.data; + + sdkjs.makeNativeCall("DispatchAppEvent?event=" + event + "&data=" + + data); + } + + sdkjs.callGetDeviceID = function (queryParameters) { + var cb = queryParameters.cb; + + sdkjs.makeNativeCall("GetDeviceID?cb=" + cb); + } + + sdkjs.callMraid = function (queryParameters) { + var key = "p0"; + var count = 0; + var args = []; + + while ((typeof queryParameters[key]) !== "undefined") { + args.push(JSON.parse(decodeURIComponent(queryParameters[key]))); + count++; + key = "p" + count; + } + + if ((typeof mraid) !== "undefined") { + mraid[queryParameters.method].apply(mraid, args); + } + } + + sdkjs.client.result = function (params) { + sdkjs.fireMessage(CALL_RESULT, params); + } + + sdkjs.mraidEventHandler = function (eventName) { + // mraid events have at most two parameters in the callback + // pass undefined if not present; anjam should handle + this.call = function (p0, p1) { + sdkjs.fireMessage(CALL_MRAID, "event=" + eventName + "&p0=" + + p0 + "&p1=" + p1); + }; + } + + sdkjs.mraidReadyEventHandler = new sdkjs.mraidEventHandler("ready"); + sdkjs.mraidErrorEventHandler = new sdkjs.mraidEventHandler("error"); + sdkjs.mraidStateChangeEventHandler = new sdkjs.mraidEventHandler( + "stateChange"); + sdkjs.mraidViewableChangeEventHandler = new sdkjs.mraidEventHandler( + "viewableChange"); + sdkjs.mraidSizeChangeEventHandler = new sdkjs.mraidEventHandler( + "sizeChange"); + + if ((typeof mraid) !== "undefined") { + // add mraid event listeners to pass to anjam + mraid.addEventListener("ready", sdkjs.mraidReadyEventHandler.call); + mraid.addEventListener("error", sdkjs.mraidErrorEventHandler.call); + mraid.addEventListener("stateChange", sdkjs.mraidStateChangeEventHandler + .call); + mraid.addEventListener("viewableChange", + sdkjs.mraidViewableChangeEventHandler.call); + mraid.addEventListener("sizeChange", sdkjs.mraidSizeChangeEventHandler + .call); + } + + sdkjs.mraidUpdateProperty = function (propertyName, value) { + sdkjs.fireMessage(CALL_MRAID, "method=updateProperty&propertyName=" + + propertyName + "&value=" + encodeURIComponent(JSON.stringify( + value))); + } + + sdkjs.mraidUpdateSupports = function (feature, value) { + sdkjs.fireMessage(CALL_MRAID, "method=updateSupports&feature=" + + feature + "&value=" + value); + } + +}()); \ No newline at end of file diff --git a/sdk/internal/ANANJAMImplementation.h b/sdk/internal/ANANJAMImplementation.h new file mode 100644 index 000000000..7fc40ba5c --- /dev/null +++ b/sdk/internal/ANANJAMImplementation.h @@ -0,0 +1,25 @@ +/* Copyright 2013 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANAdViewDelegate.h" +#import "ANBrowserViewController.h" + +#import +#import + +@interface ANANJAMImplementation : NSObject ++ (void)handleUrl:(NSURL *)url forWebView:(UIWebView *)webView + forDelegate:(id)delegate; +@end diff --git a/sdk/internal/ANANJAMImplementation.m b/sdk/internal/ANANJAMImplementation.m new file mode 100644 index 000000000..83247b0eb --- /dev/null +++ b/sdk/internal/ANANJAMImplementation.m @@ -0,0 +1,205 @@ +/* Copyright 2013 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANANJAMImplementation.h" + +#import "ANGlobal.h" +#import "ANLogging.h" +#import "NSString+ANCategory.h" + +NSString *const kANCallMayDeepLink = @"MayDeepLink"; +NSString *const kANCallDeepLink = @"DeepLink"; +NSString *const kANCallExternalBrowser = @"ExternalBrowser"; +NSString *const kANCallInternalBrowser = @"InternalBrowser"; +NSString *const kANCallRecordEvent = @"RecordEvent"; +NSString *const kANCallDispatchAppEvent = @"DispatchAppEvent"; +NSString *const kANCallGetDeviceID = @"GetDeviceID"; + +NSString *const kANKeyCaller = @"caller"; + +@interface ANRecordEventDelegate : NSObject +@end + +@interface UIWebView (RecordEvent) +@property (nonatomic, readwrite, strong) ANRecordEventDelegate *recordEventDelegate; +@end + +@implementation ANANJAMImplementation + ++ (void)handleUrl:(NSURL *)url forWebView:(UIWebView *)webView + forDelegate:(id)delegate { + NSString *call = [url host]; + NSDictionary *queryComponents = [[url query] queryComponents]; + if ([call isEqualToString:kANCallMayDeepLink]) { + [ANANJAMImplementation callMayDeepLink:webView query:queryComponents]; + } else if ([call isEqualToString:kANCallDeepLink]) { + [ANANJAMImplementation callDeepLink:webView query:queryComponents]; + } else if ([call isEqualToString:kANCallExternalBrowser]) { + [ANANJAMImplementation callExternalBrowser:webView query:queryComponents]; + } else if ([call isEqualToString:kANCallInternalBrowser]) { + [ANANJAMImplementation callInternalBrowser:webView query:queryComponents delegate:delegate]; + } else if ([call isEqualToString:kANCallRecordEvent]) { + [ANANJAMImplementation callRecordEvent:webView query:queryComponents]; + } else if ([call isEqualToString:kANCallDispatchAppEvent]) { + [ANANJAMImplementation callDispatchAppEvent:webView query:queryComponents delegate:delegate]; + } else if ([call isEqualToString:kANCallGetDeviceID]) { + [ANANJAMImplementation callGetDeviceID:webView query:queryComponents]; + } else { + ANLogWarn(@"ANJAM called with unsupported function: %@", call); + } +} + +// Deep Link + ++ (void)callMayDeepLink:(UIWebView *)webView query:(NSDictionary *)query { + NSString *cb = [query valueForKey:@"cb"]; + NSString *urlParam = [query valueForKey:@"url"]; + BOOL mayDeepLink; + + if ([urlParam length] < 1) { + mayDeepLink = NO; + } else { + NSURL *url = [NSURL URLWithString:urlParam]; + mayDeepLink = [[UIApplication sharedApplication] canOpenURL:url]; + } + + NSDictionary *paramsList = @{ + kANKeyCaller: kANCallMayDeepLink, + @"mayDeepLink": mayDeepLink ? @"true" : @"false" + }; + [ANANJAMImplementation loadResult:webView cb:cb paramsList:paramsList]; +} + ++ (void)callDeepLink:(UIWebView *)webView query:(NSDictionary *)query { + NSString *cb = [query valueForKey:@"cb"]; + NSString *urlParam = [query valueForKey:@"url"]; + + NSURL *url = [NSURL URLWithString:urlParam]; + if ([[UIApplication sharedApplication] canOpenURL:url] + && [[UIApplication sharedApplication] openURL:url]) { + // success, do nothing + return; + } else { + NSDictionary *paramsList = @{ + kANKeyCaller: kANCallDeepLink, + }; + [ANANJAMImplementation loadResult:webView cb:cb paramsList:paramsList]; + } +} + +// Launch Browser + ++ (void)callExternalBrowser:(UIWebView *)webView query:(NSDictionary *)query { + NSString *urlParam = [query valueForKey:@"url"]; + + NSURL *url = [NSURL URLWithString:urlParam]; + if (hasHttpPrefix([url scheme]) + && [[UIApplication sharedApplication] canOpenURL:url]) { + [[UIApplication sharedApplication] openURL:url]; + } +} + ++ (void)callInternalBrowser:(UIWebView *)webView query:(NSDictionary *)query + delegate:(id)delegate { + NSString *urlParam = [query valueForKey:@"url"]; + + NSURL *url = [NSURL URLWithString:urlParam]; + if (hasHttpPrefix([url scheme])) { + [ANBrowserViewController launchURL:url withDelegate:delegate]; + } +} + +// Record Event + ++ (void)callRecordEvent:(UIWebView *)webView query:(NSDictionary *)query { + NSString *urlParam = [query valueForKey:@"url"]; + + NSURL *url = [NSURL URLWithString:urlParam]; + UIWebView *recordEventWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; + ANRecordEventDelegate *recordEventDelegate = [ANRecordEventDelegate new]; + recordEventWebView.recordEventDelegate = recordEventDelegate; + recordEventWebView.delegate = recordEventDelegate; + [recordEventWebView setHidden:YES]; + [recordEventWebView loadRequest:[NSURLRequest requestWithURL:url]]; + [webView addSubview:recordEventWebView]; +} + +// Dispatch App Event + ++ (void)callDispatchAppEvent:(UIWebView *)webView query:(NSDictionary *)query + delegate:(id)delegate { + NSString *event = [query valueForKey:@"event"]; + NSString *data = [query valueForKey:@"data"]; + + [delegate adDidReceiveAppEvent:event withData:data]; +} + +// Get Device ID + ++ (void)callGetDeviceID:(UIWebView *)webView query:(NSDictionary *)query { + NSString *cb = [query valueForKey:@"cb"]; + + // send idName:idfa, id: idfa value + NSDictionary *paramsList = @{ + kANKeyCaller: kANCallGetDeviceID, + @"idname": @"idfa", + @"id": ANUDID() + }; + [ANANJAMImplementation loadResult:webView cb:cb paramsList:paramsList]; +} + + +// Send the result back to JS + ++ (void)loadResult:(UIWebView *)webView cb:(NSString *)cb paramsList:(NSDictionary *)paramsList { + __block NSString *params = [NSString stringWithFormat:@"cb=%@", cb ? cb : @"-1"]; + + [paramsList enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + key = convertToNSString(key); + NSString *valueString = convertToNSString(value); + if (([key length] > 0) && ([valueString length] > 0)) { + params = [params stringByAppendingFormat:@"&%@=%@", key, + [valueString encodeAsURIComponent]]; + } + }]; + + NSString *url = [NSString stringWithFormat:@"javascript:window.sdkjs.client.result(\"%@\")", params]; + [webView stringByEvaluatingJavaScriptFromString:url]; +} + +@end + +@implementation ANRecordEventDelegate + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + ANLogDebug(@"RecordEvent completed succesfully"); +} + +@end + +@implementation UIWebView (RecordEvent) + +ANRecordEventDelegate *_recordEventDelegate; + + +- (void)setRecordEventDelegate:(ANRecordEventDelegate *)recordEventDelegate { + _recordEventDelegate = recordEventDelegate; +} + +- (ANRecordEventDelegate *)recordEventDelegate { + return _recordEventDelegate; +} + +@end diff --git a/sdk/internal/ANAdFetcher.h b/sdk/internal/ANAdFetcher.h index bc73546b0..1742349e0 100644 --- a/sdk/internal/ANAdFetcher.h +++ b/sdk/internal/ANAdFetcher.h @@ -17,6 +17,7 @@ #import "ANAdResponse.h" #import "ANAdViewDelegate.h" #import "ANAdWebViewController.h" +#import "ANBrowserViewController.h" #import "ANCustomAdapter.h" @class ANMRAIDAdWebViewController; @@ -47,7 +48,7 @@ extern NSString *const kANAdFetcherMediatedClassKey; - (void)processFinalResponse:(ANAdResponse *)response; @end -@protocol ANAdFetcherDelegate +@protocol ANAdFetcherDelegate @optional - (void)adFetcher:(ANAdFetcher *)fetcher didFinishRequestWithResponse:(ANAdResponse *)response; diff --git a/sdk/internal/ANAdFetcher.m b/sdk/internal/ANAdFetcher.m index 83f2477e8..045b2ffc5 100644 --- a/sdk/internal/ANAdFetcher.m +++ b/sdk/internal/ANAdFetcher.m @@ -268,18 +268,41 @@ - (void)handleStandardAd:(ANAdResponse *)response { self.webViewController.adFetcher = self; self.webViewController.webView = webView; webView.delegate = self.webViewController; - - NSURL *mraidBundlePath = [NSURL fileURLWithPath:ANMRAIDBundlePath()]; - NSURL *baseURL = self.webViewController.isMRAID ? mraidBundlePath : self.URL; + NSString *contentToLoad = response.content; - if (!self.webViewController.isMRAID) { - NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle alloc] initWithPath:ANMRAIDBundlePath()] pathForResource:@"mraid" - ofType:@"js"]]; - NSString *mraidScript = [NSString stringWithFormat:@"", [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]]; - contentToLoad = [mraidScript stringByAppendingString:contentToLoad]; + contentToLoad = [self prependMRAIDJS:contentToLoad]; + contentToLoad = [self prependSDKJS:contentToLoad]; + + [webView loadHTMLString:contentToLoad baseURL:[NSURL URLWithString:AN_BASE_URL]]; +} + +- (NSString *)prependMRAIDJS:(NSString *)content { + NSString *mraidPath = ANMRAIDBundlePath(); + if ([mraidPath length] < 1) { + return content; } - [webView loadHTMLString:contentToLoad baseURL:baseURL]; + NSBundle *mraidBundle = [[NSBundle alloc] initWithPath:ANMRAIDBundlePath()]; + NSData *data = [NSData dataWithContentsOfFile:[mraidBundle pathForResource:@"mraid" ofType:@"js"]]; + NSString *mraidScript = [NSString stringWithFormat:@"", + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]]; + return [mraidScript stringByAppendingString:content]; +} + +- (NSString *)prependSDKJS:(NSString *)content { + NSBundle *resBundle = ANResourcesBundle(); + if (!resBundle) { + ANLogError(@"Resource not found. Make sure the AppNexusSDKResources bundle is included in project"); + return content; + } + NSData *sdkjsData = [NSData dataWithContentsOfFile:[resBundle pathForResource:@"sdkjs" ofType:@"js"]]; + NSData *anjamData = [NSData dataWithContentsOfFile:[resBundle pathForResource:@"anjam" ofType:@"js"]]; + NSString *sdkjs = [[NSString alloc] initWithData:sdkjsData encoding:NSUTF8StringEncoding]; + NSString *anjam = [[NSString alloc] initWithData:anjamData encoding:NSUTF8StringEncoding]; + + NSString *sdkjsScript = [NSString stringWithFormat:@"", + sdkjs, anjam]; + return [sdkjsScript stringByAppendingString:content]; + } - (void)handleMediatedAds:(NSMutableArray *)mediatedAds @@ -502,7 +525,7 @@ - (NSString *)createResultCBRequest:(NSString *)baseResultCBString reason:(int)r NSString *resultCBRequestString = [baseResultCBString stringByAppendingUrlParameter:@"reason" value:[NSString stringWithFormat:@"%d",reasonCode]]; - resultCBRequestString = [resultCBRequestString stringByAppendingString:ANUdidParameter()]; + resultCBRequestString = [resultCBRequestString stringByAppendingUrlParameter:@"idfa" value:ANUDID()]; return resultCBRequestString; } diff --git a/sdk/internal/ANAdRequestUrl.m b/sdk/internal/ANAdRequestUrl.m index 5e47317b9..d7ef92599 100644 --- a/sdk/internal/ANAdRequestUrl.m +++ b/sdk/internal/ANAdRequestUrl.m @@ -18,6 +18,7 @@ #import "ANGlobal.h" #import "ANLogging.h" #import "ANReachability.h" +#import "NSString+ANCategory.h" #import #import @@ -54,7 +55,7 @@ + (NSURL *)buildRequestUrlWithAdFetcherDelegate:(id)adFetch - (NSURL *)buildRequestUrlWithBaseUrlString:(NSString *)baseUrlString { baseUrlString = [baseUrlString stringByAppendingString:[self placementIdParameter]]; - baseUrlString = [baseUrlString stringByAppendingString:ANUdidParameter()]; + baseUrlString = [baseUrlString stringByAppendingUrlParameter:@"idfa" value:ANUDID()]; baseUrlString = [baseUrlString stringByAppendingString:[self dontTrackEnabledParameter]]; baseUrlString = [baseUrlString stringByAppendingString:[self deviceMakeParameter]]; baseUrlString = [baseUrlString stringByAppendingString:[self deviceModelParameter]]; diff --git a/sdk/internal/ANAdView.m b/sdk/internal/ANAdView.m index d6afb6471..7d5e9fa81 100644 --- a/sdk/internal/ANAdView.m +++ b/sdk/internal/ANAdView.m @@ -22,6 +22,7 @@ #import "ANInterstitialAd.h" #import "ANLogging.h" #import "ANMRAIDViewController.h" +#import "UIView+ANCategory.h" #import "UIWebView+ANCategory.h" #define DEFAULT_PSAS YES @@ -36,6 +37,7 @@ @interface ANAdView () delegate; +@property (nonatomic, readwrite, weak) id appEventDelegate; @property (nonatomic, readwrite, assign) CGRect defaultFrame; @property (nonatomic, readwrite, assign) CGRect defaultParentFrame; @property (nonatomic, strong) ANMRAIDViewController *mraidController; @@ -506,7 +508,9 @@ - (void)setContentView:(UIView *)contentView { [webView setDelegate:nil]; } + [_contentView removeSubviews]; [_contentView removeFromSuperview]; + [self removeSubviews]; if (contentView != nil) { if ([contentView isKindOfClass:[UIWebView class]]) { @@ -575,10 +579,7 @@ - (NSMutableDictionary *)customKeywords { - (void)adFetcher:(ANAdFetcher *)fetcher adShouldOpenInBrowserWithURL:(NSURL *)URL { [self adWasClicked]; - NSString *scheme = [URL scheme]; - BOOL schemeIsHttp = ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]); - - if (!self.opensInNativeBrowser && schemeIsHttp) { + if (!self.opensInNativeBrowser && hasHttpPrefix([URL scheme])) { if (!self.browserViewController) { self.browserViewController = [[ANBrowserViewController alloc] initWithURL:URL]; self.browserViewController.delegate = self; @@ -687,6 +688,12 @@ - (void)adWillLeaveApplication { } } +- (void)adDidReceiveAppEvent:(NSString *)name withData:(NSString *)data { + if ([self.appEventDelegate respondsToSelector:@selector(ad:didReceiveAppEvent:withData:)]) { + [self.appEventDelegate ad:self didReceiveAppEvent:name withData:data]; + } +} + - (void)adFailedToDisplay { if ([self isMemberOfClass:[ANInterstitialAd class]] && [self.delegate conformsToProtocol:@protocol(ANInterstitialAdDelegate)]) { diff --git a/sdk/internal/ANAdViewDelegate.h b/sdk/internal/ANAdViewDelegate.h index 3f98f702e..bef333a99 100644 --- a/sdk/internal/ANAdViewDelegate.h +++ b/sdk/internal/ANAdViewDelegate.h @@ -23,6 +23,7 @@ - (void)adWillClose; - (void)adDidClose; - (void)adWillLeaveApplication; +- (void)adDidReceiveAppEvent:(NSString *)name withData:(NSString *)data; // for interstitials only - (void)adFailedToDisplay; diff --git a/sdk/internal/ANAdWebViewController.m b/sdk/internal/ANAdWebViewController.m index 9d5a3150c..dcfd7f349 100644 --- a/sdk/internal/ANAdWebViewController.m +++ b/sdk/internal/ANAdWebViewController.m @@ -16,6 +16,7 @@ #import "ANAdWebViewController.h" #import "ANAdFetcher.h" +#import "ANANJAMImplementation.h" #import "ANBrowserViewController.h" #import "ANGlobal.h" #import "ANLogging.h" @@ -210,8 +211,15 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) NSURL *mainDocumentURL = [request mainDocumentURL]; NSString *scheme = [URL scheme]; + if ([scheme isEqualToString:@"anwebconsole"]) { + [self printConsoleLog:URL]; + return NO; + } + + ANLogDebug(@"Loading URL: %@", [[URL absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]); + if (self.completedFirstLoad) { - if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { + if (hasHttpPrefix(scheme)) { if (self.isMRAID) { /* The mainDocumentURL will be equal to the URL whenever a URL has requested to load in a new window/tab, @@ -244,8 +252,8 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) } else if ([scheme isEqualToString:@"mraid"]) { // Do MRAID actions [self dispatchNativeMRAIDURL:URL forWebView:webView]; - } else if ([scheme isEqualToString:@"anwebconsole"]) { - [self printConsoleLog:URL]; + } else if ([scheme isEqualToString:@"anjam"]) { + [ANANJAMImplementation handleUrl:URL forWebView:webView forDelegate:self.adFetcher.delegate]; } else if ([[UIApplication sharedApplication] canOpenURL:URL]) { [[UIApplication sharedApplication] openURL:URL]; } else { @@ -316,15 +324,14 @@ - (void)setValuesForMRAIDSupportsFunction:(UIWebView*)webView{ cal = YES; } - [webView setSupportsSMS:sms]; - [webView setSupportsTel:tel]; - [webView setSupportsCalendar:cal]; - [webView setSupportsInlineVideo:inline_video]; - [webView setSupportsStorePicture:store_picture]; + [webView setSupports:@"sms" isSupported:sms]; + [webView setSupports:@"tel" isSupported:tel]; + [webView setSupports:@"calendar" isSupported:cal]; + [webView setSupports:@"inlineVideo" isSupported:inline_video]; + [webView setSupports:@"storePicture" isSupported:store_picture]; } - (void)dispatchNativeMRAIDURL:(NSURL *)mraidURL forWebView:(UIWebView *)webView { - ANLogDebug(@"MRAID URL: %@", [mraidURL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]); NSString *mraidCommand = [mraidURL host]; NSString *query = [mraidURL query]; NSDictionary *queryComponents = [query queryComponents]; @@ -745,20 +752,8 @@ - (void)storePicture:(NSString*)uri } - (void)printConsoleLog:(NSURL *)URL { - NSMutableString *urlString = [NSMutableString stringWithString:[URL absoluteString]]; - [urlString replaceOccurrencesOfString:@"%20" - withString:@" " - options:NSLiteralSearch - range:NSMakeRange(0, [urlString length])]; - [urlString replaceOccurrencesOfString:@"%5B" - withString:@"[" - options:NSLiteralSearch - range:NSMakeRange(0, [urlString length])]; - [urlString replaceOccurrencesOfString:@"%5D" - withString:@"]" - options:NSLiteralSearch - range:NSMakeRange(0, [urlString length])]; - ANLogDebug(urlString); + NSString *decodedString = [[URL absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + ANLogDebug(decodedString); } // expand close button for non-custom close is provided by SDK diff --git a/sdk/internal/ANBrowserViewController.h b/sdk/internal/ANBrowserViewController.h index 0c1f84953..1dcc5218c 100644 --- a/sdk/internal/ANBrowserViewController.h +++ b/sdk/internal/ANBrowserViewController.h @@ -33,6 +33,8 @@ - (IBAction)backAction:(id)sender; - (IBAction)openInAction:(id)sender; ++ (void)launchURL:(NSURL *)url withDelegate:(id)delegate; + @end @protocol ANBrowserViewControllerDelegate diff --git a/sdk/internal/ANBrowserViewController.m b/sdk/internal/ANBrowserViewController.m index 3e8208e1c..e07c4bf0a 100644 --- a/sdk/internal/ANBrowserViewController.m +++ b/sdk/internal/ANBrowserViewController.m @@ -72,6 +72,15 @@ - (id)initWithURL:(NSURL *)url return self; } ++ (void)launchURL:(NSURL *)url withDelegate:(id)delegate { + ANBrowserViewController *controller = [[ANBrowserViewController alloc] initWithURL:url]; + controller.delegate = delegate; + if ([controller.delegate respondsToSelector:@selector(browserViewControllerShouldPresent:)]) { + [controller.delegate browserViewControllerShouldPresent:controller]; + controller.isPresented = YES; + } +} + - (IBAction)closeAction:(id)sender { [self.openInSheet dismissWithClickedButtonIndex:1 animated:NO]; @@ -92,7 +101,12 @@ - (IBAction)backAction:(id)sender - (IBAction)openInAction:(id)sender { - self.openInSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Open In Browser", @"Title: Open in browser option") delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", @"Title: Cancel button") destructiveButtonTitle:nil otherButtonTitles:@"Open In External Browser", nil]; + self.openInSheet = [[UIActionSheet alloc] + initWithTitle:NSLocalizedString(@"Open In Browser", @"Title: Open in browser option") + delegate:self + cancelButtonTitle:NSLocalizedString(@"Cancel", @"Title: Cancel button") + destructiveButtonTitle:nil + otherButtonTitles:@"Open In External Browser", nil]; [self.openInSheet showFromBarButtonItem:sender animated:YES]; } @@ -132,10 +146,8 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) { NSURL *URL = [request URL]; if (!self.isPresented) ANLogDebug(@"%@ | Loading URL: %@", NSStringFromClass([self class]), URL); - NSString *scheme = [URL scheme]; - BOOL schemeIsHttp = ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]); - if (schemeIsHttp) { + if (hasHttpPrefix([URL scheme])) { return YES; } else if ([[UIApplication sharedApplication] canOpenURL:URL]) { if ([self.delegate respondsToSelector:@selector(browserViewControllerShouldDismiss:)]) { @@ -170,8 +182,8 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView if (!self.isPresented) { if ([self.delegate respondsToSelector:@selector(browserViewControllerShouldPresent:)]) { [self.delegate browserViewControllerShouldPresent:self]; + self.isPresented = YES; } - self.isPresented = YES; } } diff --git a/sdk/internal/ANGlobal.h b/sdk/internal/ANGlobal.h index dcddcddca..e2cef0462 100644 --- a/sdk/internal/ANGlobal.h +++ b/sdk/internal/ANGlobal.h @@ -16,6 +16,7 @@ #import #import +#define AN_BASE_URL @"http://mediation.adnxs.com/" #define AN_MOBILE_HOSTNAME @"mediation.adnxs.com/mob" #define AN_MOBILE_HOSTNAME_INSTALL @"mediation.adnxs.com/install" #define AN_ERROR_DOMAIN @"com.appnexus.sdk" @@ -61,9 +62,10 @@ NSString *ANUserAgent(void); NSString *ANDeviceModel(void); BOOL ANAdvertisingTrackingEnabled(void); BOOL isFirstLaunch(void); -NSString *ANUdidParameter(void); +NSString *ANUDID(void); NSString *ANErrorString(NSString *key); NSBundle *ANResourcesBundle(); NSString *convertToNSString(id value); CGRect adjustAbsoluteRectInWindowCoordinatesForOrientationGivenRect(CGRect rect); -NSString *ANMRAIDBundlePath(); \ No newline at end of file +NSString *ANMRAIDBundlePath(); +BOOL hasHttpPrefix(NSString *url); diff --git a/sdk/internal/ANGlobal.m b/sdk/internal/ANGlobal.m index c5b2da204..d662c22d5 100644 --- a/sdk/internal/ANGlobal.m +++ b/sdk/internal/ANGlobal.m @@ -73,9 +73,7 @@ BOOL isFirstLaunch() return isFirstLaunch; } - - -NSString *ANUdidParameter() { +NSString *ANUDID() { static NSString *udidComponent = @""; if ([udidComponent isEqualToString:@""]) { @@ -85,8 +83,8 @@ BOOL isFirstLaunch() NSString *advertisingIdentifier = [[ASIdentifierManager sharedManager] .advertisingIdentifier UUIDString]; - if (advertisingIdentifier != nil) { - udidComponent = [NSString stringWithFormat:@"&idfa=%@", advertisingIdentifier]; + if (advertisingIdentifier) { + udidComponent = advertisingIdentifier; } else { ANLogWarn(@"No advertisingIdentifier retrieved. Cannot generate udidComponent."); @@ -153,3 +151,7 @@ CGRect adjustAbsoluteRectInWindowCoordinatesForOrientationGivenRect(CGRect rect) } return mraidBundlePath; } + +BOOL hasHttpPrefix(NSString *url) { + return ([url hasPrefix:@"http"] || [url hasPrefix:@"https"]); +} diff --git a/sdk/internal/ANInstallTrackerPixel.m b/sdk/internal/ANInstallTrackerPixel.m index 25053c43e..913f75aab 100644 --- a/sdk/internal/ANInstallTrackerPixel.m +++ b/sdk/internal/ANInstallTrackerPixel.m @@ -17,6 +17,7 @@ #import "ANGlobal.h" #import "ANLogging.h" +#import "NSString+ANCategory.h" #define AN_INSTALL_TRACKER_PIXEL_MAX_ATTEMPTS 5 #define AN_INSTALL_TRACKER_PIXEL_ATTEMPT_DURATION 30.0 @@ -92,7 +93,7 @@ - (NSURL *)pixelURL urlString = [urlString stringByAppendingString:[self trackingIDParameter]]; urlString = [urlString stringByAppendingString:[self dontTrackEnabledParameter]]; urlString = [urlString stringByAppendingString:[self applicationIdParameter]]; - urlString = [urlString stringByAppendingString:ANUdidParameter()]; + urlString = [urlString stringByAppendingUrlParameter:@"idfa" value:ANUDID()]; return [NSURL URLWithString:urlString]; } diff --git a/sdk/internal/ANInterstitialAdViewController.m b/sdk/internal/ANInterstitialAdViewController.m index 49cc57c94..f5ca9a4f7 100644 --- a/sdk/internal/ANInterstitialAdViewController.m +++ b/sdk/internal/ANInterstitialAdViewController.m @@ -17,6 +17,7 @@ #import "ANGlobal.h" #import "ANLogging.h" +#import "UIView+ANCategory.h" #import "UIWebView+ANCategory.h" @interface ANInterstitialAdViewController () @@ -136,8 +137,10 @@ - (void)setContentView:(UIView *)contentView [self.containerView addSubview:contentView]; } - + + [__contentView removeSubviews]; [__contentView removeFromSuperview]; + [self.containerView removeSubviews]; if ([__contentView isKindOfClass:[UIWebView class]]) { diff --git a/sdk/internal/ANMediationAdViewController.m b/sdk/internal/ANMediationAdViewController.m index 1d724ce56..5a88f31a6 100644 --- a/sdk/internal/ANMediationAdViewController.m +++ b/sdk/internal/ANMediationAdViewController.m @@ -67,7 +67,7 @@ - (BOOL)requestAd:(CGSize)size targetingParameters.age = adView.age; targetingParameters.gender = adView.gender; targetingParameters.location = adView.location; - targetingParameters.idforadvertising = ANUdidParameter(); + targetingParameters.idforadvertising = ANUDID(); // if the class implements both banner and interstitial protocols, default to banner first if ([[self.currentAdapter class] conformsToProtocol:@protocol(ANCustomAdapterBanner)] diff --git a/sdk/internal/ANWebView.h b/sdk/internal/ANWebView.h index 85500cbc0..e04c5ea4f 100644 --- a/sdk/internal/ANWebView.h +++ b/sdk/internal/ANWebView.h @@ -35,11 +35,7 @@ - (void)setDefaultPosition:(CGRect)frame; - (void)setScreenSize:(CGSize)size; - (void)setMaxSize:(CGSize)size; -- (void)setSupportsTel:(BOOL)isSupported; -- (void)setSupportsSMS:(BOOL)isSupported; -- (void)setSupportsCalendar:(BOOL)isSupported; -- (void)setSupportsStorePicture:(BOOL)isSupported; -- (void)setSupportsInlineVideo:(BOOL)isSupported; +- (void)setSupports:(NSString *)feature isSupported:(BOOL)isSupported; - (void)setHidden:(BOOL)hidden animated:(BOOL)animated; diff --git a/sdk/internal/ANWebView.m b/sdk/internal/ANWebView.m index 73fa63591..e56f2be91 100644 --- a/sdk/internal/ANWebView.m +++ b/sdk/internal/ANWebView.m @@ -132,29 +132,9 @@ - (void)setMaxSize:(CGSize)size { [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setMaxSize(%i, %i);",width, height]]; } -- (void)setSupportsTel:(BOOL)isSupported { - [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupportsTel(%@);", - isSupported ? @"true" : @"false"]]; -} - -- (void)setSupportsSMS:(BOOL)isSupported { - [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupportsSMS(%@);", - isSupported ? @"true" : @"false"]]; -} - -- (void)setSupportsCalendar:(BOOL)isSupported { - [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupportsCalendar(%@);", - isSupported ? @"true" : @"false"]]; -} - -- (void)setSupportsStorePicture:(BOOL)isSupported { - [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupportsStorePicture(%@);", - isSupported ? @"true" : @"false"]]; -} - -- (void)setSupportsInlineVideo:(BOOL)isSupported { - [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupportsInlineVideo(%@);", - isSupported ? @"true" : @"false"]]; +- (void)setSupports:(NSString *)feature isSupported:(BOOL)isSupported { + [self stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.mraid.util.setSupports(\'%@\', %@);", + feature, (isSupported ? @"true" : @"false")]]; } - (ANMRAIDState)getMRAIDState { From 61dd895bd3ceb4b6caff55191466ae0fef014839 Mon Sep 17 00:00:00 2001 From: Mark Ha Date: Tue, 29 Apr 2014 15:48:56 -0400 Subject: [PATCH 6/8] MS-655 Various fixes Fix Interstitials being removed MRAID supports and setOrientation fix --- sdk/Resources/MRAID.bundle/mraid.js | 4 +- sdk/internal/ANAdView.m | 42 +++++++--------- sdk/internal/ANInterstitialAdViewController.m | 49 +++++++++---------- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/sdk/Resources/MRAID.bundle/mraid.js b/sdk/Resources/MRAID.bundle/mraid.js index 41c2ea444..2ee6647df 100644 --- a/sdk/Resources/MRAID.bundle/mraid.js +++ b/sdk/Resources/MRAID.bundle/mraid.js @@ -325,7 +325,7 @@ mraid.util.errorEvent("Method 'mraid.supports()' called during loading state.", "mraid.supports()"); return; } - if (supports[feature] !== "boolean") { + if ((typeof supports[feature]) !== "boolean") { mraid.util.errorEvent("Unknown feature to check for support: " + feature, "mraid.supports()"); return false; } @@ -403,7 +403,7 @@ }; mraid.util.errorEvent = function (message, what_doing) { - mraid.util.fireEvent('error', what_doing); + mraid.util.fireEvent('error', message, what_doing); }; mraid.util.viewableChangeEvent = function (is_viewable_now) { diff --git a/sdk/internal/ANAdView.m b/sdk/internal/ANAdView.m index 7d5e9fa81..9cf61abd5 100644 --- a/sdk/internal/ANAdView.m +++ b/sdk/internal/ANAdView.m @@ -172,29 +172,26 @@ - (void)allowOrientationChange:(BOOL)allowOrientationChange - (void)updateOrientationPropertiesOnMRAIDViewController { if (self.mraidController) { self.mraidController.allowOrientationChange = self.allowOrientationChange; - + self.mraidController.orientation = [[UIApplication sharedApplication] statusBarOrientation]; + if (!self.isExpanded) { - if (!self.allowOrientationChange) { - switch(self.forceOrientation) { - case ANMRAIDOrientationLandscape: - if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) { - self.mraidController.orientation = UIInterfaceOrientationLandscapeRight; - break; - } - self.mraidController.orientation = UIInterfaceOrientationLandscapeLeft; + switch(self.forceOrientation) { + case ANMRAIDOrientationLandscape: + if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) { + self.mraidController.orientation = UIInterfaceOrientationLandscapeRight; break; - case ANMRAIDOrientationPortrait: - if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) { - self.mraidController.orientation = UIInterfaceOrientationPortraitUpsideDown; - break; - } - self.mraidController.orientation = UIInterfaceOrientationPortrait; + } + self.mraidController.orientation = UIInterfaceOrientationLandscapeLeft; + break; + case ANMRAIDOrientationPortrait: + if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) { + self.mraidController.orientation = UIInterfaceOrientationPortraitUpsideDown; break; - default: - self.mraidController.orientation = [[UIApplication sharedApplication] statusBarOrientation]; - } - } else { - self.mraidController.orientation = [[UIApplication sharedApplication] statusBarOrientation]; + } + self.mraidController.orientation = UIInterfaceOrientationPortrait; + break; + default: + break; } } } @@ -218,11 +215,8 @@ - (void)mraidExpandAd:(CGSize)size // expand to full screen if ((size.width == -1) && (size.height == -1)) { [contentView removeFromSuperview]; - if (!self.mraidController) { - self.mraidController = [ANMRAIDViewController new]; - self.mraidController.orientation = [[UIApplication sharedApplication] statusBarOrientation]; - } + self.mraidController = [ANMRAIDViewController new]; [self updateOrientationPropertiesOnMRAIDViewController]; self.mraidController.contentView = contentView; diff --git a/sdk/internal/ANInterstitialAdViewController.m b/sdk/internal/ANInterstitialAdViewController.m index f5ca9a4f7..88da17fae 100644 --- a/sdk/internal/ANInterstitialAdViewController.m +++ b/sdk/internal/ANInterstitialAdViewController.m @@ -122,35 +122,30 @@ - (void)centerContentView { self.contentView.frame = CGRectMake(centerX, centerY, contentWidth, contentHeight); } -- (void)setContentView:(UIView *)contentView -{ - if (contentView != __contentView) - { - if (contentView != nil) - { - if ([contentView isKindOfClass:[UIWebView class]]) - { - UIWebView *webView = (UIWebView *)contentView; - [webView removeDocumentPadding]; - [webView setMediaProperties]; - } - - [self.containerView addSubview:contentView]; - } - +- (void)setContentView:(UIView *)contentView { + if (contentView != __contentView) { + if ([__contentView isKindOfClass:[UIWebView class]]) { + UIWebView *webView = (UIWebView *)__contentView; + [webView stopLoading]; + [webView setDelegate:nil]; + } + [__contentView removeSubviews]; - [__contentView removeFromSuperview]; + [__contentView removeFromSuperview]; [self.containerView removeSubviews]; - - if ([__contentView isKindOfClass:[UIWebView class]]) - { - UIWebView *webView = (UIWebView *)__contentView; - [webView setDelegate:nil]; - [webView stopLoading]; - } - - __contentView = contentView; - } + + if (contentView != nil) { + if ([contentView isKindOfClass:[UIWebView class]]) { + UIWebView *webView = (UIWebView *)contentView; + [webView removeDocumentPadding]; + [webView setMediaProperties]; + } + + [self.containerView addSubview:contentView]; + } + + __contentView = contentView; + } } -(void)setBackgroundColor:(UIColor *)backgroundColor From af570b39957bc533d338368af941b852ec250685 Mon Sep 17 00:00:00 2001 From: Mark Ha Date: Tue, 29 Apr 2014 17:08:40 -0400 Subject: [PATCH 7/8] MS-655 Update Unit Tests --- tests/TestClasses/MRAIDTests.m | 7 ++-- tests/TestClasses/MediationTests.m | 39 ++++++++++++++++++- tests/TestClasses/TestUtils/ANBaseTestCase.m | 4 ++ tests/Tests.xcodeproj/project.pbxproj | 29 +++++++++----- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- .../xcschemes/TestsTests.xcscheme | 2 +- 6 files changed, 66 insertions(+), 17 deletions(-) diff --git a/tests/TestClasses/MRAIDTests.m b/tests/TestClasses/MRAIDTests.m index f61f00227..37092c5c6 100644 --- a/tests/TestClasses/MRAIDTests.m +++ b/tests/TestClasses/MRAIDTests.m @@ -1296,15 +1296,16 @@ - (void)testLoadInterstitialAd { [self delay:0.5]; [self.interstitial displayAdFromViewController:[UIApplication sharedApplication].keyWindow.rootViewController]; UIViewController *pvc = [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController; - id wv = [[pvc.view subviews] firstObject]; - STAssertTrue([wv isKindOfClass:[ANWebView class]], @"Expected ANWebView as subview of BannerAdView"); + // webview is contained in a container view + id wv = [[[[pvc.view subviews] firstObject] subviews] firstObject]; + STAssertTrue([wv isKindOfClass:[ANWebView class]], @"Expected ANWebView as subview of InterstitialAdView"); self.webView = (ANWebView *)wv; [self delay:2]; [self setResizePropertiesResizeToSize:CGSizeMake(320.0f, 50.0f) withOffset:CGPointZero withCustomClosePosition:@"top-left" allowOffscreen:YES]; [self resize]; - [self delay:100]; + [self delay:1]; } - (void)removeBannerFromSuperview { diff --git a/tests/TestClasses/MediationTests.m b/tests/TestClasses/MediationTests.m index ab59f7475..738210ee1 100644 --- a/tests/TestClasses/MediationTests.m +++ b/tests/TestClasses/MediationTests.m @@ -335,6 +335,7 @@ - (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs } #pragma mark ANAdFetcherDelegate + - (void)adFetcher:(ANAdFetcher *)fetcher didFinishRequestWithResponse:(ANAdResponse *)response { if (!__testComplete) @@ -387,8 +388,7 @@ - (void)adFetcher:(ANAdFetcher *)fetcher didFinishRequestWithResponse:(ANAdRespo } } -- (NSTimeInterval)autoRefreshIntervalForAdFetcher:(ANAdFetcher *)fetcher -{ +- (NSTimeInterval)autoRefreshIntervalForAdFetcher:(ANAdFetcher *)fetcher { return 0.0; } @@ -396,6 +396,17 @@ - (CGSize)requestedSizeForAdFetcher:(ANAdFetcher *)fetcher { return CGSizeMake(320, 50); } +- (void)adFetcher:(ANAdFetcher *)fetcher adShouldOpenInBrowserWithURL:(NSURL *)URL {}; + +#pragma mark ANBrowserViewControllerDelegate + +- (void)browserViewControllerShouldDismiss:(ANBrowserViewController *)controller{}; +- (void)browserViewControllerShouldPresent:(ANBrowserViewController *)controller{}; +- (void)browserViewControllerWillLaunchExternalApplication{}; +- (void)browserViewControllerWillNotPresent:(ANBrowserViewController *)controller{}; + +#pragma mark ANAdViewDelegate + - (void)adWasClicked{}; - (void)adWillPresent{}; - (void)adDidPresent{}; @@ -403,5 +414,29 @@ - (void)adWillClose{}; - (void)adDidClose{}; - (void)adWillLeaveApplication{}; - (void)adFailedToDisplay{}; +- (void)adDidReceiveAppEvent:(NSString *)name withData:(NSString *)data{}; + +#pragma mark ANMRAIDAdViewDelegate + +- (NSString *)adType{ + return nil; +}; + +- (UIViewController *)displayController{ + return nil; +}; + +- (void)adShouldResetToDefault{}; +- (void)adShouldExpandToFrame:(CGRect)frame closeButton:(UIButton *)closeButton{}; +- (void)adShouldResizeToFrame:(CGRect)frame allowOffscreen:(BOOL)allowOffscreen + closeButton:(UIButton *)closeButton + closePosition:(ANMRAIDCustomClosePosition)closePosition{}; +- (void)allowOrientationChange:(BOOL)allowOrientationChange + withForcedOrientation:(ANMRAIDOrientation)orientation{}; + +# pragma mark ANAppEventDelegate + +- (void)ad:(id)ad +didReceiveAppEvent:(NSString *)name withData:(NSString *)data{}; @end diff --git a/tests/TestClasses/TestUtils/ANBaseTestCase.m b/tests/TestClasses/TestUtils/ANBaseTestCase.m index a92f28cef..097fb7637 100644 --- a/tests/TestClasses/TestUtils/ANBaseTestCase.m +++ b/tests/TestClasses/TestUtils/ANBaseTestCase.m @@ -54,6 +54,10 @@ - (void)stubWithBody:(NSString *)body { .andReturn(200) .withBody(body) ; + stubRequest(@"GET", [AN_BASE_URL stringByAppendingString:@".*"].regex) + .andReturn(200) + .withBody(@"") + ; } - (void)stubResultCBResponses:(NSString *)body { diff --git a/tests/Tests.xcodeproj/project.pbxproj b/tests/Tests.xcodeproj/project.pbxproj index 7c41bda22..5c4363b40 100755 --- a/tests/Tests.xcodeproj/project.pbxproj +++ b/tests/Tests.xcodeproj/project.pbxproj @@ -55,9 +55,10 @@ EC09B320183437CC00D76510 /* NSString+Matcheable.m in Sources */ = {isa = PBXBuildFile; fileRef = EC09B28E1834340200D76510 /* NSString+Matcheable.m */; }; EC09B327183437CC00D76510 /* LSStubRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = EC09B2971834340200D76510 /* LSStubRequest.m */; }; EC09B329183437CC00D76510 /* LSStubResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = EC09B2991834340200D76510 /* LSStubResponse.m */; }; - EC3640E6183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3640E5183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.m */; }; + EC2E96C219103A00001A42EF /* ANANJAMImplementation.m in Sources */ = {isa = PBXBuildFile; fileRef = EC2E96C019103A00001A42EF /* ANANJAMImplementation.m */; }; + EC2E96C419103A7D001A42EF /* ANFailAndHitOtherCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3640EB184001EC00DB8000 /* ANFailAndHitOtherCallbacks.m */; }; + EC2E96C519103A7D001A42EF /* ANSuccessfulBannerNeverCalled.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3640E5183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.m */; }; EC3640E9183FFA9F00DB8000 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC3640E8183FFA9F00DB8000 /* CoreFoundation.framework */; }; - EC3640EC184001EC00DB8000 /* ANFailAndHitOtherCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3640EB184001EC00DB8000 /* ANFailAndHitOtherCallbacks.m */; }; EC4055FB183D43FB006A1D09 /* ANMRAIDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC4055FA183D43FB006A1D09 /* ANMRAIDViewController.m */; }; EC405619183D670D006A1D09 /* ANBaseTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = EC40560E183D5D88006A1D09 /* ANBaseTestCase.m */; }; EC40561A183D670D006A1D09 /* ANTestResponses.m in Sources */ = {isa = PBXBuildFile; fileRef = EC405610183D5D88006A1D09 /* ANTestResponses.m */; }; @@ -224,6 +225,9 @@ EC09B2981834340200D76510 /* LSStubResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LSStubResponse.h; sourceTree = ""; }; EC09B2991834340200D76510 /* LSStubResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LSStubResponse.m; sourceTree = ""; }; EC09B2B21834350E00D76510 /* BasicTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BasicTests.m; sourceTree = ""; }; + EC2E96BF19103A00001A42EF /* ANANJAMImplementation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANANJAMImplementation.h; sourceTree = ""; }; + EC2E96C019103A00001A42EF /* ANANJAMImplementation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANANJAMImplementation.m; sourceTree = ""; }; + EC2E96C119103A00001A42EF /* ANMRAIDProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANMRAIDProperties.h; sourceTree = ""; }; EC3640E4183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANSuccessfulBannerNeverCalled.h; sourceTree = ""; }; EC3640E5183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANSuccessfulBannerNeverCalled.m; sourceTree = ""; }; EC3640E8183FFA9F00DB8000 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; @@ -654,6 +658,9 @@ ECABE5581821E4C80037E6C5 /* internal */ = { isa = PBXGroup; children = ( + EC2E96BF19103A00001A42EF /* ANANJAMImplementation.h */, + EC2E96C019103A00001A42EF /* ANANJAMImplementation.m */, + EC2E96C119103A00001A42EF /* ANMRAIDProperties.h */, EC4055F9183D43FB006A1D09 /* ANMRAIDViewController.h */, EC4055FA183D43FB006A1D09 /* ANMRAIDViewController.m */, ECABE5591821E4C80037E6C5 /* ANAdFetcher.h */, @@ -814,7 +821,8 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastTestingUpgradeCheck = 0510; + LastUpgradeCheck = 0510; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; @@ -891,24 +899,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - EC3640EC184001EC00DB8000 /* ANFailAndHitOtherCallbacks.m in Sources */, 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 5C3208FB173061C700DAB5CF /* ANDemoAdsViewController.m in Sources */, 5C320905173090F300DAB5CF /* ANDemoConsoleViewController.m in Sources */, ECBA78B6187F6D4200F1D73F /* ANTargetingParameters.m in Sources */, 1D3623260D0F684500981E51 /* AppDelegate.m in Sources */, 5C3209001730664500DAB5CF /* RootViewController.m in Sources */, - EC3640E6183FE45B00DB8000 /* ANSuccessfulBannerNeverCalled.m in Sources */, ECABE58E1821E4C80037E6C5 /* ANAdFetcher.m in Sources */, + EC7AB08E188883DB00C27B1E /* ANAdRequestUrl.m in Sources */, EC7AB08B188883C300C27B1E /* ANLogManager.m in Sources */, ECABE58F1821E4C80037E6C5 /* ANAdResponse.m in Sources */, ECABE5911821E4C80037E6C5 /* ANAdWebViewController.m in Sources */, ECABE5901821E4C80037E6C5 /* ANAdView.m in Sources */, + EC2E96C219103A00001A42EF /* ANANJAMImplementation.m in Sources */, ECABE5921821E4C80037E6C5 /* ANBannerAdView.m in Sources */, ECABE5931821E4C80037E6C5 /* ANBrowserViewController.m in Sources */, ECABE5951821E4C80037E6C5 /* ANGlobal.m in Sources */, ECABE5961821E4C80037E6C5 /* ANInstallTrackerPixel.m in Sources */, - EC7AB08E188883DB00C27B1E /* ANAdRequestUrl.m in Sources */, ECABE5971821E4C80037E6C5 /* ANInterstitialAd.m in Sources */, ECABE5981821E4C80037E6C5 /* ANInterstitialAdViewController.m in Sources */, ECABE59A1821E4C80037E6C5 /* ANLocation.m in Sources */, @@ -933,6 +940,7 @@ EC40561F183D6818006A1D09 /* ANAdAdapterBannerNoAds.m in Sources */, EC405621183D6818006A1D09 /* ANAdAdapterBannerRequestFail.m in Sources */, EC405623183D6818006A1D09 /* ANAdAdapterErrorCode.m in Sources */, + EC2E96C419103A7D001A42EF /* ANFailAndHitOtherCallbacks.m in Sources */, EC405625183D6818006A1D09 /* ANFailedMultiple.m in Sources */, EC405627183D6818006A1D09 /* ANFailThenLoad.m in Sources */, EC405629183D6818006A1D09 /* ANLoadAndHitOtherCallbacks.m in Sources */, @@ -940,6 +948,7 @@ EC40562D183D6818006A1D09 /* ANLoadThenFail.m in Sources */, EC40562F183D6818006A1D09 /* ANTimeout.m in Sources */, EC405631183D6818006A1D09 /* ANSuccessfulBanner.m in Sources */, + EC2E96C519103A7D001A42EF /* ANSuccessfulBannerNeverCalled.m in Sources */, EC405619183D670D006A1D09 /* ANBaseTestCase.m in Sources */, EC40561A183D670D006A1D09 /* ANTestResponses.m in Sources */, ECD929B91822CD0E00420840 /* MediationCallbacksTests.m in Sources */, @@ -1052,7 +1061,7 @@ PREBINDING = NO; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphoneos; - VALID_ARCHS = "arm64 armv7 armv7s"; + VALID_ARCHS = "armv7 armv7s"; }; name = "Ad-Hoc"; }; @@ -1191,11 +1200,11 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; - VALID_ARCHS = "arm64 armv7 armv7s"; + VALID_ARCHS = "armv7 armv7s"; }; name = Debug; }; @@ -1211,7 +1220,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; - VALID_ARCHS = "arm64 armv7 armv7s"; + VALID_ARCHS = "armv7 armv7s"; }; name = Release; }; diff --git a/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index a32ace16c..bf589bf1d 100644 --- a/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Tue, 29 Apr 2014 18:12:58 -0400 Subject: [PATCH 8/8] SDK Version 1.15 --- ANSDK.xcodeproj/project.pbxproj | 22 +++++++++---------- .../xcshareddata/xcschemes/ANSDK.xcscheme | 2 +- .../xcschemes/ANSDKResources.xcscheme | 2 +- buildsdk.sh | 8 +++---- .../AppNexusSDKApp/AppNexusSDKApp.plist | 4 ++-- sdk/internal/ANGlobal.h | 2 +- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/ANSDK.xcodeproj/project.pbxproj b/ANSDK.xcodeproj/project.pbxproj index 1f165bfa5..635ddab33 100644 --- a/ANSDK.xcodeproj/project.pbxproj +++ b/ANSDK.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + EC2E96D91911A147001A42EF /* ANANJAMImplementation.m in Sources */ = {isa = PBXBuildFile; fileRef = EC2E96D81911A147001A42EF /* ANANJAMImplementation.m */; }; EC3905FA186693B50017959C /* ANTargetingParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3905F9186693B50017959C /* ANTargetingParameters.m */; }; EC3905FB186693D30017959C /* ANTargetingParameters.h in Copy Files */ = {isa = PBXBuildFile; fileRef = EC3905F8186693AA0017959C /* ANTargetingParameters.h */; }; EC3E5CE01843C6D50070315E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC3E5CDF1843C6D50070315E /* Foundation.framework */; }; @@ -90,6 +91,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + EC2E96D71911A147001A42EF /* ANANJAMImplementation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANANJAMImplementation.h; sourceTree = ""; }; + EC2E96D81911A147001A42EF /* ANANJAMImplementation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANANJAMImplementation.m; sourceTree = ""; }; EC3905F8186693AA0017959C /* ANTargetingParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANTargetingParameters.h; sourceTree = ""; }; EC3905F9186693B50017959C /* ANTargetingParameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANTargetingParameters.m; sourceTree = ""; }; EC3E5CDC1843C6D50070315E /* libANSDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libANSDK.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -255,6 +258,8 @@ EC3E5D1B1843C7560070315E /* ANAdViewDelegate.h */, EC3E5D1C1843C7560070315E /* ANAdWebViewController.h */, EC3E5D1D1843C7560070315E /* ANAdWebViewController.m */, + EC2E96D71911A147001A42EF /* ANANJAMImplementation.h */, + EC2E96D81911A147001A42EF /* ANANJAMImplementation.m */, EC3E5D1E1843C7560070315E /* ANBannerAdView.m */, EC3E5D1F1843C7560070315E /* ANBrowserViewController.h */, EC3E5D201843C7560070315E /* ANBrowserViewController.m */, @@ -358,7 +363,7 @@ EC3E5CD41843C6D50070315E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0510; ORGANIZATIONNAME = AppNexus; }; buildConfigurationList = EC3E5CD71843C6D50070315E /* Build configuration list for PBXProject "ANSDK" */; @@ -419,6 +424,7 @@ EC3E5D4B1843C7560070315E /* ANAdView.m in Sources */, EC3E5D491843C7560070315E /* ANAdFetcher.m in Sources */, EC3E5D4C1843C7560070315E /* ANAdWebViewController.m in Sources */, + EC2E96D91911A147001A42EF /* ANANJAMImplementation.m in Sources */, EC3E5D571843C7560070315E /* ANMRAIDViewController.m in Sources */, EC3E5D4F1843C7560070315E /* ANGlobal.m in Sources */, EC9B33CC187DA9F300013F79 /* ANWebView.m in Sources */, @@ -464,10 +470,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - "$(ARCHS_STANDARD_INCLUDING_64_BIT)", - i386, - ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -498,8 +500,8 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IBC_FLATTEN_NIBS = NO; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - ONLY_ACTIVE_ARCH = NO; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SYMROOT = build; VALID_ARCHS = "arm64 armv7 armv7s i386"; @@ -510,10 +512,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - "$(ARCHS_STANDARD_INCLUDING_64_BIT)", - i386, - ); CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -538,7 +536,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IBC_FLATTEN_NIBS = NO; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; ONLY_ACTIVE_ARCH = NO; SDKROOT = iphoneos; SYMROOT = build; diff --git a/ANSDK.xcodeproj/xcshareddata/xcschemes/ANSDK.xcscheme b/ANSDK.xcodeproj/xcshareddata/xcschemes/ANSDK.xcscheme index a46f7ecec..7f3c92b5e 100644 --- a/ANSDK.xcodeproj/xcshareddata/xcschemes/ANSDK.xcscheme +++ b/ANSDK.xcodeproj/xcshareddata/xcschemes/ANSDK.xcscheme @@ -1,6 +1,6 @@ $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} +xcodebuild -project 'ANSDK.xcodeproj/' -scheme 'ANSDK' -configuration 'Release' -sdk iphoneos7.1 CONFIGURATION_BUILD_DIR=$OUTDIR SYMROOT=$BUILDDIR OBJROOT=$BUILDDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} mv $OUTDIR/libANSDK.a $OUTDIR/ANSDK/libANSDK.a echo "Started building of Full AN SDK" LOGFILE=$LOGDIR/ANSDKFull.log -xcodebuild -project 'ANSDKFull.xcodeproj/' -scheme 'ANSDKFull' -configuration 'Release' -sdk iphoneos7.0 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} +xcodebuild -project 'ANSDKFull.xcodeproj/' -scheme 'ANSDKFull' -configuration 'Release' -sdk iphoneos7.1 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} mv $OUTDIR/libANSDKFull.a $OUTDIR/ANSDKFull/libANSDKFull.a echo "Started building of Full AN SDK with Mopub Adaptor" LOGFILE=$LOGDIR/ANSDKFullMopub.log -xcodebuild -project 'ANSDKMoPub.xcodeproj/' -scheme 'ANSDKMoPub' -configuration 'Release' -sdk iphoneos7.0 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} +xcodebuild -project 'ANSDKMoPub.xcodeproj/' -scheme 'ANSDKMoPub' -configuration 'Release' -sdk iphoneos7.1 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} mv $OUTDIR/libANSDKMoPub.a $OUTDIR/ANSDKMoPub/libANSDKMoPub.a echo "Started building of Full AN SDK with Admob Adaptor" LOGFILE=$LOGDIR/ANSDKFullAdmob.log -xcodebuild -project 'ANSDKAdMob.xcodeproj/' -scheme 'ANSDKAdMob' -configuration 'Release' -sdk iphoneos7.0 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} +xcodebuild -project 'ANSDKAdMob.xcodeproj/' -scheme 'ANSDKAdMob' -configuration 'Release' -sdk iphoneos7.1 CONFIGURATION_BUILD_DIR=$OUTDIR > $LOGFILE 2>&1 || { echo "Error in build check log $LOGFILE"; exit;} mv $OUTDIR/libANSDKAdMob.a $OUTDIR/ANSDKAdMob/libANSDKAdMob.a rm -rf $OUTDIR/Intermediates diff --git a/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist b/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist index dfd41f524..d432e908b 100644 --- a/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist +++ b/examples/AppNexusSDKApp/AppNexusSDKApp/AppNexusSDKApp.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.13 + 1.135 CFBundleSignature ???? CFBundleURLTypes @@ -36,7 +36,7 @@ CFBundleVersion - 6 + 7 LSRequiresIPhoneOS UIMainStoryboardFile diff --git a/sdk/internal/ANGlobal.h b/sdk/internal/ANGlobal.h index e2cef0462..94b753842 100644 --- a/sdk/internal/ANGlobal.h +++ b/sdk/internal/ANGlobal.h @@ -24,7 +24,7 @@ #define AN_RESOURCE_BUNDLE @"ANSDKResources" #define AN_DEFAULT_PLACEMENT_ID @"default_placement_id" -#define AN_SDK_VERSION @"1.13" +#define AN_SDK_VERSION @"1.15" #define APPNEXUS_BANNER_SIZE CGSizeMake(320, 50) #define APPNEXUS_MEDIUM_RECT_SIZE CGSizeMake(300, 250)