16330432e6a3189921127022bf40a1c61c05b3d1
[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 UsesGameControllerFrameworkKey = @"UsesGameControllerFramework";
45 static NSString * const IncrementalRenderingSuppressedPreferenceKey = @"IncrementalRenderingSuppressed";
46 static NSString * const AcceleratedDrawingEnabledPreferenceKey = @"AcceleratedDrawingEnabled";
47 static NSString * const DisplayListDrawingEnabledPreferenceKey = @"DisplayListDrawingEnabled";
48 static NSString * const ResourceLoadStatisticsEnabledPreferenceKey = @"ResourceLoadStatisticsEnabled";
49
50 static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @"NonFastScrollableRegionOverlayVisible";
51 static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @"WheelEventHandlerRegionOverlayVisible";
52
53 static NSString * const UseTransparentWindowsPreferenceKey = @"UseTransparentWindows";
54 static NSString * const UsePaginatedModePreferenceKey = @"UsePaginatedMode";
55 static NSString * const EnableSubPixelCSSOMMetricsPreferenceKey = @"EnableSubPixelCSSOMMetrics";
56
57 static NSString * const VisualViewportEnabledPreferenceKey = @"VisualViewportEnabled";
58 static NSString * const LargeImageAsyncDecodingEnabledPreferenceKey = @"LargeImageAsyncDecodingEnabled";
59 static NSString * const AnimatedImageAsyncDecodingEnabledPreferenceKey = @"AnimatedImageAsyncDecodingEnabled";
60
61 // This default name intentionally overlaps with the key that WebKit2 checks when creating a view.
62 static NSString * const UseRemoteLayerTreeDrawingAreaPreferenceKey = @"WebKit2UseRemoteLayerTreeDrawingArea";
63
64 static NSString * const PerWindowWebProcessesDisabledKey = @"PerWindowWebProcessesDisabled";
65
66 typedef NS_ENUM(NSInteger, DebugOverylayMenuItemTag) {
67     NonFastScrollableRegionOverlayTag = 100,
68     WheelEventHandlerRegionOverlayTag,
69 #if WK_API_ENABLED
70     ExperimentalFeatureTag,
71 #endif
72 };
73
74 @implementation SettingsController
75
76 @synthesize menu=_menu;
77
78 + (instancetype)shared
79 {
80     static SettingsController *sharedSettingsController;
81     static dispatch_once_t onceToken;
82     dispatch_once(&onceToken, ^{
83         sharedSettingsController = [[super alloc] init];
84     });
85
86     return sharedSettingsController;
87 }
88
89 - (NSMenu *)menu
90 {
91     if (!_menu)
92         [self _populateMenu];
93
94     return _menu;
95 }
96
97 - (void)_addItemWithTitle:(NSString *)title action:(SEL)action indented:(BOOL)indented
98 {
99     NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""];
100     [item setTarget:self];
101     if (indented)
102         [item setIndentationLevel:1];
103     [_menu addItem:item];
104     [item release];
105 }
106
107 - (void)_addHeaderWithTitle:(NSString *)title
108 {
109     [_menu addItem:[NSMenuItem separatorItem]];
110     [_menu addItem:[[[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""] autorelease]];
111 }
112
113 - (void)_populateMenu
114 {
115     _menu = [[NSMenu alloc] initWithTitle:@"Settings"];
116
117     [self _addItemWithTitle:@"Use WebKit2 By Default" action:@selector(toggleUseWebKit2ByDefault:) indented:NO];
118     [self _addItemWithTitle:@"Set Default URL to Current URL" action:@selector(setDefaultURLToCurrentURL:) indented:NO];
119
120     [_menu addItem:[NSMenuItem separatorItem]];
121
122     [self _addItemWithTitle:@"Use Transparent Windows" action:@selector(toggleUseTransparentWindows:) indented:NO];
123     [self _addItemWithTitle:@"Use Paginated Mode" action:@selector(toggleUsePaginatedMode:) indented:NO];
124     [self _addItemWithTitle:@"Show Layer Borders" action:@selector(toggleShowLayerBorders:) indented:NO];
125     [self _addItemWithTitle:@"Show Simple Line Layout Borders" action:@selector(toggleSimpleLineLayoutDebugBordersEnabled:) indented:NO];
126     [self _addItemWithTitle:@"Suppress Incremental Rendering in New Windows" action:@selector(toggleIncrementalRenderingSuppressed:) indented:NO];
127     [self _addItemWithTitle:@"Enable Accelerated Drawing" action:@selector(toggleAcceleratedDrawingEnabled:) indented:NO];
128     [self _addItemWithTitle:@"Enable Display List Drawing" action:@selector(toggleDisplayListDrawingEnabled:) indented:NO];
129     [self _addItemWithTitle:@"Enable Visual Viewport" action:@selector(toggleVisualViewportEnabled:) indented:NO];
130     [self _addItemWithTitle:@"Enable Resource Load Statistics" action:@selector(toggleResourceLoadStatisticsEnabled:) indented:NO];
131     [self _addItemWithTitle:@"Enable Large Image Async Decoding" action:@selector(toggleLargeImageAsyncDecodingEnabled:) indented:NO];
132     [self _addItemWithTitle:@"Enable Animated Image Async Decoding" action:@selector(toggleAnimatedImageAsyncDecodingEnabled:) indented:NO];
133
134     [self _addHeaderWithTitle:@"WebKit2-only Settings"];
135
136     [self _addItemWithTitle:@"Show Tiled Scrolling Indicator" action:@selector(toggleShowTiledScrollingIndicator:) indented:YES];
137     [self _addItemWithTitle:@"Use UI-Side Compositing" action:@selector(toggleUseUISideCompositing:) indented:YES];
138     [self _addItemWithTitle:@"Disable Per-Window Web Processes" action:@selector(togglePerWindowWebProcessesDisabled:) indented:YES];
139     [self _addItemWithTitle:@"Show Resource Usage Overlay" action:@selector(toggleShowResourceUsageOverlay:) indented:YES];
140     [self _addItemWithTitle:@"Use GameController.framework on macOS (Restart required)" action:@selector(toggleUsesGameControllerFramework:) indented:YES];
141
142     NSMenuItem *debugOverlaysSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Debug Overlays" action:nil keyEquivalent:@""];
143     NSMenu *debugOverlaysMenu = [[NSMenu alloc] initWithTitle:@"Debug Overlays"];
144     [debugOverlaysSubmenuItem setSubmenu:debugOverlaysMenu];
145
146     NSMenuItem *nonFastScrollableRegionItem = [[NSMenuItem alloc] initWithTitle:@"Non-fast Scrollable Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
147     [nonFastScrollableRegionItem setTag:NonFastScrollableRegionOverlayTag];
148     [nonFastScrollableRegionItem setTarget:self];
149     [debugOverlaysMenu addItem:[nonFastScrollableRegionItem autorelease]];
150
151     NSMenuItem *wheelEventHandlerRegionItem = [[NSMenuItem alloc] initWithTitle:@"Wheel Event Handler Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
152     [wheelEventHandlerRegionItem setTag:WheelEventHandlerRegionOverlayTag];
153     [wheelEventHandlerRegionItem setTarget:self];
154     [debugOverlaysMenu addItem:[wheelEventHandlerRegionItem autorelease]];
155     [debugOverlaysMenu release];
156     
157     [_menu addItem:debugOverlaysSubmenuItem];
158     [debugOverlaysSubmenuItem release];
159
160 #if WK_API_ENABLED
161     NSMenuItem *experimentalFeaturesSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Experimental Features" action:nil keyEquivalent:@""];
162     NSMenu *experimentalFeaturesMenu = [[NSMenu alloc] initWithTitle:@"Experimental Features"];
163     [experimentalFeaturesSubmenuItem setSubmenu:experimentalFeaturesMenu];
164
165     NSArray<_WKExperimentalFeature *> *features = [WKPreferences _experimentalFeatures];
166
167     for (_WKExperimentalFeature *feature in features) {
168         NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:feature.name action:@selector(toggleExperimentalFeature:) keyEquivalent:@""];
169         item.representedObject = feature;
170
171         [item setTag:ExperimentalFeatureTag];
172         [item setTarget:self];
173         [experimentalFeaturesMenu addItem:[item autorelease]];
174     }
175
176     [_menu addItem:experimentalFeaturesSubmenuItem];
177     [experimentalFeaturesSubmenuItem release];
178 #endif // WK_API_ENABLED
179
180     [self _addHeaderWithTitle:@"WebKit1-only Settings"];
181     [self _addItemWithTitle:@"Enable Subpixel CSSOM Metrics" action:@selector(toggleEnableSubPixelCSSOMMetrics:) indented:YES];
182 }
183
184 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
185 {
186     SEL action = [menuItem action];
187
188     if (action == @selector(toggleUseWebKit2ByDefault:))
189         [menuItem setState:[self useWebKit2ByDefault] ? NSOnState : NSOffState];
190     else if (action == @selector(toggleUseTransparentWindows:))
191         [menuItem setState:[self useTransparentWindows] ? NSOnState : NSOffState];
192     else if (action == @selector(toggleUsePaginatedMode:))
193         [menuItem setState:[self usePaginatedMode] ? NSOnState : NSOffState];
194     else if (action == @selector(toggleShowLayerBorders:))
195         [menuItem setState:[self layerBordersVisible] ? NSOnState : NSOffState];
196     else if (action == @selector(toggleSimpleLineLayoutDebugBordersEnabled:))
197         [menuItem setState:[self simpleLineLayoutDebugBordersEnabled] ? NSOnState : NSOffState];
198     else if (action == @selector(toggleIncrementalRenderingSuppressed:))
199         [menuItem setState:[self incrementalRenderingSuppressed] ? NSOnState : NSOffState];
200     else if (action == @selector(toggleAcceleratedDrawingEnabled:))
201         [menuItem setState:[self acceleratedDrawingEnabled] ? NSOnState : NSOffState];
202     else if (action == @selector(toggleDisplayListDrawingEnabled:))
203         [menuItem setState:[self displayListDrawingEnabled] ? NSOnState : NSOffState];
204     else if (action == @selector(toggleResourceLoadStatisticsEnabled:))
205         [menuItem setState:[self resourceLoadStatisticsEnabled] ? NSOnState : NSOffState];
206     else if (action == @selector(toggleLargeImageAsyncDecodingEnabled:))
207         [menuItem setState:[self largeImageAsyncDecodingEnabled] ? NSOnState : NSOffState];
208     else if (action == @selector(toggleAnimatedImageAsyncDecodingEnabled:))
209         [menuItem setState:[self animatedImageAsyncDecodingEnabled] ? NSOnState : NSOffState];
210     else if (action == @selector(toggleVisualViewportEnabled:))
211         [menuItem setState:[self visualViewportEnabled] ? NSOnState : NSOffState];
212     else if (action == @selector(toggleShowTiledScrollingIndicator:))
213         [menuItem setState:[self tiledScrollingIndicatorVisible] ? NSOnState : NSOffState];
214     else if (action == @selector(toggleShowResourceUsageOverlay:))
215         [menuItem setState:[self resourceUsageOverlayVisible] ? NSOnState : NSOffState];
216     else if (action == @selector(toggleUsesGameControllerFramework:))
217         [menuItem setState:[self usesGameControllerFramework] ? NSOnState : NSOffState];
218     else if (action == @selector(toggleUseUISideCompositing:))
219         [menuItem setState:[self useUISideCompositing] ? NSOnState : NSOffState];
220     else if (action == @selector(togglePerWindowWebProcessesDisabled:))
221         [menuItem setState:[self perWindowWebProcessesDisabled] ? NSOnState : NSOffState];
222     else if (action == @selector(toggleEnableSubPixelCSSOMMetrics:))
223         [menuItem setState:[self subPixelCSSOMMetricsEnabled] ? NSOnState : NSOffState];
224     else if (action == @selector(toggleDebugOverlay:))
225         [menuItem setState:[self debugOverlayVisible:menuItem] ? NSOnState : NSOffState];
226
227 #if WK_API_ENABLED
228     if (menuItem.tag == ExperimentalFeatureTag) {
229         _WKExperimentalFeature *feature = menuItem.representedObject;
230         [menuItem setState:[defaultPreferences() _isEnabledForFeature:feature] ? NSOnState : NSOffState];
231     }
232 #endif
233
234     return YES;
235 }
236
237 - (void)_toggleBooleanDefault:(NSString *)defaultName
238 {
239     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
240     [defaults setBool:![defaults boolForKey:defaultName] forKey:defaultName];
241
242     [(BrowserAppDelegate *)[[NSApplication sharedApplication] delegate] didChangeSettings];
243 }
244
245 - (void)toggleUseWebKit2ByDefault:(id)sender
246 {
247     [self _toggleBooleanDefault:UseWebKit2ByDefaultPreferenceKey];
248 }
249
250 - (BOOL)useWebKit2ByDefault
251 {
252     return [[NSUserDefaults standardUserDefaults] boolForKey:UseWebKit2ByDefaultPreferenceKey];
253 }
254
255 - (void)toggleUseTransparentWindows:(id)sender
256 {
257     [self _toggleBooleanDefault:UseTransparentWindowsPreferenceKey];
258 }
259
260 - (BOOL)useTransparentWindows
261 {
262     return [[NSUserDefaults standardUserDefaults] boolForKey:UseTransparentWindowsPreferenceKey];
263 }
264
265 - (void)toggleUsePaginatedMode:(id)sender
266 {
267     [self _toggleBooleanDefault:UsePaginatedModePreferenceKey];
268 }
269
270 - (BOOL)usePaginatedMode
271 {
272     return [[NSUserDefaults standardUserDefaults] boolForKey:UsePaginatedModePreferenceKey];
273 }
274
275 - (void)toggleUseUISideCompositing:(id)sender
276 {
277     [self _toggleBooleanDefault:UseRemoteLayerTreeDrawingAreaPreferenceKey];
278 }
279
280 - (BOOL)useUISideCompositing
281 {
282     return [[NSUserDefaults standardUserDefaults] boolForKey:UseRemoteLayerTreeDrawingAreaPreferenceKey];
283 }
284
285 - (void)togglePerWindowWebProcessesDisabled:(id)sender
286 {
287     NSAlert *alert = [[NSAlert alloc] init];
288     [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?"];
289     [alert setInformativeText:@"This requires quitting and relaunching MiniBrowser. I'll do the quitting. You will have to do the relaunching."];
290     [alert addButtonWithTitle:@"Switch and Quit"];
291     [alert addButtonWithTitle:@"Cancel"];
292
293     if ([alert runModal] != NSAlertFirstButtonReturn)
294         return;
295
296     [self _toggleBooleanDefault:PerWindowWebProcessesDisabledKey];
297     [NSApp terminate:self];
298 }
299
300 - (BOOL)perWindowWebProcessesDisabled
301 {
302     return [[NSUserDefaults standardUserDefaults] boolForKey:PerWindowWebProcessesDisabledKey];
303 }
304
305 - (void)toggleIncrementalRenderingSuppressed:(id)sender
306 {
307     [self _toggleBooleanDefault:IncrementalRenderingSuppressedPreferenceKey];
308 }
309
310 - (BOOL)incrementalRenderingSuppressed
311 {
312     return [[NSUserDefaults standardUserDefaults] boolForKey:IncrementalRenderingSuppressedPreferenceKey];
313 }
314
315 - (void)toggleShowLayerBorders:(id)sender
316 {
317     [self _toggleBooleanDefault:LayerBordersVisiblePreferenceKey];
318 }
319
320 - (BOOL)layerBordersVisible
321 {
322     return [[NSUserDefaults standardUserDefaults] boolForKey:LayerBordersVisiblePreferenceKey];
323 }
324
325 - (void)toggleSimpleLineLayoutDebugBordersEnabled:(id)sender
326 {
327     [self _toggleBooleanDefault:SimpleLineLayoutDebugBordersEnabledPreferenceKey];
328 }
329
330 - (BOOL)simpleLineLayoutDebugBordersEnabled
331 {
332     return [[NSUserDefaults standardUserDefaults] boolForKey:SimpleLineLayoutDebugBordersEnabledPreferenceKey];
333 }
334
335 - (void)toggleAcceleratedDrawingEnabled:(id)sender
336 {
337     [self _toggleBooleanDefault:AcceleratedDrawingEnabledPreferenceKey];
338 }
339
340 - (BOOL)acceleratedDrawingEnabled
341 {
342     return [[NSUserDefaults standardUserDefaults] boolForKey:AcceleratedDrawingEnabledPreferenceKey];
343 }
344
345 - (void)toggleDisplayListDrawingEnabled:(id)sender
346 {
347     [self _toggleBooleanDefault:DisplayListDrawingEnabledPreferenceKey];
348 }
349
350 - (BOOL)displayListDrawingEnabled
351 {
352     return [[NSUserDefaults standardUserDefaults] boolForKey:DisplayListDrawingEnabledPreferenceKey];
353 }
354
355 - (void)toggleShowTiledScrollingIndicator:(id)sender
356 {
357     [self _toggleBooleanDefault:TiledScrollingIndicatorVisiblePreferenceKey];
358 }
359
360 - (void)toggleShowResourceUsageOverlay:(id)sender
361 {
362     [self _toggleBooleanDefault:ResourceUsageOverlayVisiblePreferenceKey];
363 }
364
365 - (BOOL)usesGameControllerFramework
366 {
367     return [[NSUserDefaults standardUserDefaults] boolForKey:UsesGameControllerFrameworkKey];
368 }
369
370 - (void)toggleUsesGameControllerFramework:(id)sender
371 {
372     [self _toggleBooleanDefault:UsesGameControllerFrameworkKey];
373 }
374
375 - (BOOL)tiledScrollingIndicatorVisible
376 {
377     return [[NSUserDefaults standardUserDefaults] boolForKey:TiledScrollingIndicatorVisiblePreferenceKey];
378 }
379
380 - (BOOL)resourceUsageOverlayVisible
381 {
382     return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceUsageOverlayVisiblePreferenceKey];
383 }
384
385 - (void)toggleResourceLoadStatisticsEnabled:(id)sender
386 {
387     [self _toggleBooleanDefault:ResourceLoadStatisticsEnabledPreferenceKey];
388 }
389
390 - (BOOL)visualViewportEnabled
391 {
392     return [[NSUserDefaults standardUserDefaults] boolForKey:VisualViewportEnabledPreferenceKey];
393 }
394
395 - (void)toggleVisualViewportEnabled:(id)sender
396 {
397     [self _toggleBooleanDefault:VisualViewportEnabledPreferenceKey];
398 }
399
400 - (BOOL)resourceLoadStatisticsEnabled
401 {
402     return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceLoadStatisticsEnabledPreferenceKey];
403 }
404
405 - (void)toggleLargeImageAsyncDecodingEnabled:(id)sender
406 {
407     [self _toggleBooleanDefault:LargeImageAsyncDecodingEnabledPreferenceKey];
408 }
409
410 - (BOOL)largeImageAsyncDecodingEnabled
411 {
412     return [[NSUserDefaults standardUserDefaults] boolForKey:LargeImageAsyncDecodingEnabledPreferenceKey];
413 }
414
415 - (void)toggleAnimatedImageAsyncDecodingEnabled:(id)sender
416 {
417     [self _toggleBooleanDefault:AnimatedImageAsyncDecodingEnabledPreferenceKey];
418 }
419
420 - (BOOL)animatedImageAsyncDecodingEnabled
421 {
422     return [[NSUserDefaults standardUserDefaults] boolForKey:AnimatedImageAsyncDecodingEnabledPreferenceKey];
423 }
424
425 - (void)toggleEnableSubPixelCSSOMMetrics:(id)sender
426 {
427     [self _toggleBooleanDefault:EnableSubPixelCSSOMMetricsPreferenceKey];
428 }
429
430 - (BOOL)subPixelCSSOMMetricsEnabled
431 {
432     return [[NSUserDefaults standardUserDefaults] boolForKey:EnableSubPixelCSSOMMetricsPreferenceKey];
433 }
434
435 - (BOOL)nonFastScrollableRegionOverlayVisible
436 {
437     return [[NSUserDefaults standardUserDefaults] boolForKey:NonFastScrollableRegionOverlayVisiblePreferenceKey];
438 }
439
440 - (BOOL)wheelEventHandlerRegionOverlayVisible
441 {
442     return [[NSUserDefaults standardUserDefaults] boolForKey:WheelEventHandlerRegionOverlayVisiblePreferenceKey];
443 }
444
445 - (NSString *)preferenceKeyForRegionOverlayTag:(NSUInteger)tag
446 {
447     switch (tag) {
448     case NonFastScrollableRegionOverlayTag:
449         return NonFastScrollableRegionOverlayVisiblePreferenceKey;
450
451     case WheelEventHandlerRegionOverlayTag:
452         return WheelEventHandlerRegionOverlayVisiblePreferenceKey;
453     }
454     return nil;
455 }
456
457 - (void)toggleDebugOverlay:(id)sender
458 {
459     NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[sender tag]];
460     if (preferenceKey)
461         [self _toggleBooleanDefault:preferenceKey];
462 }
463
464 #if WK_API_ENABLED
465 - (void)toggleExperimentalFeature:(id)sender
466 {
467     _WKExperimentalFeature *feature = ((NSMenuItem *)sender).representedObject;
468     WKPreferences *preferences = defaultPreferences();
469
470     BOOL currentlyEnabled = [preferences _isEnabledForFeature:feature];
471     [preferences _setEnabled:!currentlyEnabled forFeature:feature];
472
473     [[NSUserDefaults standardUserDefaults] setBool:!currentlyEnabled forKey:feature.key];
474 }
475 #endif
476
477 - (BOOL)debugOverlayVisible:(NSMenuItem *)menuItem
478 {
479     NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[menuItem tag]];
480     if (preferenceKey)
481         return [[NSUserDefaults standardUserDefaults] boolForKey:preferenceKey];
482
483     return NO;
484 }
485
486 - (NSString *)defaultURL
487 {
488     NSString *customDefaultURL = [[NSUserDefaults standardUserDefaults] stringForKey:DefaultURLPreferenceKey];
489     if (customDefaultURL)
490         return customDefaultURL;
491     return defaultURL;
492 }
493
494 - (void)setDefaultURLToCurrentURL:(id)sender
495 {
496     NSWindowController *windowController = [[NSApp keyWindow] windowController];
497     NSString *customDefaultURL = nil;
498
499     if ([windowController isKindOfClass:[BrowserWindowController class]])
500         customDefaultURL = [[(BrowserWindowController *)windowController currentURL] absoluteString];
501
502     if (customDefaultURL)
503         [[NSUserDefaults standardUserDefaults] setObject:customDefaultURL forKey:DefaultURLPreferenceKey];
504 }
505
506 @end