iOS web browser with a focus on security and privacy
1/*
2 * Endless
3 * Copyright (c) 2014-2015 joshua stein <jcs@jcs.org>
4 *
5 * See LICENSE file for redistribution terms.
6 */
7
8#import "AppDelegate.h"
9#import "Bookmark.h"
10#import "CookieController.h"
11#import "HostSettings.h"
12#import "HostSettingsController.h"
13#import "IASKAppSettingsViewController.h"
14#import "HTTPSEverywhereRuleController.h"
15#import "WebViewMenuController.h"
16
17#import "OnePasswordExtension.h"
18#import "TUSafariActivity.h"
19
20#ifdef SHOW_DONATION_CONTROLLER
21#include "DonationViewController.h"
22#endif
23
24@implementation WebViewMenuController {
25 AppDelegate *appDelegate;
26 IASKAppSettingsViewController *appSettingsViewController;
27 NSMutableArray *buttons;
28}
29
30NSString * const FUNC = @"F";
31NSString * const LABEL = @"L";
32
33- (void)viewDidLoad
34{
35 [super viewDidLoad];
36
37 appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
38
39 buttons = [[NSMutableArray alloc] initWithCapacity:10];
40
41 [buttons addObject:@{ FUNC : @"menuRefresh", LABEL : @"Refresh" }];
42
43 /* no point in showing this if the user doesn't have 1p installed */
44 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"onepassword://"]])
45 [buttons addObject:@{ FUNC : @"menuOnePassword", LABEL : @"Fill with 1Password" }];
46
47 [buttons addObject:@{ FUNC : @"menuAddOrManageBookmarks", LABEL : @"Manage Bookmarks" }];
48 [buttons addObject:@{ FUNC : @"menuShare", LABEL : @"Share URL" }];
49 [buttons addObject:@{ FUNC : @"menuHTTPSEverywhere", LABEL : @"HTTPS Everywhere" }];
50 [buttons addObject:@{ FUNC : @"menuHostSettings", LABEL : @"Host Settings" }];
51 [buttons addObject:@{ FUNC : @"menuSettings", LABEL : @"Global Settings" }];
52
53 [self.view setBackgroundColor:[UIColor clearColor]];
54 [self.tableView setSeparatorInset:UIEdgeInsetsZero];
55
56 if ([[appDelegate webViewController] darkInterface])
57 [self.tableView setSeparatorColor:[UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.75]];
58}
59
60- (CGSize)preferredContentSize
61{
62 return CGSizeMake(160, [self tableView:self.tableView heightForRowAtIndexPath:[[NSIndexPath alloc] init]] * [buttons count]);
63}
64
65#pragma mark - Table view data source
66
67- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
68{
69 return [buttons count];
70}
71
72-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
73{
74 if ([cell respondsToSelector:@selector(setSeparatorInset:)])
75 [cell setSeparatorInset:UIEdgeInsetsZero];
76
77 if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
78 [cell setPreservesSuperviewLayoutMargins:NO];
79
80 if ([cell respondsToSelector:@selector(setLayoutMargins:)])
81 [cell setLayoutMargins:UIEdgeInsetsZero];
82}
83
84- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
85{
86 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"button"];
87 if (cell == nil)
88 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"button"];
89
90 NSDictionary *button = [buttons objectAtIndex:[indexPath row]];
91
92 cell.backgroundColor = [UIColor clearColor];
93 cell.textLabel.font = [UIFont systemFontOfSize:13];
94 cell.textLabel.text = [button objectForKey:LABEL];
95 cell.detailTextLabel.text = nil;
96 cell.detailTextLabel.font = [UIFont systemFontOfSize:11];
97
98 if ([[appDelegate webViewController] darkInterface]) {
99 cell.textLabel.textColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
100 cell.detailTextLabel.textColor = [UIColor grayColor];
101 }
102
103 BOOL haveURL = ([[[appDelegate webViewController] curWebViewTab] url] != nil);
104
105 NSString *func = [button objectForKey:FUNC];
106 if ([func isEqualToString:@"menuAddOrManageBookmarks"]) {
107 if (haveURL && [Bookmark isURLBookmarked:[[[appDelegate webViewController] curWebViewTab] url]]) {
108 cell.textLabel.text = @"Bookmarks";
109 cell.detailTextLabel.text = @"Page bookmarked";
110 }
111 }
112 else if ([func isEqualToString:@"menuOnePassword"] || [func isEqualToString:@"menuRefresh"] || [func isEqualToString:@"menuShare"]) {
113 cell.userInteractionEnabled = haveURL;
114 cell.textLabel.enabled = haveURL;
115 }
116 else if ([func isEqualToString:@"menuHTTPSEverywhere"] && haveURL) {
117 long ruleCount = [[[[appDelegate webViewController] curWebViewTab] applicableHTTPSEverywhereRules] count];
118
119 if (ruleCount > 0) {
120 cell.detailTextLabel.text = [NSString stringWithFormat:@"%ld rule%@ in use", ruleCount, (ruleCount == 1 ? @"" : @"s")];
121 cell.detailTextLabel.textColor = [self colorForMenuTextHighlight];
122 }
123 }
124 else if ([func isEqualToString:@"menuHostSettings"]) {
125 HostSettings *hs = [HostSettings settingsOrDefaultsForHost:[[[[appDelegate webViewController] curWebViewTab] url] host]];
126 if (hs && ![hs isDefault]) {
127 cell.detailTextLabel.text = @"Custom settings";
128 cell.detailTextLabel.textColor = [self colorForMenuTextHighlight];
129 }
130 else {
131 cell.detailTextLabel.text = @"Using defaults";
132 cell.detailTextLabel.textColor = [UIColor grayColor];
133 }
134 }
135
136 return cell;
137}
138
139- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
140{
141 return 35;
142}
143
144- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
145{
146 return NO;
147}
148
149- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
150{
151 return NO;
152}
153
154- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
155{
156 [[appDelegate webViewController] dismissPopover];
157 NSDictionary *button = [buttons objectAtIndex:[indexPath row]];
158
159 SEL action = NSSelectorFromString([button objectForKey:FUNC]);
160
161 if ([self respondsToSelector:action])
162 [self performSelector:action];
163 else
164 NSLog(@"can't call %@", NSStringFromSelector(action));
165}
166
167
168/* individual menu item functions */
169
170
171- (void)menuRefresh
172{
173 [[appDelegate webViewController] forceRefresh];
174}
175
176- (void)menuOnePassword
177{
178 [[OnePasswordExtension sharedExtension] fillItemIntoWebView:[[[appDelegate webViewController] curWebViewTab] webView] forViewController:[appDelegate webViewController] sender:[[appDelegate webViewController] settingsButton] showOnlyLogins:NO completion:^(BOOL success, NSError *error) {
179 if (!success)
180 NSLog(@"[OnePasswordExtension] failed to fill into webview: %@", error);
181 }];
182}
183
184- (void)menuHTTPSEverywhere
185{
186 HTTPSEverywhereRuleController *herc = [[HTTPSEverywhereRuleController alloc] init];
187 UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:herc];
188 [[appDelegate webViewController] presentViewController:navController animated:YES completion:nil];
189}
190
191- (void)menuHostSettings
192{
193 HostSettingsController *hsc = [[HostSettingsController alloc] init];
194 UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:hsc];
195 [[appDelegate webViewController] presentViewController:navController animated:YES completion:nil];
196
197 /* if we have custom settings, skip directly to them */
198 HostSettings *hs = [HostSettings settingsOrDefaultsForHost:[[[[appDelegate webViewController] curWebViewTab] url] host]];
199 if (hs && ![hs isDefault])
200 [hsc showDetailsForHost:[hs hostname]];
201}
202
203- (void)menuAddOrManageBookmarks
204{
205 [[appDelegate webViewController] showBookmarksForEditing:YES];
206}
207
208- (void)menuSettings
209{
210 if (!appSettingsViewController) {
211 appSettingsViewController = [[IASKAppSettingsViewController alloc] init];
212 appSettingsViewController.delegate = [appDelegate webViewController];
213 appSettingsViewController.showDoneButton = YES;
214 appSettingsViewController.showCreditsFooter = NO;
215
216#ifdef SHOW_DONATION_CONTROLLER
217 if (![DonationViewController canMakeDonation])
218 [appSettingsViewController setHiddenKeys:[NSSet setWithArray:@[ @"open_donation" ]]];
219#else
220 [appSettingsViewController setHiddenKeys:[NSSet setWithArray:@[ @"open_donation" ]]];
221#endif
222 }
223
224 UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:appSettingsViewController];
225 [[appDelegate webViewController] presentViewController:navController animated:YES completion:nil];
226}
227
228- (void)menuShare
229{
230 TUSafariActivity *activity = [[TUSafariActivity alloc] init];
231 UIActivityViewController *avc = [[UIActivityViewController alloc] initWithActivityItems:@[ [[[appDelegate webViewController] curWebViewTab] url] ] applicationActivities:@[ activity ]];
232
233 UIPopoverPresentationController *popover = [avc popoverPresentationController];
234 if (popover) {
235 popover.sourceView = [[appDelegate webViewController] settingsButton];
236 popover.sourceRect = CGRectMake(1, popover.sourceView.frame.size.height / 2, 1, 1);
237 popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
238 }
239
240 [[appDelegate webViewController] presentViewController:avc animated:YES completion:nil];
241}
242
243- (UIColor *)colorForMenuTextHighlight
244{
245 if ([[appDelegate webViewController] darkInterface])
246 return [UIColor yellowColor];
247 else
248 return [UIColor colorWithRed:0 green:0.5 blue:0 alpha:1];
249}
250
251@end