Re-landing:
[WebKit-https.git] / Tools / MiniBrowser / mac / SettingsController.m
1 /*
2  * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "SettingsController.h"
27
28 #import "AppDelegate.h"
29 #import "BrowserWindowController.h"
30 #import <WebKit/WKPreferencesPrivate.h>
31
32 #if WK_API_ENABLED
33 #import <WebKit/_WKExperimentalFeature.h>
34 #endif
35
36 static NSString * const defaultURL = @"http://www.webkit.org/";
37 static NSString * const DefaultURLPreferenceKey = @"DefaultURL";
38
39 static NSString * const UseWebKit2ByDefaultPreferenceKey = @"UseWebKit2ByDefault";
40 static NSString * const LayerBordersVisiblePreferenceKey = @"LayerBordersVisible";
41 static NSString * const SimpleLineLayoutDebugBordersEnabledPreferenceKey = @"SimpleLineLayoutDebugBordersEnabled";
42 static NSString * const TiledScrollingIndicatorVisiblePreferenceKey = @"TiledScrollingIndicatorVisible";
43 static NSString * const ResourceUsageOverlayVisiblePreferenceKey = @"ResourceUsageOverlayVisible";
44 static NSString * const LoadsAllSiteIconsKey = @"LoadsAllSiteIcons";
45 static NSString * const UsesGameControllerFrameworkKey = @"UsesGameControllerFramework";
46 static NSString * const IncrementalRenderingSuppressedPreferenceKey = @"IncrementalRenderingSuppressed";
47 static NSString * const AcceleratedDrawingEnabledPreferenceKey = @"AcceleratedDrawingEnabled";
48 static NSString * const DisplayListDrawingEnabledPreferenceKey = @"DisplayListDrawingEnabled";
49 static NSString * const ResourceLoadStatisticsEnabledPreferenceKey = @"ResourceLoadStatisticsEnabled";
50
51 static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @"NonFastScrollableRegionOverlayVisible";
52 static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @"WheelEventHandlerRegionOverlayVisible";
53
54 static NSString * const UseTransparentWindowsPreferenceKey = @"UseTransparentWindows";
55 static NSString * const UsePaginatedModePreferenceKey = @"UsePaginatedMode";
56 static NSString * const EnableSubPixelCSSOMMetricsPreferenceKey = @"EnableSubPixelCSSOMMetrics";
57
58 static NSString * const VisualViewportEnabledPreferenceKey = @"VisualViewportEnabled";
59 static NSString * const LargeImageAsyncDecodingEnabledPreferenceKey = @"LargeImageAsyncDecodingEnabled";
60 static NSString * const AnimatedImageAsyncDecodingEnabledPreferenceKey = @"AnimatedImageAsyncDecodingEnabled";
61
62 // This default name intentionally overlaps with the key that WebKit2 checks when creating a view.
63 static NSString * const UseRemoteLayerTreeDrawingAreaPreferenceKey = @"WebKit2UseRemoteLayerTreeDrawingArea";
64
65 static NSString * const PerWindowWebProcessesDisabledKey = @"PerWindowWebProcessesDisabled";
66
67 typedef NS_ENUM(NSInteger, DebugOverylayMenuItemTag) {
68     NonFastScrollableRegionOverlayTag = 100,
69     WheelEventHandlerRegionOverlayTag,
70 #if WK_API_ENABLED
71     ExperimentalFeatureTag,
72 #endif
73 };
74
75 @implementation SettingsController
76
77 @synthesize menu=_menu;
78
79 + (instancetype)shared
80 {
81     static SettingsController *sharedSettingsController;
82     static dispatch_once_t onceToken;
83     dispatch_once(&onceToken, ^{
84         sharedSettingsController = [[super alloc] init];
85     });
86
87     return sharedSettingsController;
88 }
89
90 - (NSMenu *)menu
91 {
92     if (!_menu)
93         [self _populateMenu];
94
95     return _menu;
96 }
97
98 - (void)_addItemWithTitle:(NSString *)title action:(SEL)action indented:(BOOL)indented
99 {
100     NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""];
101     [item setTarget:self];
102     if (indented)
103         [item setIndentationLevel:1];
104     [_menu addItem:item];
105     [item release];
106 }
107
108 - (void)_addHeaderWithTitle:(NSString *)title
109 {
110     [_menu addItem:[NSMenuItem separatorItem]];
111     [_menu addItem:[[[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""] autorelease]];
112 }
113
114 - (void)_populateMenu
115 {
116     _menu = [[NSMenu alloc] initWithTitle:@"Settings"];
117
118     [self _addItemWithTitle:@"Use WebKit2 By Default" action:@selector(toggleUseWebKit2ByDefault:) indented:NO];
119     [self _addItemWithTitle:@"Set Default URL to Current URL" action:@selector(setDefaultURLToCurrentURL:) indented:NO];
120
121     [_menu addItem:[NSMenuItem separatorItem]];
122
123     [self _addItemWithTitle:@"Use Transparent Windows" action:@selector(toggleUseTransparentWindows:) indented:NO];
124     [self _addItemWithTitle:@"Use Paginated Mode" action:@selector(toggleUsePaginatedMode:) indented:NO];
125     [self _addItemWithTitle:@"Show Layer Borders" action:@selector(toggleShowLayerBorders:) indented:NO];
126     [self _addItemWithTitle:@"Show Simple Line Layout Borders" action:@selector(toggleSimpleLineLayoutDebugBordersEnabled:) indented:NO];
127     [self _addItemWithTitle:@"Suppress Incremental Rendering in New Windows" action:@selector(toggleIncrementalRenderingSuppressed:) indented:NO];
128     [self _addItemWithTitle:@"Enable Accelerated Drawing" action:@selector(toggleAcceleratedDrawingEnabled:) indented:NO];
129     [self _addItemWithTitle:@"Enable Display List Drawing" action:@selector(toggleDisplayListDrawingEnabled:) indented:NO];
130     [self _addItemWithTitle:@"Enable Visual Viewport" action:@selector(toggleVisualViewportEnabled:) indented:NO];
131     [self _addItemWithTitle:@"Enable Resource Load Statistics" action:@selector(toggleResourceLoadStatisticsEnabled:) indented:NO];
132     [self _addItemWithTitle:@"Enable Large Image Async Decoding" action:@selector(toggleLargeImageAsyncDecodingEnabled:) indented:NO];
133     [self _addItemWithTitle:@"Enable Animated Image Async Decoding" action:@selector(toggleAnimatedImageAsyncDecodingEnabled:) indented:NO];
134
135     [self _addHeaderWithTitle:@"WebKit2-only Settings"];
136
137     [self _addItemWithTitle:@"Show Tiled Scrolling Indicator" action:@selector(toggleShowTiledScrollingIndicator:) indented:YES];
138     [self _addItemWithTitle:@"Use UI-Side Compositing" action:@selector(toggleUseUISideCompositing:) indented:YES];
139     [self _addItemWithTitle:@"Disable Per-Window Web Processes" action:@selector(togglePerWindowWebProcessesDisabled:) indented:YES];
140     [self _addItemWithTitle:@"Show Resource Usage Overlay" action:@selector(toggleShowResourceUsageOverlay:) indented:YES];
141     [self _addItemWithTitle:@"Load All Site Icons Per-Page" action:@selector(toggleLoadsAllSiteIcons:) indented:YES];
142     [self _addItemWithTitle:@"Use GameController.framework on macOS (Restart required)" action:@selector(toggleUsesGameControllerFramework:) indented:YES];
143
144     NSMenuItem *debugOverlaysSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Debug Overlays" action:nil keyEquivalent:@""];
145     NSMenu *debugOverlaysMenu = [[NSMenu alloc] initWithTitle:@"Debug Overlays"];
146     [debugOverlaysSubmenuItem setSubmenu:debugOverlaysMenu];
147
148     NSMenuItem *nonFastScrollableRegionItem = [[NSMenuItem alloc] initWithTitle:@"Non-fast Scrollable Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
149     [nonFastScrollableRegionItem setTag:NonFastScrollableRegionOverlayTag];
150     [nonFastScrollableRegionItem setTarget:self];
151     [debugOverlaysMenu addItem:[nonFastScrollableRegionItem autorelease]];
152
153     NSMenuItem *wheelEventHandlerRegionItem = [[NSMenuItem alloc] initWithTitle:@"Wheel Event Handler Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
154     [wheelEventHandlerRegionItem setTag:WheelEventHandlerRegionOverlayTag];
155     [wheelEventHandlerRegionItem setTarget:self];
156     [debugOverlaysMenu addItem:[wheelEventHandlerRegionItem autorelease]];
157     [debugOverlaysMenu release];
158     
159     [_menu addItem:debugOverlaysSubmenuItem];
160     [debugOverlaysSubmenuItem release];
161
162 #if WK_API_ENABLED
163     NSMenuItem *experimentalFeaturesSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Experimental Features" action:nil keyEquivalent:@""];
164     NSMenu *experimentalFeaturesMenu = [[NSMenu alloc] initWithTitle:@"Experimental Features"];
165     [experimentalFeaturesSubmenuItem setSubmenu:experimentalFeaturesMenu];
166
167     NSArray<_WKExperimentalFeature *> *features = [WKPreferences _experimentalFeatures];
168
169     for (_WKExperimentalFeature *feature in features) {
170         NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:feature.name action:@selector(toggleExperimentalFeature:) keyEquivalent:@""];
171         item.representedObject = feature;
172
173         [item setTag:ExperimentalFeatureTag];
174         [item setTarget:self];
175         [experimentalFeaturesMenu addItem:[item autorelease]];
176     }
177
178     [_menu addItem:experimentalFeaturesSubmenuItem];
179     [experimentalFeaturesSubmenuItem release];
180 #endif // WK_API_ENABLED
181
182     [self _addHeaderWithTitle:@"WebKit1-only Settings"];
183     [self _addItemWithTitle:@"Enable Subpixel CSSOM Metrics" action:@selector(toggleEnableSubPixelCSSOMMetrics:) indented:YES];
184 }
185
186 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
187 {
188     SEL action = [menuItem action];
189
190     if (action == @selector(toggleUseWebKit2ByDefault:))
191         [menuItem setState:[self useWebKit2ByDefault] ? NSOnState : NSOffState];
192     else if (action == @selector(toggleUseTransparentWindows:))
193         [menuItem setState:[self useTransparentWindows] ? NSOnState : NSOffState];
194     else if (action == @selector(toggleUsePaginatedMode:))
195         [menuItem setState:[self usePaginatedMode] ? NSOnState : NSOffState];
196     else if (action == @selector(toggleShowLayerBorders:))
197         [menuItem setState:[self layerBordersVisible] ? NSOnState : NSOffState];
198     else if (action == @selector(toggleSimpleLineLayoutDebugBordersEnabled:))
199         [menuItem setState:[self simpleLineLayoutDebugBordersEnabled] ? NSOnState : NSOffState];
200     else if (action == @selector(toggleIncrementalRenderingSuppressed:))
201         [menuItem setState:[self incrementalRenderingSuppressed] ? NSOnState : NSOffState];
202     else if (action == @selector(toggleAcceleratedDrawingEnabled:))
203         [menuItem setState:[self acceleratedDrawingEnabled] ? NSOnState : NSOffState];
204     else if (action == @selector(toggleDisplayListDrawingEnabled:))
205         [menuItem setState:[self displayListDrawingEnabled] ? NSOnState : NSOffState];
206     else if (action == @selector(toggleResourceLoadStatisticsEnabled:))
207         [menuItem setState:[self resourceLoadStatisticsEnabled] ? NSOnState : NSOffState];
208     else if (action == @selector(toggleLargeImageAsyncDecodingEnabled:))
209         [menuItem setState:[self largeImageAsyncDecodingEnabled] ? NSOnState : NSOffState];
210     else if (action == @selector(toggleAnimatedImageAsyncDecodingEnabled:))
211         [menuItem setState:[self animatedImageAsyncDecodingEnabled] ? NSOnState : NSOffState];
212     else if (action == @selector(toggleVisualViewportEnabled:))
213         [menuItem setState:[self visualViewportEnabled] ? NSOnState : NSOffState];
214     else if (action == @selector(toggleShowTiledScrollingIndicator:))
215         [menuItem setState:[self tiledScrollingIndicatorVisible] ? NSOnState : NSOffState];
216     else if (action == @selector(toggleShowResourceUsageOverlay:))
217         [menuItem setState:[self resourceUsageOverlayVisible] ? NSOnState : NSOffState];
218     else if (action == @selector(toggleLoadsAllSiteIcons:))
219         [menuItem setState:[self loadsAllSiteIcons] ? NSOnState : NSOffState];
220     else if (action == @selector(toggleUsesGameControllerFramework:))
221         [menuItem setState:[self usesGameControllerFramework] ? NSOnState : NSOffState];
222     else if (action == @selector(toggleUseUISideCompositing:))
223         [menuItem setState:[self useUISideCompositing] ? NSOnState : NSOffState];
224     else if (action == @selector(togglePerWindowWebProcessesDisabled:))
225         [menuItem setState:[self perWindowWebProcessesDisabled] ? NSOnState : NSOffState];
226     else if (action == @selector(toggleEnableSubPixelCSSOMMetrics:))
227         [menuItem setState:[self subPixelCSSOMMetricsEnabled] ? NSOnState : NSOffState];
228     else if (action == @selector(toggleDebugOverlay:))
229         [menuItem setState:[self debugOverlayVisible:menuItem] ? NSOnState : NSOffState];
230
231 #if WK_API_ENABLED
232     if (menuItem.tag == ExperimentalFeatureTag) {
233         _WKExperimentalFeature *feature = menuItem.representedObject;
234         [menuItem setState:[defaultPreferences() _isEnabledForFeature:feature] ? NSOnState : NSOffState];
235     }
236 #endif
237
238     return YES;
239 }
240
241 - (void)_toggleBooleanDefault:(NSString *)defaultName
242 {
243     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
244     [defaults setBool:![defaults boolForKey:defaultName] forKey:defaultName];
245
246     [(BrowserAppDelegate *)[[NSApplication sharedApplication] delegate] didChangeSettings];
247 }
248
249 - (void)toggleUseWebKit2ByDefault:(id)sender
250 {
251     [self _toggleBooleanDefault:UseWebKit2ByDefaultPreferenceKey];
252 }
253
254 - (BOOL)useWebKit2ByDefault
255 {
256     return [[NSUserDefaults standardUserDefaults] boolForKey:UseWebKit2ByDefaultPreferenceKey];
257 }
258
259 - (void)toggleUseTransparentWindows:(id)sender
260 {
261     [self _toggleBooleanDefault:UseTransparentWindowsPreferenceKey];
262 }
263
264 - (BOOL)useTransparentWindows
265 {
266     return [[NSUserDefaults standardUserDefaults] boolForKey:UseTransparentWindowsPreferenceKey];
267 }
268
269 - (void)toggleUsePaginatedMode:(id)sender
270 {
271     [self _toggleBooleanDefault:UsePaginatedModePreferenceKey];
272 }
273
274 - (BOOL)usePaginatedMode
275 {
276     return [[NSUserDefaults standardUserDefaults] boolForKey:UsePaginatedModePreferenceKey];
277 }
278
279 - (void)toggleUseUISideCompositing:(id)sender
280 {
281     [self _toggleBooleanDefault:UseRemoteLayerTreeDrawingAreaPreferenceKey];
282 }
283
284 - (BOOL)useUISideCompositing
285 {
286     return [[NSUserDefaults standardUserDefaults] boolForKey:UseRemoteLayerTreeDrawingAreaPreferenceKey];
287 }
288
289 - (void)togglePerWindowWebProcessesDisabled:(id)sender
290 {
291     NSAlert *alert = [[NSAlert alloc] init];
292     [alert setMessageText:self.perWindowWebProcessesDisabled ? @"Are you sure you want to switch to per-window web processes?" : @"Are you sure you want to switch to a single web process?"];
293     [alert setInformativeText:@"This requires quitting and relaunching MiniBrowser. I'll do the quitting. You will have to do the relaunching."];
294     [alert addButtonWithTitle:@"Switch and Quit"];
295     [alert addButtonWithTitle:@"Cancel"];
296
297     if ([alert runModal] != NSAlertFirstButtonReturn)
298         return;
299
300     [self _toggleBooleanDefault:PerWindowWebProcessesDisabledKey];
301     [NSApp terminate:self];
302 }
303
304 - (BOOL)perWindowWebProcessesDisabled
305 {
306     return [[NSUserDefaults standardUserDefaults] boolForKey:PerWindowWebProcessesDisabledKey];
307 }
308
309 - (void)toggleIncrementalRenderingSuppressed:(id)sender
310 {
311     [self _toggleBooleanDefault:IncrementalRenderingSuppressedPreferenceKey];
312 }
313
314 - (BOOL)incrementalRenderingSuppressed
315 {
316     return [[NSUserDefaults standardUserDefaults] boolForKey:IncrementalRenderingSuppressedPreferenceKey];
317 }
318
319 - (void)toggleShowLayerBorders:(id)sender
320 {
321     [self _toggleBooleanDefault:LayerBordersVisiblePreferenceKey];
322 }
323
324 - (BOOL)layerBordersVisible
325 {
326     return [[NSUserDefaults standardUserDefaults] boolForKey:LayerBordersVisiblePreferenceKey];
327 }
328
329 - (void)toggleSimpleLineLayoutDebugBordersEnabled:(id)sender
330 {
331     [self _toggleBooleanDefault:SimpleLineLayoutDebugBordersEnabledPreferenceKey];
332 }
333
334 - (BOOL)simpleLineLayoutDebugBordersEnabled
335 {
336     return [[NSUserDefaults standardUserDefaults] boolForKey:SimpleLineLayoutDebugBordersEnabledPreferenceKey];
337 }
338
339 - (void)toggleAcceleratedDrawingEnabled:(id)sender
340 {
341     [self _toggleBooleanDefault:AcceleratedDrawingEnabledPreferenceKey];
342 }
343
344 - (BOOL)acceleratedDrawingEnabled
345 {
346     return [[NSUserDefaults standardUserDefaults] boolForKey:AcceleratedDrawingEnabledPreferenceKey];
347 }
348
349 - (void)toggleDisplayListDrawingEnabled:(id)sender
350 {
351     [self _toggleBooleanDefault:DisplayListDrawingEnabledPreferenceKey];
352 }
353
354 - (BOOL)displayListDrawingEnabled
355 {
356     return [[NSUserDefaults standardUserDefaults] boolForKey:DisplayListDrawingEnabledPreferenceKey];
357 }
358
359 - (void)toggleShowTiledScrollingIndicator:(id)sender
360 {
361     [self _toggleBooleanDefault:TiledScrollingIndicatorVisiblePreferenceKey];
362 }
363
364 - (void)toggleShowResourceUsageOverlay:(id)sender
365 {
366     [self _toggleBooleanDefault:ResourceUsageOverlayVisiblePreferenceKey];
367 }
368
369 - (BOOL)loadsAllSiteIcons
370 {
371     return [[NSUserDefaults standardUserDefaults] boolForKey:LoadsAllSiteIconsKey];
372 }
373
374 - (void)toggleLoadsAllSiteIcons:(id)sender
375 {
376     [self _toggleBooleanDefault:LoadsAllSiteIconsKey];
377 }
378
379 - (BOOL)usesGameControllerFramework
380 {
381     return [[NSUserDefaults standardUserDefaults] boolForKey:UsesGameControllerFrameworkKey];
382 }
383
384 - (void)toggleUsesGameControllerFramework:(id)sender
385 {
386     [self _toggleBooleanDefault:UsesGameControllerFrameworkKey];
387 }
388
389 - (BOOL)tiledScrollingIndicatorVisible
390 {
391     return [[NSUserDefaults standardUserDefaults] boolForKey:TiledScrollingIndicatorVisiblePreferenceKey];
392 }
393
394 - (BOOL)resourceUsageOverlayVisible
395 {
396     return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceUsageOverlayVisiblePreferenceKey];
397 }
398
399 - (void)toggleResourceLoadStatisticsEnabled:(id)sender
400 {
401     [self _toggleBooleanDefault:ResourceLoadStatisticsEnabledPreferenceKey];
402 }
403
404 - (BOOL)visualViewportEnabled
405 {
406     return [[NSUserDefaults standardUserDefaults] boolForKey:VisualViewportEnabledPreferenceKey];
407 }
408
409 - (void)toggleVisualViewportEnabled:(id)sender
410 {
411     [self _toggleBooleanDefault:VisualViewportEnabledPreferenceKey];
412 }
413
414 - (BOOL)resourceLoadStatisticsEnabled
415 {
416     return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceLoadStatisticsEnabledPreferenceKey];
417 }
418
419 - (void)toggleLargeImageAsyncDecodingEnabled:(id)sender
420 {
421     [self _toggleBooleanDefault:LargeImageAsyncDecodingEnabledPreferenceKey];
422 }
423
424 - (BOOL)largeImageAsyncDecodingEnabled
425 {
426     return [[NSUserDefaults standardUserDefaults] boolForKey:LargeImageAsyncDecodingEnabledPreferenceKey];
427 }
428
429 - (void)toggleAnimatedImageAsyncDecodingEnabled:(id)sender
430 {
431     [self _toggleBooleanDefault:AnimatedImageAsyncDecodingEnabledPreferenceKey];
432 }
433
434 - (BOOL)animatedImageAsyncDecodingEnabled
435 {
436     return [[NSUserDefaults standardUserDefaults] boolForKey:AnimatedImageAsyncDecodingEnabledPreferenceKey];
437 }
438
439 - (void)toggleEnableSubPixelCSSOMMetrics:(id)sender
440 {
441     [self _toggleBooleanDefault:EnableSubPixelCSSOMMetricsPreferenceKey];
442 }
443
444 - (BOOL)subPixelCSSOMMetricsEnabled
445 {
446     return [[NSUserDefaults standardUserDefaults] boolForKey:EnableSubPixelCSSOMMetricsPreferenceKey];
447 }
448
449 - (BOOL)nonFastScrollableRegionOverlayVisible
450 {
451     return [[NSUserDefaults standardUserDefaults] boolForKey:NonFastScrollableRegionOverlayVisiblePreferenceKey];
452 }
453
454 - (BOOL)wheelEventHandlerRegionOverlayVisible
455 {
456     return [[NSUserDefaults standardUserDefaults] boolForKey:WheelEventHandlerRegionOverlayVisiblePreferenceKey];
457 }
458
459 - (NSString *)preferenceKeyForRegionOverlayTag:(NSUInteger)tag
460 {
461     switch (tag) {
462     case NonFastScrollableRegionOverlayTag:
463         return NonFastScrollableRegionOverlayVisiblePreferenceKey;
464
465     case WheelEventHandlerRegionOverlayTag:
466         return WheelEventHandlerRegionOverlayVisiblePreferenceKey;
467     }
468     return nil;
469 }
470
471 - (void)toggleDebugOverlay:(id)sender
472 {
473     NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[sender tag]];
474     if (preferenceKey)
475         [self _toggleBooleanDefault:preferenceKey];
476 }
477
478 #if WK_API_ENABLED
479 - (void)toggleExperimentalFeature:(id)sender
480 {
481     _WKExperimentalFeature *feature = ((NSMenuItem *)sender).representedObject;
482     WKPreferences *preferences = defaultPreferences();
483
484     BOOL currentlyEnabled = [preferences _isEnabledForFeature:feature];
485     [preferences _setEnabled:!currentlyEnabled forFeature:feature];
486
487     [[NSUserDefaults standardUserDefaults] setBool:!currentlyEnabled forKey:feature.key];
488 }
489 #endif
490
491 - (BOOL)debugOverlayVisible:(NSMenuItem *)menuItem
492 {
493     NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[menuItem tag]];
494     if (preferenceKey)
495         return [[NSUserDefaults standardUserDefaults] boolForKey:preferenceKey];
496
497     return NO;
498 }
499
500 - (NSString *)defaultURL
501 {
502     NSString *customDefaultURL = [[NSUserDefaults standardUserDefaults] stringForKey:DefaultURLPreferenceKey];
503     if (customDefaultURL)
504         return customDefaultURL;
505     return defaultURL;
506 }
507
508 - (void)setDefaultURLToCurrentURL:(id)sender
509 {
510     NSWindowController *windowController = [[NSApp keyWindow] windowController];
511     NSString *customDefaultURL = nil;
512
513     if ([windowController isKindOfClass:[BrowserWindowController class]])
514         customDefaultURL = [[(BrowserWindowController *)windowController currentURL] absoluteString];
515
516     if (customDefaultURL)
517         [[NSUserDefaults standardUserDefaults] setObject:customDefaultURL forKey:DefaultURLPreferenceKey];
518 }
519
520 @end