Skip to content

Commit b3cf505

Browse files
committed
This commit adds a few features:
- The ability to retrieve SSL certificates for the pages in the webview - Allows the delegate to dictate whether the height of the content div should get fixed - Nicer handling of javascript alerts
1 parent a6242b3 commit b3cf505

3 files changed

Lines changed: 132 additions & 8 deletions

File tree

FsprgEmbeddedStore/FsprgEmbeddedStoreController.h

100644100755
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,16 @@
6464
*/
6565
- (BOOL)isSecure;
6666

67+
/**
68+
*
69+
* @result NSArray containing SecCertificateRef objects for the host of the main frame, if it was loaded via https.
70+
*/
71+
- (NSArray *)securityCertificates;
72+
6773
/*!
6874
* Host that delivers the store (e.g. sites.fastspring.com).
6975
* @result <code>nil</code> until the store has been loaded.
7076
*/
7177
- (NSString *)storeHost;
7278

73-
@end
79+
@end

FsprgEmbeddedStore/FsprgEmbeddedStoreController.m

100644100755
Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,28 @@
1010
#import "FsprgOrderView.h"
1111
#import "FsprgOrderDocumentRepresentation.h"
1212

13+
@interface FsprgEmbeddedStoreController ()
14+
15+
@property (nonatomic, retain) NSMutableDictionary *hostCertificates;
16+
@property (nonatomic, retain) NSMapTable *connectionsToRequests;
17+
18+
@end
1319

1420
@interface FsprgEmbeddedStoreController (Private)
21+
1522
- (void)setIsLoading:(BOOL)aFlag;
1623
- (void)setEstimatedLoadingProgress:(double)aProgress;
1724
- (void)setIsSecure:(BOOL)aFlag;
1825
- (void)setStoreHost:(NSString *)aHost;
1926
- (void)resizeContentDivE;
2027
- (void)webViewFrameChanged:(NSNotification *)aNotification;
28+
2129
@end
2230

2331
@implementation FsprgEmbeddedStoreController
2432

33+
@synthesize hostCertificates=_hostCertificates;
34+
2535
+ (void)initialize
2636
{
2737
[WebView registerViewClass:[FsprgOrderView class]
@@ -36,10 +46,23 @@ - (id) init
3646
[self setWebView:nil];
3747
[self setDelegate:nil];
3848
[self setStoreHost:nil];
49+
self.hostCertificates = [NSMutableDictionary dictionary];
50+
self.connectionsToRequests = [NSMapTable mapTableWithStrongToStrongObjects];
3951
}
4052
return self;
4153
}
4254

