mirror of
https://github.com/zhigang1992/shadowsocks-iOS.git
synced 2026-06-11 16:49:42 +08:00
667 lines
26 KiB
Objective-C
667 lines
26 KiB
Objective-C
//
|
|
// WebViewController.m
|
|
// OnionBrowser
|
|
//
|
|
// Created by Mike Tigas on 2/25/12.
|
|
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
|
|
//
|
|
|
|
#include "err.h"
|
|
|
|
#import "WebViewController.h"
|
|
#import "AppDelegate.h"
|
|
#import "BookmarkTableViewController.h"
|
|
#import "SettingsViewController.h"
|
|
#import "Bookmark.h"
|
|
#import "BridgeTableViewController.h"
|
|
#import "ProxySettingsTableViewController.h"
|
|
|
|
static const CGFloat kNavBarHeight = 52.0f;
|
|
static const CGFloat kToolBarHeight = 44.0f;
|
|
static const CGFloat kLabelHeight = 14.0f;
|
|
static const CGFloat kMargin = 10.0f;
|
|
static const CGFloat kSpacer = 2.0f;
|
|
static const CGFloat kLabelFontSize = 12.0f;
|
|
static const CGFloat kAddressHeight = 26.0f;
|
|
|
|
static const NSInteger kNavBarTag = 1000;
|
|
static const NSInteger kAddressFieldTag = 1001;
|
|
static const NSInteger kAddressCancelButtonTag = 1002;
|
|
static const NSInteger kLoadingStatusTag = 1003;
|
|
|
|
static const Boolean kForwardButton = YES;
|
|
static const Boolean kBackwardButton = NO;
|
|
|
|
@interface WebViewController ()
|
|
|
|
@end
|
|
|
|
@implementation WebViewController
|
|
|
|
@synthesize myWebView = _myWebView,
|
|
toolbar = _toolbar,
|
|
backButton = _backButton,
|
|
forwardButton = _forwardButton,
|
|
toolButton = _toolButton,
|
|
optionsMenu = _optionsMenu,
|
|
bookmarkButton = _bookmarkButton,
|
|
stopRefreshButton = _stopRefreshButton,
|
|
pageTitleLabel = _pageTitleLabel,
|
|
addressField = _addressField,
|
|
currentURL = _currentURL,
|
|
torStatus = _torStatus;
|
|
@synthesize addrItemsActive, addrItemsInactive, cancelButton;
|
|
|
|
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
|
{
|
|
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
|
if (self) {
|
|
dontLoadURLNow = NO;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)loadView {
|
|
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
|
|
self.view = contentView;
|
|
CGRect webViewFrame = [[UIScreen mainScreen] applicationFrame];
|
|
webViewFrame.origin.y = kNavBarHeight;
|
|
webViewFrame.origin.x = 0;
|
|
webViewFrame.size.height = webViewFrame.size.height - kToolBarHeight - kNavBarHeight;
|
|
_myWebView = [[UIWebView alloc] initWithFrame:webViewFrame];
|
|
_myWebView.backgroundColor = [UIColor whiteColor];
|
|
_myWebView.scalesPageToFit = YES;
|
|
_myWebView.contentScaleFactor = 3;
|
|
_myWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
|
|
_myWebView.delegate = self;
|
|
[self.view addSubview: _myWebView];
|
|
}
|
|
|
|
- (void)renderTorStatus: (NSString *)statusLine {
|
|
// TODO: really needs cleanup / prettiness
|
|
// (turn into semi-transparent modal with spinner?)
|
|
UILabel *loadingStatus = (UILabel *)[self.view viewWithTag:kLoadingStatusTag];
|
|
|
|
_torStatus = [NSString stringWithFormat:@"%@\n%@",
|
|
_torStatus, statusLine];
|
|
NSRange progress_loc = [statusLine rangeOfString:@"BOOTSTRAP PROGRESS="];
|
|
NSRange progress_r = {
|
|
progress_loc.location+progress_loc.length,
|
|
2
|
|
};
|
|
NSString *progress_str = @"";
|
|
if (progress_loc.location != NSNotFound)
|
|
progress_str = [statusLine substringWithRange:progress_r];
|
|
|
|
NSRange summary_loc = [statusLine rangeOfString:@" SUMMARY="];
|
|
NSString *summary_str = @"";
|
|
if (summary_loc.location != NSNotFound)
|
|
summary_str = [statusLine substringFromIndex:summary_loc.location+summary_loc.length+1];
|
|
NSRange summary_loc2 = [summary_str rangeOfString:@"\""];
|
|
if (summary_loc2.location != NSNotFound)
|
|
summary_str = [summary_str substringToIndex:summary_loc2.location];
|
|
|
|
NSString *status = [NSString stringWithFormat:@"Connecting… This may take a minute.\n\nIf this takes longer than 60 seconds, please close and re-open the app to try connecting from scratch.\n\nIf this problem persists, you can try connecting via Tor bridges by pressing the \"options\" button below. Visit http://onionbrowser.com/help/ if you need help with bridges or if you continue to have issues.\n\n%@%%\n%@",
|
|
progress_str,
|
|
summary_str];
|
|
loadingStatus.text = status;
|
|
|
|
}
|
|
|
|
-(void)loadURL: (NSURL *)navigationURL {
|
|
// Remove the "connecting..." (initial tor load) overlay if it still exists.
|
|
UIView *loadingStatus = [self.view viewWithTag:kLoadingStatusTag];
|
|
if (loadingStatus != nil) {
|
|
[loadingStatus removeFromSuperview];
|
|
}
|
|
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
|
|
// Build request and go.
|
|
_myWebView.delegate = self;
|
|
_myWebView.scalesPageToFit = YES;
|
|
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:navigationURL];
|
|
[req setHTTPShouldUsePipelining:appDelegate.usePipelining];
|
|
[_myWebView loadRequest:req];
|
|
|
|
_addressField.enabled = YES;
|
|
_toolButton.enabled = YES;
|
|
_stopRefreshButton.enabled = YES;
|
|
_bookmarkButton.enabled = YES;
|
|
[self updateButtons];
|
|
}
|
|
|
|
|
|
- (UIImage *)makeForwardBackButtonImage:(Boolean)whichButton {
|
|
// Draws the vector image for the forward or back button. (see kForwardButton
|
|
// and kBackwardButton for the "whichButton" values)
|
|
CGFloat scale = [[UIScreen mainScreen] scale];
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGContextRef context = CGBitmapContextCreate(nil,28*scale,28*scale,8,0,
|
|
colorSpace,kCGImageAlphaPremultipliedLast);
|
|
CFRelease(colorSpace);
|
|
CGColorRef fillColor = [[UIColor blackColor] CGColor];
|
|
CGContextSetFillColor(context, CGColorGetComponents(fillColor));
|
|
|
|
CGContextBeginPath(context);
|
|
if (whichButton == kForwardButton) {
|
|
CGContextMoveToPoint(context, 20.0f*scale, 12.0f*scale);
|
|
CGContextAddLineToPoint(context, 4.0f*scale, 4.0f*scale);
|
|
CGContextAddLineToPoint(context, 4.0f*scale, 22.0f*scale);
|
|
} else {
|
|
CGContextMoveToPoint(context, 8.0f*scale, 12.0f*scale);
|
|
CGContextAddLineToPoint(context, 24.0f*scale, 4.0f*scale);
|
|
CGContextAddLineToPoint(context, 24.0f*scale, 22.0f*scale);
|
|
}
|
|
CGContextClosePath(context);
|
|
CGContextFillPath(context);
|
|
|
|
CGImageRef theCGImage = CGBitmapContextCreateImage(context);
|
|
CGContextRelease(context);
|
|
UIImage *buttonImage = [[UIImage alloc] initWithCGImage:theCGImage
|
|
scale:[[UIScreen mainScreen] scale]
|
|
orientation:UIImageOrientationUp];
|
|
CGImageRelease(theCGImage);
|
|
return buttonImage;
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
|
|
// Set up toolbar.
|
|
_toolbar = [[UIToolbar alloc] init];
|
|
[_toolbar setTintColor:[UIColor blackColor]];
|
|
_toolbar.frame = CGRectMake(0, self.view.frame.size.height - kToolBarHeight, self.view.frame.size.width, kToolBarHeight);
|
|
_toolbar.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
|
|
_toolbar.contentMode = UIViewContentModeBottom;
|
|
UIBarButtonItem *space = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
|
|
target:nil
|
|
action:nil];
|
|
|
|
_backButton = [[UIBarButtonItem alloc] initWithImage:[self makeForwardBackButtonImage:kBackwardButton]
|
|
style:UIBarButtonItemStylePlain
|
|
target:self
|
|
action:@selector(goBack)];
|
|
_forwardButton = [[UIBarButtonItem alloc] initWithImage:[self makeForwardBackButtonImage:kForwardButton]
|
|
style:UIBarButtonItemStylePlain
|
|
target:self
|
|
action:@selector(goForward)];
|
|
_toolButton = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemAction
|
|
target:self
|
|
action:@selector(openOptionsMenu)];
|
|
_bookmarkButton = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks
|
|
target:self
|
|
action:@selector(showBookmarks)];
|
|
_stopRefreshButton = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
|
|
target:self
|
|
action:@selector(stopLoading)];
|
|
|
|
_forwardButton.enabled = NO;
|
|
_backButton.enabled = NO;
|
|
_stopRefreshButton.enabled = NO;
|
|
_toolButton.enabled = YES;
|
|
_bookmarkButton.enabled = YES;
|
|
|
|
NSMutableArray *items = [[NSMutableArray alloc] init];
|
|
[items addObject:_backButton];
|
|
[items addObject:space];
|
|
[items addObject:_forwardButton];
|
|
[items addObject:space];
|
|
[items addObject:_toolButton];
|
|
[items addObject:space];
|
|
[items addObject:_bookmarkButton];
|
|
[items addObject:space];
|
|
[items addObject:_stopRefreshButton];
|
|
[_toolbar setItems:items animated:NO];
|
|
|
|
[self.view addSubview:_toolbar];
|
|
// (/toolbar)
|
|
|
|
// Set up actionsheets (options menu, bookmarks menu)
|
|
_optionsMenu = [[UIActionSheet alloc] initWithTitle:nil
|
|
delegate:self
|
|
cancelButtonTitle:@"Close"
|
|
destructiveButtonTitle:nil
|
|
otherButtonTitles:@"Bookmark Current Page", @"Proxy Settings", @"About", nil];
|
|
// (/actionsheets)
|
|
|
|
|
|
// Set up navbar
|
|
CGRect navBarFrame = self.view.bounds;
|
|
navBarFrame.size.height = kNavBarHeight;
|
|
UIToolbar *navBar = [[UIToolbar alloc] initWithFrame:navBarFrame];
|
|
navBar.tag = kNavBarTag;
|
|
navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
|
|
|
CGRect labelFrame = CGRectMake(kMargin, kSpacer,
|
|
navBar.bounds.size.width - 2*kMargin, kLabelHeight);
|
|
UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
|
|
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
|
label.text = @"";
|
|
label.backgroundColor = [UIColor clearColor];
|
|
label.font = [UIFont systemFontOfSize:12];
|
|
label.textAlignment = UITextAlignmentCenter;
|
|
|
|
[navBar setTintColor:[UIColor blackColor]];
|
|
[label setTextColor:[UIColor whiteColor]];
|
|
|
|
[navBar addSubview:label];
|
|
_pageTitleLabel = label;
|
|
|
|
// The address field is the same with as the label and located just below
|
|
// it with a gap of kSpacer
|
|
CGRect addressFrame = CGRectMake(kMargin, kSpacer*2.0 + kLabelHeight,
|
|
labelFrame.size.width, kAddressHeight);
|
|
UITextField *address = [[UITextField alloc] initWithFrame:addressFrame];
|
|
|
|
address.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
|
address.borderStyle = UITextBorderStyleRoundedRect;
|
|
address.font = [UIFont systemFontOfSize:17];
|
|
address.keyboardType = UIKeyboardTypeURL;
|
|
address.returnKeyType = UIReturnKeyGo;
|
|
address.autocorrectionType = UITextAutocorrectionTypeNo;
|
|
address.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
|
address.clearButtonMode = UITextFieldViewModeWhileEditing;
|
|
address.delegate = self;
|
|
address.tag = kAddressFieldTag;
|
|
// [address addTarget:self
|
|
// action:@selector(loadAddress:event:)
|
|
// forControlEvents:UIControlEventEditingDidEndOnExit|UIControlEventEditingDidEnd];
|
|
|
|
self.cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(addressBarCancel) ];
|
|
|
|
self.addrItemsInactive = [NSMutableArray arrayWithObjects:[[UIBarButtonItem alloc] initWithCustomView:address], [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], nil];
|
|
self.addrItemsActive = [NSMutableArray arrayWithArray:addrItemsInactive];
|
|
[addrItemsActive addObject:cancelButton];
|
|
|
|
[navBar setItems:addrItemsInactive];
|
|
[navBar setBarStyle:UIBarStyleBlack];
|
|
|
|
_addressField = address;
|
|
_addressField.enabled = YES;
|
|
[self.view addSubview:navBar];
|
|
// (/navbar)
|
|
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
if (appDelegate.doPrepopulateBookmarks){
|
|
[self prePopulateBookmarks];
|
|
}
|
|
}
|
|
|
|
-(void)viewDidAppear:(BOOL)animated {
|
|
if ([ProxySettingsTableViewController settingsAreNotComplete]) {
|
|
[self showSettings];
|
|
}
|
|
}
|
|
|
|
-(void) prePopulateBookmarks {
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
|
|
NSManagedObjectContext *context = [appDelegate managedObjectContext];
|
|
|
|
NSError *error = nil;
|
|
if (![context save:&error]) {
|
|
NSLog(@"Error adding bookmarks: %@", error);
|
|
}
|
|
}
|
|
|
|
|
|
- (void)viewDidUnload {
|
|
[super viewDidUnload];
|
|
}
|
|
|
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
|
// Allow all four orientations on iPad.
|
|
// Disallow upside-down for iPhone.
|
|
return (IS_IPAD) || (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark WebView behavior
|
|
|
|
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
|
|
[self updateAddress:request];
|
|
return YES;
|
|
}
|
|
|
|
- (void)webViewDidStartLoad:(UIWebView *)webView {
|
|
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
|
|
[self updateButtons];
|
|
}
|
|
|
|
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
|
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
|
|
[self updateButtons];
|
|
[self updateTitle:webView];
|
|
NSURLRequest* request = [webView request];
|
|
[self updateAddress:request];
|
|
}
|
|
|
|
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
|
|
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
|
|
[self updateButtons];
|
|
[self informError:error];
|
|
#ifdef DEBUG
|
|
NSString* errorString = [NSString stringWithFormat:@"error %@",
|
|
error.localizedDescription];
|
|
NSLog(@"[WebViewController] Error: %@", errorString);
|
|
#endif
|
|
}
|
|
|
|
- (void)informError:(NSError *)error {
|
|
if ([error.domain isEqualToString:@"NSOSStatusErrorDomain"] &&
|
|
(error.code == -9807 || error.code == -9812)) {
|
|
// Invalid certificate chain; valid cert chain, untrusted root
|
|
|
|
UIAlertView* alertView = [[UIAlertView alloc]
|
|
initWithTitle:@"SSL Error"
|
|
message:@"Certificate chain is invalid. Either the site's SSL certificate is self-signed or the certificate was signed by an untrusted authority."
|
|
delegate:nil
|
|
cancelButtonTitle:@"Cancel"
|
|
otherButtonTitles:@"Continue",nil];
|
|
alertView.delegate = self;
|
|
[alertView show];
|
|
|
|
} else if ([error.domain isEqualToString:(NSString *)kCFErrorDomainCFNetwork] ||
|
|
[error.domain isEqualToString:@"NSOSStatusErrorDomain"]) {
|
|
NSString* errorDescription;
|
|
|
|
if (error.code == kCFSOCKS5ErrorBadState) {
|
|
errorDescription = @"Could not connect to the server. Either the domain name is incorrect, the server is inaccessible, or the Tor circuit was broken.";
|
|
} else if (error.code == kCFHostErrorHostNotFound) {
|
|
errorDescription = @"The server could not be found";
|
|
} else {
|
|
errorDescription = [NSString stringWithFormat:@"An error occurred: %@",
|
|
error.localizedDescription];
|
|
}
|
|
UIAlertView* alertView = [[UIAlertView alloc]
|
|
initWithTitle:@"Cannot Open Page"
|
|
message:errorDescription delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
[alertView show];
|
|
}
|
|
#ifdef DEBUG
|
|
else {
|
|
NSLog(@"[WebViewController] uncaught error: %@", [error localizedDescription]);
|
|
NSLog(@"\t -> %@", error.domain);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
|
|
if (buttonIndex == 1) {
|
|
// "Continue anyway" for SSL cert error
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
|
|
// Assumung URL in address bar is the one that caused this error.
|
|
NSURL *url = [NSURL URLWithString:_currentURL];
|
|
NSString *hostname = url.host;
|
|
[appDelegate.sslWhitelistedDomains addObject:hostname];
|
|
|
|
UIAlertView* alertView = [[UIAlertView alloc]
|
|
initWithTitle:@"Whitelisted Domain"
|
|
message:[NSString stringWithFormat:@"SSL certificate errors for '%@' will be ignored for the rest of this session.", hostname] delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
[alertView show];
|
|
|
|
// Reload (now that we have added host to whitelist)
|
|
[self loadURL:url];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# pragma mark -
|
|
# pragma mark Address Bar
|
|
|
|
- (void)addressBarCancel {
|
|
_addressField.text = _currentURL;
|
|
dontLoadURLNow = YES;
|
|
[_addressField resignFirstResponder];
|
|
dontLoadURLNow = NO;
|
|
}
|
|
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
|
[textField resignFirstResponder];
|
|
return YES;
|
|
}
|
|
|
|
- (void)textFieldDidBeginEditing:(UITextField *)textField {
|
|
// Stop loading if we are loading a page
|
|
[_myWebView stopLoading];
|
|
|
|
// Move a "cancel" button into the nav bar a la Safari.
|
|
UIToolbar *navBar = (UIToolbar *)[self.view viewWithTag:kNavBarTag];
|
|
|
|
[navBar setItems:addrItemsActive animated:YES];
|
|
|
|
|
|
[UIView beginAnimations:nil context:NULL];
|
|
[_addressField setFrame:CGRectMake(kMargin, kSpacer*2.0 + kLabelHeight,
|
|
navBar.bounds.size.width - 2*kMargin - 70, kAddressHeight)];
|
|
[UIView commitAnimations];
|
|
}
|
|
|
|
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
|
if (!dontLoadURLNow) {
|
|
[self loadAddress:nil event:nil];
|
|
}
|
|
|
|
UIToolbar *navBar = (UIToolbar *)[self.view viewWithTag:kNavBarTag];
|
|
|
|
|
|
[navBar setItems:addrItemsInactive animated:YES];
|
|
|
|
[UIView beginAnimations:nil context:NULL];
|
|
[_addressField setFrame:CGRectMake(kMargin, kSpacer*2.0 + kLabelHeight,
|
|
navBar.bounds.size.width - 2*kMargin, kAddressHeight)];
|
|
[UIView commitAnimations];
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Options Menu action sheet
|
|
|
|
- (void)openOptionsMenu {
|
|
[_optionsMenu showFromToolbar:_toolbar];
|
|
// }
|
|
}
|
|
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
|
|
if (actionSheet == _optionsMenu) {
|
|
if (buttonIndex == 0) {
|
|
////////////////////////////////////////////////////////
|
|
// Add To Bookmarks
|
|
////////////////////////////////////////////////////////
|
|
[self addCurrentAsBookmark];
|
|
} else if (buttonIndex == 1) {
|
|
[self showSettings];
|
|
} else if (buttonIndex == 2) {
|
|
[self loadURL:[NSURL URLWithString:@"https://github.com/shadowsocks/shadowsocks-iOS/blob/master/LICENSE"]];
|
|
} else {
|
|
// close
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void) showSettings {
|
|
ProxySettingsTableViewController *settingsController = [[ProxySettingsTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
|
|
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:settingsController];
|
|
// nav.navigationBar.tintColor = [UIColor blackColor];
|
|
nav.navigationBar.barStyle = UIBarStyleBlackOpaque;
|
|
[self presentModalViewController:nav animated:YES];
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Toolbar/navbar behavior
|
|
|
|
- (void)goForward {
|
|
[_myWebView goForward];
|
|
[self updateTitle:_myWebView];
|
|
[self updateAddress:[_myWebView request]];
|
|
[self updateButtons];
|
|
}
|
|
- (void)goBack {
|
|
[_myWebView goBack];
|
|
[self updateTitle:_myWebView];
|
|
[self updateAddress:[_myWebView request]];
|
|
[self updateButtons];
|
|
}
|
|
- (void)stopLoading {
|
|
[_myWebView stopLoading];
|
|
[self updateTitle:_myWebView];
|
|
if (!_addressField.isEditing) {
|
|
_addressField.text = _currentURL;
|
|
}
|
|
[self updateButtons];
|
|
}
|
|
- (void)reload {
|
|
[_myWebView reload];
|
|
[self updateButtons];
|
|
}
|
|
|
|
- (void)updateButtons
|
|
{
|
|
_forwardButton.enabled = _myWebView.canGoForward;
|
|
_backButton.enabled = _myWebView.canGoBack;
|
|
if (_myWebView.loading) {
|
|
_stopRefreshButton = nil;
|
|
_stopRefreshButton = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemStop
|
|
target:self
|
|
action:@selector(stopLoading)];
|
|
} else {
|
|
_stopRefreshButton = nil;
|
|
_stopRefreshButton = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
|
|
target:self
|
|
action:@selector(reload)];
|
|
}
|
|
_stopRefreshButton.enabled = YES;
|
|
NSMutableArray *items = [[NSMutableArray alloc] init];
|
|
UIBarButtonItem *space = [[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
|
|
target:nil
|
|
action:nil];
|
|
[items addObject:_backButton];
|
|
[items addObject:space];
|
|
[items addObject:_forwardButton];
|
|
[items addObject:space];
|
|
[items addObject:_toolButton];
|
|
[items addObject:space];
|
|
[items addObject:_bookmarkButton];
|
|
[items addObject:space];
|
|
[items addObject:_stopRefreshButton];
|
|
[_toolbar setItems:items animated:NO];
|
|
|
|
}
|
|
|
|
- (void)updateTitle:(UIWebView*)aWebView
|
|
{
|
|
NSString* pageTitle = [aWebView stringByEvaluatingJavaScriptFromString:@"document.title"];
|
|
_pageTitleLabel.text = pageTitle;
|
|
}
|
|
|
|
- (void)updateAddress:(NSURLRequest*)request {
|
|
NSURL* url = [request mainDocumentURL];
|
|
NSString* absoluteString;
|
|
|
|
if ((url != nil) && [[url scheme] isEqualToString:@"file"]) {
|
|
// Faked local URLs
|
|
if ([[url absoluteString] rangeOfString:@"startup.html"].location != NSNotFound) {
|
|
absoluteString = @"onionbrowser:start";
|
|
}
|
|
else if ([[url absoluteString] rangeOfString:@"about.html"].location != NSNotFound) {
|
|
absoluteString = @"onionbrowser:about";
|
|
} else {
|
|
absoluteString = @"";
|
|
}
|
|
} else {
|
|
// Regular ol' web URL.
|
|
absoluteString = [url absoluteString];
|
|
}
|
|
|
|
if (![absoluteString isEqualToString:_currentURL]){
|
|
_currentURL = absoluteString;
|
|
if (!_addressField.isEditing) {
|
|
_addressField.text = absoluteString;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)loadAddress:(id)sender event:(UIEvent *)event {
|
|
NSString* urlString = _addressField.text;
|
|
NSURL* url = [NSURL URLWithString:urlString];
|
|
if(!url.scheme)
|
|
{
|
|
NSString *absUrl = [NSString stringWithFormat:@"http://%@", urlString];
|
|
url = [NSURL URLWithString:absUrl];
|
|
}
|
|
_currentURL = [url absoluteString];
|
|
[self loadURL:url];
|
|
}
|
|
|
|
- (void) addCurrentAsBookmark {
|
|
if ((_currentURL != nil) && ![_currentURL isEqualToString:@""]) {
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
NSFetchRequest *request = [[NSFetchRequest alloc] init];
|
|
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bookmark" inManagedObjectContext:appDelegate.managedObjectContext];
|
|
[request setEntity:entity];
|
|
|
|
NSError *error = nil;
|
|
NSUInteger numBookmarks = [appDelegate.managedObjectContext countForFetchRequest:request error:&error];
|
|
if (error) {
|
|
// error state?
|
|
}
|
|
Bookmark *bookmark = (Bookmark *)[NSEntityDescription insertNewObjectForEntityForName:@"Bookmark" inManagedObjectContext:appDelegate.managedObjectContext];
|
|
|
|
NSString *pageTitle = [_myWebView stringByEvaluatingJavaScriptFromString:@"document.title"];
|
|
[bookmark setTitle:pageTitle];
|
|
[bookmark setUrl:_currentURL];
|
|
[bookmark setOrder:numBookmarks];
|
|
|
|
NSError *saveError = nil;
|
|
if (![appDelegate.managedObjectContext save:&saveError]) {
|
|
NSLog(@"Error saving bookmark: %@", saveError);
|
|
}
|
|
|
|
UIAlertView* alertView = [[UIAlertView alloc]
|
|
initWithTitle:@"Add Bookmark"
|
|
message:[NSString stringWithFormat:@"Added '%@' %@ to bookmarks.",
|
|
pageTitle, _currentURL]
|
|
delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
alertView.delegate = self;
|
|
[alertView show];
|
|
} else {
|
|
UIAlertView* alertView = [[UIAlertView alloc]
|
|
initWithTitle:@"Add Bookmark"
|
|
message:@"Can't bookmark a (local) page with no URL."
|
|
delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
alertView.delegate = self;
|
|
[alertView show];
|
|
}
|
|
}
|
|
|
|
-(void)showBookmarks {
|
|
BookmarkTableViewController *bookmarksVC = [[BookmarkTableViewController alloc] initWithStyle:UITableViewStylePlain];
|
|
UINavigationController *bookmarkNavController = [[UINavigationController alloc]
|
|
initWithRootViewController:bookmarksVC];
|
|
|
|
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
|
|
|
NSManagedObjectContext *context = [appDelegate managedObjectContext];
|
|
|
|
bookmarksVC.managedObjectContext = context;
|
|
|
|
[self presentModalViewController:bookmarkNavController animated:YES];
|
|
}
|
|
|
|
@end
|