blob: 5f71baf0ff2e2427dc221dddea7db15cb0aedcfd [file] [log] [blame]
/*
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "SettingsController.h"
#import "AppDelegate.h"
#import "BrowserWindowController.h"
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/_WKExperimentalFeature.h>
#import <WebKit/_WKInternalDebugFeature.h>
NSString * const kUserAgentChangedNotificationName = @"UserAgentChangedNotification";
static NSString * const defaultURL = @"http://www.webkit.org/";
static NSString * const DefaultURLPreferenceKey = @"DefaultURL";
static NSString * const CustomUserAgentPreferenceKey = @"CustomUserAgentIdentifier";
static NSString * const UseWebKit2ByDefaultPreferenceKey = @"UseWebKit2ByDefault";
static NSString * const CreateEditorByDefaultPreferenceKey = @"CreateEditorByDefault";
static NSString * const LayerBordersVisiblePreferenceKey = @"LayerBordersVisible";
static NSString * const LegacyLineLayoutVisualCoverageEnabledPreferenceKey = @"LegacyLineLayoutVisualCoverageEnabled";
static NSString * const TiledScrollingIndicatorVisiblePreferenceKey = @"TiledScrollingIndicatorVisible";
static NSString * const ReserveSpaceForBannersPreferenceKey = @"ReserveSpaceForBanners";
static NSString * const WebViewFillsWindowKey = @"WebViewFillsWindow";
static NSString * const ResourceUsageOverlayVisiblePreferenceKey = @"ResourceUsageOverlayVisible";
static NSString * const LoadsAllSiteIconsKey = @"LoadsAllSiteIcons";
static NSString * const UsesGameControllerFrameworkKey = @"UsesGameControllerFramework";
static NSString * const IncrementalRenderingSuppressedPreferenceKey = @"IncrementalRenderingSuppressed";
static NSString * const AcceleratedDrawingEnabledPreferenceKey = @"AcceleratedDrawingEnabled";
static NSString * const DisplayListDrawingEnabledPreferenceKey = @"DisplayListDrawingEnabled";
static NSString * const SubpixelAntialiasedLayerTextEnabledPreferenceKey = @"SubpixelAntialiasedLayerTextEnabled";
static NSString * const ResourceLoadStatisticsEnabledPreferenceKey = @"ResourceLoadStatisticsEnabled";
static NSString * const NonFastScrollableRegionOverlayVisiblePreferenceKey = @"NonFastScrollableRegionOverlayVisible";
static NSString * const WheelEventHandlerRegionOverlayVisiblePreferenceKey = @"WheelEventHandlerRegionOverlayVisible";
static NSString * const InteractionRegionOverlayVisiblePreferenceKey = @"InteractionRegionOverlayVisible";
static NSString * const UseTransparentWindowsPreferenceKey = @"UseTransparentWindows";
static NSString * const UsePaginatedModePreferenceKey = @"UsePaginatedMode";
static NSString * const LargeImageAsyncDecodingEnabledPreferenceKey = @"LargeImageAsyncDecodingEnabled";
static NSString * const AnimatedImageAsyncDecodingEnabledPreferenceKey = @"AnimatedImageAsyncDecodingEnabled";
static NSString * const AppleColorFilterEnabledPreferenceKey = @"AppleColorFilterEnabled";
static NSString * const PunchOutWhiteBackgroundsInDarkModePreferenceKey = @"PunchOutWhiteBackgroundsInDarkMode";
static NSString * const UseSystemAppearancePreferenceKey = @"UseSystemAppearance";
// This default name intentionally overlaps with the key that WebKit2 checks when creating a view.
static NSString * const UseRemoteLayerTreeDrawingAreaPreferenceKey = @"WebKit2UseRemoteLayerTreeDrawingArea";
static NSString * const PerWindowWebProcessesDisabledKey = @"PerWindowWebProcessesDisabled";
static NSString * const NetworkCacheSpeculativeRevalidationDisabledKey = @"NetworkCacheSpeculativeRevalidationDisabled";
static NSString * const ProcessSwapOnWindowOpenWithOpenerKey = @"ProcessSwapOnWindowOpenWithOpener";
typedef NS_ENUM(NSInteger, DebugOverylayMenuItemTag) {
NonFastScrollableRegionOverlayTag = 100,
WheelEventHandlerRegionOverlayTag,
InteractionRegionOverlayTag,
ExperimentalFeatureTag,
InternalDebugFeatureTag,
};
@interface SettingsController ()
@property (nonatomic, retain) NSMenu *menu;
@end
@implementation SettingsController
- (instancetype)initWithMenu:(NSMenu *)menu
{
self = [super init];
if (!self)
return nil;
_menu = [menu retain];
NSArray *onByDefaultPrefs = @[
UseWebKit2ByDefaultPreferenceKey,
AcceleratedDrawingEnabledPreferenceKey,
SubpixelAntialiasedLayerTextEnabledPreferenceKey,
LargeImageAsyncDecodingEnabledPreferenceKey,
AnimatedImageAsyncDecodingEnabledPreferenceKey,
WebViewFillsWindowKey,
ResourceLoadStatisticsEnabledPreferenceKey,
];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
for (NSString *prefName in onByDefaultPrefs) {
if (![userDefaults objectForKey:prefName])
[userDefaults setBool:YES forKey:prefName];
}
[self _populateMenu];
return self;
}
- (void)dealloc
{
[_menu release];
[super dealloc];
}
- (void)_addItemWithTitle:(NSString *)title action:(SEL)action indented:(BOOL)indented
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""];
[item setTarget:self];
if (indented)
[item setIndentationLevel:1];
[_menu addItem:item];
[item release];
}
- (void)_addHeaderWithTitle:(NSString *)title
{
[_menu addItem:[NSMenuItem separatorItem]];
[_menu addItem:[[[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""] autorelease]];
}
- (void)_populateMenu
{
[self _addItemWithTitle:@"Use WebKit2 By Default" action:@selector(toggleUseWebKit2ByDefault:) indented:NO];
[self _addItemWithTitle:@"Create Editor By Default" action:@selector(toggleCreateEditorByDefault:) indented:NO];
[self _addItemWithTitle:@"Set Default URL to Current URL" action:@selector(setDefaultURLToCurrentURL:) indented:NO];
[_menu addItem:[NSMenuItem separatorItem]];
NSMenuItem *userAgentSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"User Agent" action:nil keyEquivalent:@""];
NSMenu *userAgentMenu = [[NSMenu alloc] initWithTitle:@"User Agent"];
[self buildUserAgentsMenu:userAgentMenu];
[userAgentSubmenuItem setSubmenu:userAgentMenu];
[_menu addItem:userAgentSubmenuItem];
[userAgentMenu release];
[userAgentSubmenuItem release];
[_menu addItem:[NSMenuItem separatorItem]];
[self _addItemWithTitle:@"Use Transparent Windows" action:@selector(toggleUseTransparentWindows:) indented:NO];
[self _addItemWithTitle:@"Use Paginated Mode" action:@selector(toggleUsePaginatedMode:) indented:NO];
[self _addItemWithTitle:@"Show Layer Borders" action:@selector(toggleShowLayerBorders:) indented:NO];
[self _addItemWithTitle:@"Enable Legacy Line Layout Visual Coverage" action:@selector(toggleLegacyLineLayoutVisualCoverageEnabled:) indented:NO];
[self _addItemWithTitle:@"Suppress Incremental Rendering in New Windows" action:@selector(toggleIncrementalRenderingSuppressed:) indented:NO];
[self _addItemWithTitle:@"Enable Accelerated Drawing" action:@selector(toggleAcceleratedDrawingEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable Display List Drawing" action:@selector(toggleDisplayListDrawingEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable Subpixel-antialiased Layer Text" action:@selector(toggleSubpixelAntialiasedLayerTextEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable Resource Load Statistics" action:@selector(toggleResourceLoadStatisticsEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable Large Image Async Decoding" action:@selector(toggleLargeImageAsyncDecodingEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable Animated Image Async Decoding" action:@selector(toggleAnimatedImageAsyncDecodingEnabled:) indented:NO];
[self _addItemWithTitle:@"Enable color-filter" action:@selector(toggleAppleColorFilterEnabled:) indented:NO];
[self _addItemWithTitle:@"Punch Out White Backgrounds in Dark Mode" action:@selector(togglePunchOutWhiteBackgroundsInDarkMode:) indented:NO];
[self _addItemWithTitle:@"Use System Appearance" action:@selector(toggleUseSystemAppearance:) indented:NO];
[self _addHeaderWithTitle:@"WebKit2-only Settings"];
[self _addItemWithTitle:@"Reserve Space For Banners" action:@selector(toggleReserveSpaceForBanners:) indented:YES];
[self _addItemWithTitle:@"Show Tiled Scrolling Indicator" action:@selector(toggleShowTiledScrollingIndicator:) indented:YES];
[self _addItemWithTitle:@"Use UI-Side Compositing" action:@selector(toggleUseUISideCompositing:) indented:YES];
[self _addItemWithTitle:@"Disable Per-Window Web Processes" action:@selector(togglePerWindowWebProcessesDisabled:) indented:YES];
[self _addItemWithTitle:@"Show Resource Usage Overlay" action:@selector(toggleShowResourceUsageOverlay:) indented:YES];
[self _addItemWithTitle:@"Load All Site Icons Per-Page" action:@selector(toggleLoadsAllSiteIcons:) indented:YES];
[self _addItemWithTitle:@"Use GameController.framework on macOS (Restart required)" action:@selector(toggleUsesGameControllerFramework:) indented:YES];
[self _addItemWithTitle:@"Disable network cache speculative revalidation" action:@selector(toggleNetworkCacheSpeculativeRevalidationDisabled:) indented:YES];
[self _addItemWithTitle:@"Enable Process Swap on window.open() with an opener" action:@selector(toggleProcessSwapOnWindowOpenWithOpener:) indented:YES];
NSMenuItem *debugOverlaysSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Debug Overlays" action:nil keyEquivalent:@""];
NSMenu *debugOverlaysMenu = [[NSMenu alloc] initWithTitle:@"Debug Overlays"];
[debugOverlaysSubmenuItem setSubmenu:debugOverlaysMenu];
NSMenuItem *nonFastScrollableRegionItem = [[NSMenuItem alloc] initWithTitle:@"Non-fast Scrollable Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
[nonFastScrollableRegionItem setTag:NonFastScrollableRegionOverlayTag];
[nonFastScrollableRegionItem setTarget:self];
[debugOverlaysMenu addItem:[nonFastScrollableRegionItem autorelease]];
NSMenuItem *wheelEventHandlerRegionItem = [[NSMenuItem alloc] initWithTitle:@"Wheel Event Handler Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
[wheelEventHandlerRegionItem setTag:WheelEventHandlerRegionOverlayTag];
[wheelEventHandlerRegionItem setTarget:self];
[debugOverlaysMenu addItem:[wheelEventHandlerRegionItem autorelease]];
NSMenuItem *interactionRegionItem = [[NSMenuItem alloc] initWithTitle:@"Interaction Region" action:@selector(toggleDebugOverlay:) keyEquivalent:@""];
[interactionRegionItem setTag:InteractionRegionOverlayTag];
[interactionRegionItem setTarget:self];
[debugOverlaysMenu addItem:[interactionRegionItem autorelease]];
[debugOverlaysMenu release];
[_menu addItem:debugOverlaysSubmenuItem];
[debugOverlaysSubmenuItem release];
NSMenuItem *experimentalFeaturesSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Experimental Features" action:nil keyEquivalent:@""];
NSMenu *experimentalFeaturesMenu = [[NSMenu alloc] initWithTitle:@"Experimental Features"];
[experimentalFeaturesSubmenuItem setSubmenu:experimentalFeaturesMenu];
NSArray<_WKExperimentalFeature *> *experimentalFeatures = [WKPreferences _experimentalFeatures];
for (_WKExperimentalFeature *feature in experimentalFeatures) {
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:feature.name action:@selector(toggleExperimentalFeature:) keyEquivalent:@""];
item.toolTip = feature.details;
item.representedObject = feature;
[item setTag:ExperimentalFeatureTag];
[item setTarget:self];
[experimentalFeaturesMenu addItem:[item autorelease]];
}
[experimentalFeaturesMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem *resetExperimentalFeaturesToDefaultsItem = [[NSMenuItem alloc] initWithTitle:@"Reset All to Defaults" action:@selector(resetAllExperimentalFeatures:) keyEquivalent:@""];
[resetExperimentalFeaturesToDefaultsItem setTarget:self];
[experimentalFeaturesMenu addItem:resetExperimentalFeaturesToDefaultsItem];
[resetExperimentalFeaturesToDefaultsItem release];
[_menu addItem:experimentalFeaturesSubmenuItem];
[experimentalFeaturesSubmenuItem release];
[experimentalFeaturesMenu release];
NSMenuItem *internalDebugFeaturesSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Internal Features" action:nil keyEquivalent:@""];
NSMenu *internalDebugFeaturesMenu = [[NSMenu alloc] initWithTitle:@"Internal Features"];
[internalDebugFeaturesSubmenuItem setSubmenu:internalDebugFeaturesMenu];
NSArray<_WKInternalDebugFeature *> *internalDebugFeatures = [WKPreferences _internalDebugFeatures];
for (_WKInternalDebugFeature *feature in internalDebugFeatures) {
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:feature.name action:@selector(toggleInternalDebugFeature:) keyEquivalent:@""];
item.toolTip = feature.details;
item.representedObject = feature;
[item setTag:InternalDebugFeatureTag];
[item setTarget:self];
[internalDebugFeaturesMenu addItem:[item autorelease]];
}
[internalDebugFeaturesMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem *resetInternalFeaturesToDefaultsItem = [[NSMenuItem alloc] initWithTitle:@"Reset All to Defaults" action:@selector(resetAllInternalDebugFeatures:) keyEquivalent:@""];
[resetInternalFeaturesToDefaultsItem setTarget:self];
[internalDebugFeaturesMenu addItem:resetInternalFeaturesToDefaultsItem];
[resetInternalFeaturesToDefaultsItem release];
[_menu addItem:internalDebugFeaturesSubmenuItem];
[internalDebugFeaturesSubmenuItem release];
[internalDebugFeaturesMenu release];
[self _addHeaderWithTitle:@"WebKit1-only Settings"];
}
+ (NSArray *)userAgentData
{
return @[
@{
@"label" : @"Safari 13.1",
@"identifier" : @"safari",
@"userAgent" : @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15"
},
@{
@"label" : @"-",
},
@{
@"label" : @"Safari—iOS 13.4—iPhone",
@"identifier" : @"iphone-safari",
@"userAgent" : @"Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1"
},
@{
@"label" : @"-",
},
@{
@"label" : @"Firefox—macOS",
@"identifier" : @"firefox",
@"userAgent" : @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:70.0) Gecko/20100101 Firefox/70.0"
},
@{
@"label" : @"Firefox—Windows",
@"identifier" : @"windows-firefox",
@"userAgent" : @"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/71.0"
},
@{
@"label" : @"-",
},
@{
@"label" : @"Chrome—macOS",
@"identifier" : @"chrome",
@"userAgent" : @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
},
@{
@"label" : @"Chrome—Windows",
@"identifier" : @"windows-chrome",
@"userAgent" : @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
},
@{
@"label" : @"Chrome—Android",
@"identifier" : @"android-chrome",
@"userAgent" : @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
},
];
}
- (void)buildUserAgentsMenu:(NSMenu *)menu
{
NSDictionary* defaultUAInfo = @{
@"label" : @"Default",
@"identifier" : @"default",
};
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"Default" action:@selector(changeCutomUserAgent:) keyEquivalent:@""];
[menuItem setTarget:self];
[menuItem setRepresentedObject:defaultUAInfo];
[menu addItem:menuItem];
[menuItem release];
[menu addItem:[NSMenuItem separatorItem]];
for (NSDictionary *userAgentData in [[self class] userAgentData]) {
NSString *name = userAgentData[@"label"];
if ([name isEqualToString:@"-"]) {
[menu addItem:[NSMenuItem separatorItem]];
continue;
}
menuItem = [[NSMenuItem alloc] initWithTitle:name action:@selector(changeCutomUserAgent:) keyEquivalent:@""];
[menuItem setTarget:self];
[menuItem setRepresentedObject:userAgentData];
[menu addItem:menuItem];
[menuItem release];
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
#pragma GCC diagnostic pop
{
SEL action = [menuItem action];
if (action == @selector(toggleUseWebKit2ByDefault:))
[menuItem setState:[self useWebKit2ByDefault] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleCreateEditorByDefault:))
[menuItem setState:[self createEditorByDefault] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUseTransparentWindows:))
[menuItem setState:[self useTransparentWindows] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUsePaginatedMode:))
[menuItem setState:[self usePaginatedMode] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleShowLayerBorders:))
[menuItem setState:[self layerBordersVisible] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleLegacyLineLayoutVisualCoverageEnabled:))
[menuItem setState:[self legacyLineLayoutVisualCoverageEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleIncrementalRenderingSuppressed:))
[menuItem setState:[self incrementalRenderingSuppressed] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleAcceleratedDrawingEnabled:))
[menuItem setState:[self acceleratedDrawingEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleDisplayListDrawingEnabled:))
[menuItem setState:[self displayListDrawingEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleSubpixelAntialiasedLayerTextEnabled:))
[menuItem setState:[self subpixelAntialiasedLayerTextEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleResourceLoadStatisticsEnabled:))
[menuItem setState:[self resourceLoadStatisticsEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleLargeImageAsyncDecodingEnabled:))
[menuItem setState:[self largeImageAsyncDecodingEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleAnimatedImageAsyncDecodingEnabled:))
[menuItem setState:[self animatedImageAsyncDecodingEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleAppleColorFilterEnabled:))
[menuItem setState:[self appleColorFilterEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(togglePunchOutWhiteBackgroundsInDarkMode:))
[menuItem setState:[self punchOutWhiteBackgroundsInDarkMode] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUseSystemAppearance:))
[menuItem setState:[self useSystemAppearance] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleReserveSpaceForBanners:))
[menuItem setState:[self isSpaceReservedForBanners] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleShowTiledScrollingIndicator:))
[menuItem setState:[self tiledScrollingIndicatorVisible] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleShowResourceUsageOverlay:))
[menuItem setState:[self resourceUsageOverlayVisible] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleLoadsAllSiteIcons:))
[menuItem setState:[self loadsAllSiteIcons] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUsesGameControllerFramework:))
[menuItem setState:[self usesGameControllerFramework] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleNetworkCacheSpeculativeRevalidationDisabled:))
[menuItem setState:[self networkCacheSpeculativeRevalidationDisabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleProcessSwapOnWindowOpenWithOpener:))
[menuItem setState:[self processSwapOnWindowOpenWithOpenerEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUseUISideCompositing:))
[menuItem setState:[self useUISideCompositing] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(togglePerWindowWebProcessesDisabled:))
[menuItem setState:[self perWindowWebProcessesDisabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleDebugOverlay:))
[menuItem setState:[self debugOverlayVisible:menuItem] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(changeCutomUserAgent:)) {
NSString *savedUAIdentifier = [[NSUserDefaults standardUserDefaults] stringForKey:CustomUserAgentPreferenceKey];
NSDictionary *userAgentDict = [menuItem representedObject];
if (userAgentDict) {
BOOL isCurrentUA = [userAgentDict[@"identifier"] isEqualToString:savedUAIdentifier];
[menuItem setState:isCurrentUA ? NSControlStateValueOn : NSControlStateValueOff];
} else
[menuItem setState:NSControlStateValueOff];
}
WKPreferences *defaultPreferences = [[NSApplication sharedApplication] browserAppDelegate].defaultPreferences;
if (menuItem.tag == ExperimentalFeatureTag) {
_WKExperimentalFeature *feature = menuItem.representedObject;
[menuItem setState:[defaultPreferences _isEnabledForExperimentalFeature:feature] ? NSControlStateValueOn : NSControlStateValueOff];
}
if (menuItem.tag == InternalDebugFeatureTag) {
_WKInternalDebugFeature *feature = menuItem.representedObject;
[menuItem setState:[defaultPreferences _isEnabledForInternalDebugFeature:feature] ? NSControlStateValueOn : NSControlStateValueOff];
}
return YES;
}
- (void)_toggleBooleanDefault:(NSString *)defaultName
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:![defaults boolForKey:defaultName] forKey:defaultName];
[[[NSApplication sharedApplication] browserAppDelegate] didChangeSettings];
}
- (void)toggleUseWebKit2ByDefault:(id)sender
{
[self _toggleBooleanDefault:UseWebKit2ByDefaultPreferenceKey];
}
- (BOOL)useWebKit2ByDefault
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UseWebKit2ByDefaultPreferenceKey];
}
- (void)toggleCreateEditorByDefault:(id)sender
{
[self _toggleBooleanDefault:CreateEditorByDefaultPreferenceKey];
}
- (BOOL)createEditorByDefault
{
return [[NSUserDefaults standardUserDefaults] boolForKey:CreateEditorByDefaultPreferenceKey];
}
- (void)toggleUseTransparentWindows:(id)sender
{
[self _toggleBooleanDefault:UseTransparentWindowsPreferenceKey];
}
- (BOOL)useTransparentWindows
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UseTransparentWindowsPreferenceKey];
}
- (void)toggleUsePaginatedMode:(id)sender
{
[self _toggleBooleanDefault:UsePaginatedModePreferenceKey];
}
- (BOOL)usePaginatedMode
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UsePaginatedModePreferenceKey];
}
- (void)toggleUseUISideCompositing:(id)sender
{
[self _toggleBooleanDefault:UseRemoteLayerTreeDrawingAreaPreferenceKey];
}
- (BOOL)useUISideCompositing
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UseRemoteLayerTreeDrawingAreaPreferenceKey];
}
- (void)togglePerWindowWebProcessesDisabled:(id)sender
{
NSAlert *alert = [[NSAlert alloc] init];
[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?"];
[alert setInformativeText:@"This requires quitting and relaunching MiniBrowser. I'll do the quitting. You will have to do the relaunching."];
[alert addButtonWithTitle:@"Switch and Quit"];
[alert addButtonWithTitle:@"Cancel"];
NSModalResponse response = [alert runModal];
[alert release];
if (response != NSAlertFirstButtonReturn)
return;
[self _toggleBooleanDefault:PerWindowWebProcessesDisabledKey];
[NSApp terminate:self];
}
- (BOOL)perWindowWebProcessesDisabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:PerWindowWebProcessesDisabledKey];
}
- (void)toggleIncrementalRenderingSuppressed:(id)sender
{
[self _toggleBooleanDefault:IncrementalRenderingSuppressedPreferenceKey];
}
- (BOOL)incrementalRenderingSuppressed
{
return [[NSUserDefaults standardUserDefaults] boolForKey:IncrementalRenderingSuppressedPreferenceKey];
}
- (void)toggleShowLayerBorders:(id)sender
{
[self _toggleBooleanDefault:LayerBordersVisiblePreferenceKey];
}
- (BOOL)layerBordersVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:LayerBordersVisiblePreferenceKey];
}
- (void)toggleLegacyLineLayoutVisualCoverageEnabled:(id)sender
{
[self _toggleBooleanDefault:LegacyLineLayoutVisualCoverageEnabledPreferenceKey];
}
- (BOOL)legacyLineLayoutVisualCoverageEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:LegacyLineLayoutVisualCoverageEnabledPreferenceKey];
}
- (void)toggleAcceleratedDrawingEnabled:(id)sender
{
[self _toggleBooleanDefault:AcceleratedDrawingEnabledPreferenceKey];
}
- (BOOL)acceleratedDrawingEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:AcceleratedDrawingEnabledPreferenceKey];
}
- (void)toggleDisplayListDrawingEnabled:(id)sender
{
[self _toggleBooleanDefault:DisplayListDrawingEnabledPreferenceKey];
}
- (BOOL)displayListDrawingEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:DisplayListDrawingEnabledPreferenceKey];
}
- (void)toggleSubpixelAntialiasedLayerTextEnabled:(id)sender
{
[self _toggleBooleanDefault:SubpixelAntialiasedLayerTextEnabledPreferenceKey];
}
- (BOOL)subpixelAntialiasedLayerTextEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:SubpixelAntialiasedLayerTextEnabledPreferenceKey];
}
- (void)toggleReserveSpaceForBanners:(id)sender
{
[self _toggleBooleanDefault:ReserveSpaceForBannersPreferenceKey];
}
- (void)toggleShowTiledScrollingIndicator:(id)sender
{
[self _toggleBooleanDefault:TiledScrollingIndicatorVisiblePreferenceKey];
}
- (void)toggleShowResourceUsageOverlay:(id)sender
{
[self _toggleBooleanDefault:ResourceUsageOverlayVisiblePreferenceKey];
}
- (BOOL)loadsAllSiteIcons
{
return [[NSUserDefaults standardUserDefaults] boolForKey:LoadsAllSiteIconsKey];
}
- (void)toggleLoadsAllSiteIcons:(id)sender
{
[self _toggleBooleanDefault:LoadsAllSiteIconsKey];
}
- (BOOL)usesGameControllerFramework
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UsesGameControllerFrameworkKey];
}
- (void)toggleUsesGameControllerFramework:(id)sender
{
[self _toggleBooleanDefault:UsesGameControllerFrameworkKey];
}
- (BOOL)networkCacheSpeculativeRevalidationDisabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:NetworkCacheSpeculativeRevalidationDisabledKey];
}
- (void)toggleNetworkCacheSpeculativeRevalidationDisabled:(id)sender
{
[self _toggleBooleanDefault:NetworkCacheSpeculativeRevalidationDisabledKey];
}
- (BOOL)processSwapOnWindowOpenWithOpenerEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:ProcessSwapOnWindowOpenWithOpenerKey];
}
- (void)toggleProcessSwapOnWindowOpenWithOpener:(id)sender
{
[self _toggleBooleanDefault:ProcessSwapOnWindowOpenWithOpenerKey];
}
- (BOOL)isSpaceReservedForBanners
{
return [[NSUserDefaults standardUserDefaults] boolForKey:ReserveSpaceForBannersPreferenceKey];
}
- (BOOL)webViewFillsWindow
{
return [[NSUserDefaults standardUserDefaults] boolForKey:WebViewFillsWindowKey];
}
- (void)setWebViewFillsWindow:(BOOL)fillsWindow
{
return [[NSUserDefaults standardUserDefaults] setBool:fillsWindow forKey:WebViewFillsWindowKey];
}
- (BOOL)tiledScrollingIndicatorVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:TiledScrollingIndicatorVisiblePreferenceKey];
}
- (BOOL)resourceUsageOverlayVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceUsageOverlayVisiblePreferenceKey];
}
- (void)toggleResourceLoadStatisticsEnabled:(id)sender
{
[self _toggleBooleanDefault:ResourceLoadStatisticsEnabledPreferenceKey];
}
- (BOOL)resourceLoadStatisticsEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:ResourceLoadStatisticsEnabledPreferenceKey];
}
- (void)toggleLargeImageAsyncDecodingEnabled:(id)sender
{
[self _toggleBooleanDefault:LargeImageAsyncDecodingEnabledPreferenceKey];
}
- (BOOL)largeImageAsyncDecodingEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:LargeImageAsyncDecodingEnabledPreferenceKey];
}
- (void)toggleAnimatedImageAsyncDecodingEnabled:(id)sender
{
[self _toggleBooleanDefault:AnimatedImageAsyncDecodingEnabledPreferenceKey];
}
- (BOOL)animatedImageAsyncDecodingEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:AnimatedImageAsyncDecodingEnabledPreferenceKey];
}
- (void)toggleAppleColorFilterEnabled:(id)sender
{
[self _toggleBooleanDefault:AppleColorFilterEnabledPreferenceKey];
}
- (BOOL)appleColorFilterEnabled
{
return [[NSUserDefaults standardUserDefaults] boolForKey:AppleColorFilterEnabledPreferenceKey];
}
- (void)togglePunchOutWhiteBackgroundsInDarkMode:(id)sender
{
[self _toggleBooleanDefault:PunchOutWhiteBackgroundsInDarkModePreferenceKey];
}
- (BOOL)punchOutWhiteBackgroundsInDarkMode
{
return [[NSUserDefaults standardUserDefaults] boolForKey:PunchOutWhiteBackgroundsInDarkModePreferenceKey];
}
- (void)toggleUseSystemAppearance:(id)sender
{
[self _toggleBooleanDefault:UseSystemAppearancePreferenceKey];
}
- (BOOL)useSystemAppearance
{
return [[NSUserDefaults standardUserDefaults] boolForKey:UseSystemAppearancePreferenceKey];
}
- (BOOL)nonFastScrollableRegionOverlayVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:NonFastScrollableRegionOverlayVisiblePreferenceKey];
}
- (BOOL)wheelEventHandlerRegionOverlayVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:WheelEventHandlerRegionOverlayVisiblePreferenceKey];
}
- (BOOL)interactionRegionOverlayVisible
{
return [[NSUserDefaults standardUserDefaults] boolForKey:InteractionRegionOverlayVisiblePreferenceKey];
}
- (NSString *)preferenceKeyForRegionOverlayTag:(NSUInteger)tag
{
switch (tag) {
case NonFastScrollableRegionOverlayTag:
return NonFastScrollableRegionOverlayVisiblePreferenceKey;
case WheelEventHandlerRegionOverlayTag:
return WheelEventHandlerRegionOverlayVisiblePreferenceKey;
case InteractionRegionOverlayTag:
return InteractionRegionOverlayVisiblePreferenceKey;
}
return nil;
}
- (void)toggleDebugOverlay:(id)sender
{
NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[sender tag]];
if (preferenceKey)
[self _toggleBooleanDefault:preferenceKey];
}
- (void)toggleExperimentalFeature:(id)sender
{
_WKExperimentalFeature *feature = ((NSMenuItem *)sender).representedObject;
WKPreferences *preferences = [[NSApplication sharedApplication] browserAppDelegate].defaultPreferences;
BOOL currentlyEnabled = [preferences _isEnabledForExperimentalFeature:feature];
[preferences _setEnabled:!currentlyEnabled forExperimentalFeature:feature];
[[NSUserDefaults standardUserDefaults] setBool:!currentlyEnabled forKey:feature.key];
}
- (void)toggleInternalDebugFeature:(id)sender
{
_WKInternalDebugFeature *feature = ((NSMenuItem *)sender).representedObject;
WKPreferences *preferences = [[NSApplication sharedApplication] browserAppDelegate].defaultPreferences;
BOOL currentlyEnabled = [preferences _isEnabledForInternalDebugFeature:feature];
[preferences _setEnabled:!currentlyEnabled forInternalDebugFeature:feature];
[[NSUserDefaults standardUserDefaults] setBool:!currentlyEnabled forKey:feature.key];
}
- (void)resetAllExperimentalFeatures:(id)sender
{
WKPreferences *preferences = [[NSApplication sharedApplication] browserAppDelegate].defaultPreferences;
NSArray<_WKExperimentalFeature *> *experimentalFeatures = [WKPreferences _experimentalFeatures];
for (_WKExperimentalFeature *feature in experimentalFeatures) {
[preferences _setEnabled:feature.defaultValue forExperimentalFeature:feature];
[[NSUserDefaults standardUserDefaults] setBool:feature.defaultValue forKey:feature.key];
}
}
- (void)resetAllInternalDebugFeatures:(id)sender
{
WKPreferences *preferences = [[NSApplication sharedApplication] browserAppDelegate].defaultPreferences;
NSArray<_WKInternalDebugFeature *> *internalDebugFeatures = [WKPreferences _internalDebugFeatures];
for (_WKInternalDebugFeature *feature in internalDebugFeatures) {
[preferences _setEnabled:feature.defaultValue forInternalDebugFeature:feature];
[[NSUserDefaults standardUserDefaults] setBool:feature.defaultValue forKey:feature.key];
}
}
- (BOOL)debugOverlayVisible:(NSMenuItem *)menuItem
{
NSString *preferenceKey = [self preferenceKeyForRegionOverlayTag:[menuItem tag]];
if (preferenceKey)
return [[NSUserDefaults standardUserDefaults] boolForKey:preferenceKey];
return NO;
}
- (NSString *)customUserAgent
{
NSString *uaIdentifier = [[NSUserDefaults standardUserDefaults] stringForKey:CustomUserAgentPreferenceKey];
if (uaIdentifier) {
for (NSDictionary *item in [[self class] userAgentData]) {
if ([item[@"identifier"] isEqualToString:uaIdentifier])
return item[@"userAgent"];
}
}
return nil;
}
- (void)changeCutomUserAgent:(id)sender
{
NSDictionary *userAgentDict = [sender representedObject];
if (!userAgentDict)
return;
NSString *uaIdentifier = userAgentDict[@"identifier"];
if (uaIdentifier)
[[NSUserDefaults standardUserDefaults] setObject:uaIdentifier forKey:CustomUserAgentPreferenceKey];
[[NSNotificationCenter defaultCenter] postNotificationName:kUserAgentChangedNotificationName object:self];
}
- (NSString *)defaultURL
{
NSString *customDefaultURL = [[NSUserDefaults standardUserDefaults] stringForKey:DefaultURLPreferenceKey];
if (customDefaultURL)
return customDefaultURL;
return defaultURL;
}
- (void)setDefaultURLToCurrentURL:(id)sender
{
NSWindowController *windowController = [[NSApp keyWindow] windowController];
NSString *customDefaultURL = nil;
if ([windowController isKindOfClass:[BrowserWindowController class]])
customDefaultURL = [[(BrowserWindowController *)windowController currentURL] absoluteString];
if (customDefaultURL)
[[NSUserDefaults standardUserDefaults] setObject:customDefaultURL forKey:DefaultURLPreferenceKey];
}
@end