55+
- (void)dealloc
56+
{
57+
[self setWebView:nil];
58+
[self setDelegate:nil];
59+
[self setStoreHost:nil];
60+
[_hostCertificates release];
61+
[_connectionsToRequests release];
62+
63+
[super dealloc];
64+
}
65+
4366
- (WebView *)webView
4467
{
4568
return [[webView retain] autorelease];
@@ -51,6 +74,7 @@ - (void)setWebView:(WebView *)aWebView
5174
[webView setPostsFrameChangedNotifications:FALSE];
5275
[webView setFrameLoadDelegate:nil];
5376
[webView setUIDelegate:nil];
77+
[webView setResourceLoadDelegate:nil];
5478
[webView setApplicationNameForUserAgent:nil];
5579
[[NSNotificationCenter defaultCenter] removeObserver:self];
5680

@@ -61,6 +85,7 @@ - (void)setWebView:(WebView *)aWebView
6185
[webView setPostsFrameChangedNotifications:TRUE];
6286
[webView setFrameLoadDelegate:self];
6387
[webView setUIDelegate:self];
88+
[webView setResourceLoadDelegate:self];
6489
[webView setApplicationNameForUserAgent:@"FSEmbeddedStore/2.0"];
6590
[[NSNotificationCenter defaultCenter] addObserver:self
6691
selector:@selector(webViewFrameChanged:)
@@ -96,6 +121,8 @@ - (void)setDelegate:(id <FsprgEmbeddedStoreDelegate>)aDelegate
96121
- (void)loadWithParameters:(FsprgStoreParameters *)parameters
97122
{
98123
NSURLRequest *urlRequest = [parameters toURLRequest];
124+
if (urlRequest == nil)
125+
return;
99126

100127
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[urlRequest URL]];
101128
NSUInteger i, count = [cookies count];
@@ -151,6 +178,15 @@ - (void)setIsSecure:(BOOL)aFlag
151178
// just triggering change observer
152179
}
153180

181+
- (NSArray *)securityCertificates
182+
{
183+
if ([self isSecure] == NO)
184+
return nil;
185+
NSString *mainFrameURL = [[self webView] mainFrameURL];
186+
NSString *host = [[NSURL URLWithString:mainFrameURL] host];
187+
return [self.hostCertificates objectForKey:host];
188+
}
189+
154190
- (NSString *)storeHost
155191
{
156192
return [[storeHost retain] autorelease];
@@ -165,13 +201,22 @@ - (void)setStoreHost:(NSString *)aHost
165201
}
166202

167203
- (void)resizeContentDivE {
204+
if ([self.delegate respondsToSelector:@selector(shouldStoreControllerFixContentDivHeight:)])
205+
{
206+
if ([self.delegate shouldStoreControllerFixContentDivHeight:self] == NO)
207+
return;
208+
}
209+
168210
DOMElement *resizableContentE = [[[[self webView] mainFrame] DOMDocument] getElementById:@"FsprgResizableContent"];
169211
if(resizableContentE == nil) {
170212
return;
171213
}
172214

173215
float windowHeight = [[self webView] frame].size.height;
174-
float pageNavigationHeight = [[[[self webView] windowScriptObject] evaluateWebScript:@"document.getElementsByClassName('store-page-navigation')[0].clientHeight"] floatValue];
216+
id result = [[[self webView] windowScriptObject] evaluateWebScript:@"document.getElementsByClassName('store-page-navigation')[0].clientHeight"];
217+
if (result == [WebUndefined undefined])
218+
return;
219+
float pageNavigationHeight = [(NSString *)result floatValue];
175220

176221
DOMCSSStyleDeclaration *cssStyle = [[self webView] computedStyleForElement:resizableContentE pseudoElement:nil];
177222
float paddingTop = [[[cssStyle paddingBottom] substringToIndex:[[cssStyle paddingTop] length]-2] floatValue];
@@ -237,7 +282,14 @@ - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame
237282

238283
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
239284
{
240-
NSRunAlertPanel(@"Alert", message, @"OK", nil, nil);
285+
NSString *title = [sender mainFrameTitle];
286+
NSAlert *alertPanel = [NSAlert alertWithMessageText:title defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", message];
287+
[alertPanel beginSheetModalForWindow:[sender window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
288+
}
289+
290+
- (NSUInteger)webView:(WebView *)sender dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
291+
{
292+
return WebDragDestinationActionNone;
241293
}
242294

243295
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request
@@ -254,13 +306,68 @@ - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)
254306
return subWebView;
255307
}
256308

257-
- (void)dealloc
309+
#pragma mark - WebResourceLoadDelegate
310+
311+
- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
258312
{
259-
[self setWebView:nil];
260-
[self setDelegate:nil];
261-
[self setStoreHost:nil];
313+
NSURL *URL = [request URL];
314+
NSString *host = [URL host];
315+
if ([self.hostCertificates objectForKey:host] == nil)
316+
{
317+
NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
318+
[self.connectionsToRequests setObject:request forKey:connection];
319+
}
320+
return request;
321+
}
322+
323+
#pragma mark - NURLConnection delegate
324+
325+
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
326+
{
327+
return cachedResponse;
328+
}
329+
330+
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
331+
{
332+
}
333+
334+
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
335+
{
336+
}
337+
338+
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
339+
{
340+
return request;
341+
}
342+
343+
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
344+
{
345+
[self.connectionsToRequests setObject:nil forKey:connection];
346+
}
347+
348+
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
349+
{
350+
return YES;
351+
}
352+
353+
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
354+
{
355+
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
356+
SecTrustResultType resultType;
357+
SecTrustEvaluate(trustRef, &resultType);
358+
CFIndex count = SecTrustGetCertificateCount(trustRef);
262359

263-
[super dealloc];
360+
NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:count];
361+
for (CFIndex idx = 0; idx < count; idx++)
362+
{
363+
SecCertificateRef certificateRef = SecTrustGetCertificateAtIndex(trustRef, idx);
364+
[certificates addObject:(id)certificateRef];
365+
}
366+
367+
NSURLRequest *request = [self.connectionsToRequests objectForKey:connection];
368+
NSURL *URL = [request URL];
369+
NSString *host = [URL host];
370+
[self.hostCertificates setObject:certificates forKey:host];
264371
}
265372

266373
@end

FsprgEmbeddedStore/FsprgEmbeddedStoreDelegate.h

100644100755
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ typedef enum {
1818
FsprgPageUnknown
1919
} FsprgPageType;
2020

21+
@class FsprgEmbeddedStoreController;
2122

2223
/*!
2324
* Delegate protocol for FsprgEmbeddedStoreController.
@@ -51,6 +52,16 @@ typedef enum {
5152
*/
5253
- (NSView *)viewWithFrame:(NSRect)frame forOrder:(FsprgOrder *)order;
5354

55+
/*!
56+
* Gets called after loading the page and upon resizing the window.
57+
* The default embedded store layout assumes that the content div's height will get shortened
58+
* to make room for the navigation bar. If your layout doesn't require that assumption, you can
59+
* return NO here to avoid this manual height fixing.
60+
* @param controller The store controller in question
61+
* @result YES if you'd like the store controller to fix the content div's height, NO otherwise.
62+
*/
63+
- (BOOL)shouldStoreControllerFixContentDivHeight:(FsprgEmbeddedStoreController *)controller;
64+
5465
/*!
5566
* Invoked if an error occurs when starting to load data for a page.
5667
* @param sender The web view containing the frame.

0 commit comments

Comments
 (0)