Remove MiniBrowser custom "Process Swap" menu item which does not work
[WebKit-https.git] / Tools / MiniBrowser / mac / AppDelegate.m
1 /*
2  * Copyright (C) 2010-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 "AppDelegate.h"
27
28 #import "ExtensionManagerWindowController.h"
29 #import "SettingsController.h"
30 #import "WK1BrowserWindowController.h"
31 #import "WK2BrowserWindowController.h"
32 #import <WebKit/WKPreferencesPrivate.h>
33 #import <WebKit/WKProcessPoolPrivate.h>
34 #import <WebKit/WKUserContentControllerPrivate.h>
35 #import <WebKit/WKWebViewConfigurationPrivate.h>
36 #import <WebKit/WKWebsiteDataStorePrivate.h>
37 #import <WebKit/WebKit.h>
38 #import <WebKit/_WKProcessPoolConfiguration.h>
39 #import <WebKit/_WKUserContentExtensionStore.h>
40
41 #if WK_API_ENABLED
42 #import <WebKit/_WKExperimentalFeature.h>
43 #import <WebKit/_WKInternalDebugFeature.h>
44 #endif
45
46 enum {
47     WebKit1NewWindowTag = 1,
48     WebKit2NewWindowTag = 2,
49     WebKit1NewEditorTag = 3,
50     WebKit2NewEditorTag = 4
51 };
52
53 @interface NSApplication (TouchBar)
54 @property (getter=isAutomaticCustomizeTouchBarMenuItemEnabled) BOOL automaticCustomizeTouchBarMenuItemEnabled;
55 @end
56
57 @implementation BrowserAppDelegate
58
59 - (id)init
60 {
61     self = [super init];
62     if (self) {
63         _browserWindowControllers = [[NSMutableSet alloc] init];
64 #if WK_API_ENABLED
65         _extensionManagerWindowController = [[ExtensionManagerWindowController alloc] init];
66 #endif
67     }
68
69     return self;
70 }
71
72 - (void)awakeFromNib
73 {
74     NSMenuItem *item = [[NSMenuItem alloc] init];
75     [item setSubmenu:[[SettingsController shared] menu]];
76
77 #if WK_API_ENABLED
78     if ([[SettingsController shared] usesGameControllerFramework])
79         [WKProcessPool _forceGameControllerFramework];
80 #endif
81
82     [[NSApp mainMenu] insertItem:[item autorelease] atIndex:[[NSApp mainMenu] indexOfItemWithTitle:@"Debug"]];
83
84     if ([NSApp respondsToSelector:@selector(setAutomaticCustomizeTouchBarMenuItemEnabled:)])
85         [NSApp setAutomaticCustomizeTouchBarMenuItemEnabled:YES];
86 }
87
88 #if WK_API_ENABLED
89 static WKWebViewConfiguration *defaultConfiguration()
90 {
91     static WKWebViewConfiguration *configuration;
92
93     if (!configuration) {
94         configuration = [[WKWebViewConfiguration alloc] init];
95         configuration.preferences._fullScreenEnabled = YES;
96         configuration.preferences._developerExtrasEnabled = YES;
97         configuration.preferences._mediaDevicesEnabled = YES;
98         configuration.preferences._mockCaptureDevicesEnabled = YES;
99
100         _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease];
101         processConfiguration.diskCacheSpeculativeValidationEnabled = ![SettingsController shared].networkCacheSpeculativeRevalidationDisabled;
102         if ([SettingsController shared].perWindowWebProcessesDisabled)
103             processConfiguration.maximumProcessCount = 1;
104         if ([SettingsController shared].processSwapOnWindowOpenWithOpenerEnabled)
105             processConfiguration.processSwapsOnWindowOpenWithOpener = true;
106         
107         configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease];
108
109 #if WK_API_ENABLED
110         NSArray<_WKExperimentalFeature *> *experimentalFeatures = [WKPreferences _experimentalFeatures];
111         for (_WKExperimentalFeature *feature in experimentalFeatures) {
112             BOOL enabled;
113             if ([[NSUserDefaults standardUserDefaults] objectForKey:feature.key])
114                 enabled = [[NSUserDefaults standardUserDefaults] boolForKey:feature.key];
115             else
116                 enabled = [feature defaultValue];
117             [configuration.preferences _setEnabled:enabled forExperimentalFeature:feature];
118         }
119
120         NSArray<_WKInternalDebugFeature *> *internalDebugFeatures = [WKPreferences _internalDebugFeatures];
121         for (_WKInternalDebugFeature *feature in internalDebugFeatures) {
122             BOOL enabled;
123             if ([[NSUserDefaults standardUserDefaults] objectForKey:feature.key])
124                 enabled = [[NSUserDefaults standardUserDefaults] boolForKey:feature.key];
125             else
126                 enabled = [feature defaultValue];
127             [configuration.preferences _setEnabled:enabled forInternalDebugFeature:feature];
128         }
129 #endif
130     }
131
132     configuration.suppressesIncrementalRendering = [SettingsController shared].incrementalRenderingSuppressed;
133     configuration.websiteDataStore._resourceLoadStatisticsEnabled = [SettingsController shared].resourceLoadStatisticsEnabled;
134     return configuration;
135 }
136
137 WKPreferences *defaultPreferences()
138 {
139     return defaultConfiguration().preferences;
140 }
141
142 #endif
143
144 - (BrowserWindowController *)createBrowserWindowController:(id)sender
145 {
146     BrowserWindowController *controller = nil;
147     BOOL useWebKit2 = NO;
148     BOOL makeEditable = NO;
149
150     if (![sender respondsToSelector:@selector(tag)]) {
151         useWebKit2 = [SettingsController shared].useWebKit2ByDefault;
152         makeEditable = [SettingsController shared].createEditorByDefault;
153     } else {
154         useWebKit2 = [sender tag] == WebKit2NewWindowTag || [sender tag] == WebKit2NewEditorTag;
155         makeEditable = [sender tag] == WebKit1NewEditorTag || [sender tag] == WebKit2NewEditorTag;
156     }
157
158     if (!useWebKit2)
159         controller = [[WK1BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"];
160 #if WK_API_ENABLED
161     else
162         controller = [[WK2BrowserWindowController alloc] initWithConfiguration:defaultConfiguration()];
163 #endif
164
165     if (makeEditable)
166         controller.editable = YES;
167
168     if (!controller)
169         return nil;
170
171     [_browserWindowControllers addObject:controller];
172
173     return controller;
174 }
175
176 - (IBAction)newWindow:(id)sender
177 {
178     BrowserWindowController *controller = [self createBrowserWindowController:sender];
179     if (!controller)
180         return;
181
182     [[controller window] makeKeyAndOrderFront:sender];
183     [controller loadURLString:[SettingsController shared].defaultURL];
184 }
185
186 - (IBAction)newPrivateWindow:(id)sender
187 {
188 #if WK_API_ENABLED
189     WKWebViewConfiguration *privateConfiguraton = [defaultConfiguration() copy];
190     privateConfiguraton.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
191
192     BrowserWindowController *controller = [[WK2BrowserWindowController alloc] initWithConfiguration:privateConfiguraton];
193     [privateConfiguraton release];
194
195     [[controller window] makeKeyAndOrderFront:sender];
196     [_browserWindowControllers addObject:controller];
197
198     [controller loadURLString:[SettingsController shared].defaultURL];
199 #endif
200 }
201
202 - (IBAction)newEditorWindow:(id)sender
203 {
204     BrowserWindowController *controller = [self createBrowserWindowController:sender];
205     if (!controller)
206         return;
207
208     [[controller window] makeKeyAndOrderFront:sender];
209     [controller loadHTMLString:@"<html><body></body></html>"];
210 }
211
212 - (void)browserWindowWillClose:(NSWindow *)window
213 {
214     [_browserWindowControllers removeObject:window.windowController];
215 }
216
217 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
218 {
219     WebHistory *webHistory = [[WebHistory alloc] init];
220     [WebHistory setOptionalSharedHistory:webHistory];
221     [webHistory release];
222
223     [self _updateNewWindowKeyEquivalents];
224
225     if ([SettingsController shared].createEditorByDefault)
226         [self newEditorWindow:self];
227     else
228         [self newWindow:self];
229 }
230
231 - (BrowserWindowController *)frontmostBrowserWindowController
232 {
233     for (NSWindow* window in [NSApp windows]) {
234         id delegate = [window delegate];
235
236         if (![delegate isKindOfClass:[BrowserWindowController class]])
237             continue;
238
239         BrowserWindowController *controller = (BrowserWindowController *)delegate;
240         assert([_browserWindowControllers containsObject:controller]);
241         return controller;
242     }
243
244     return nil;
245 }
246
247 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
248 {
249     BrowserWindowController *controller = [self createBrowserWindowController:nil];
250     if (!controller)
251         return NO;
252
253     [controller.window makeKeyAndOrderFront:self];
254     [controller loadURLString:[NSURL fileURLWithPath:filename].absoluteString];
255     return YES;
256 }
257
258 - (IBAction)openDocument:(id)sender
259 {
260     BrowserWindowController *browserWindowController = [self frontmostBrowserWindowController];
261
262     if (browserWindowController) {
263         NSOpenPanel *openPanel = [[NSOpenPanel openPanel] retain];
264         [openPanel beginSheetModalForWindow:browserWindowController.window completionHandler:^(NSInteger result) {
265             if (result != NSModalResponseOK)
266                 return;
267
268             NSURL *url = [openPanel.URLs objectAtIndex:0];
269             [browserWindowController loadURLString:[url absoluteString]];
270         }];
271         return;
272     }
273
274     NSOpenPanel *openPanel = [NSOpenPanel openPanel];
275     [openPanel beginWithCompletionHandler:^(NSInteger result) {
276         if (result != NSModalResponseOK)
277             return;
278
279         BrowserWindowController *controller = [self createBrowserWindowController:nil];
280         [controller.window makeKeyAndOrderFront:self];
281
282         NSURL *url = [openPanel.URLs objectAtIndex:0];
283         [controller loadURLString:[url absoluteString]];
284     }];
285 }
286
287 - (void)didChangeSettings
288 {
289     [self _updateNewWindowKeyEquivalents];
290
291     // Let all of the BrowserWindowControllers know that a setting changed, so they can attempt to dynamically update.
292     for (BrowserWindowController *browserWindowController in _browserWindowControllers)
293         [browserWindowController didChangeSettings];
294 }
295
296 - (void)_updateNewWindowKeyEquivalents
297 {
298     NSEventModifierFlags webKit1Flags = [SettingsController shared].useWebKit2ByDefault ? NSEventModifierFlagOption : 0;
299     NSEventModifierFlags webKit2Flags = [SettingsController shared].useWebKit2ByDefault ? 0 : NSEventModifierFlagOption;
300
301     NSString *normalWindowEquivalent = [SettingsController shared].createEditorByDefault ? @"N" : @"n";
302     NSString *editorEquivalent = [SettingsController shared].createEditorByDefault ? @"n" : @"N";
303
304     _newWebKit1WindowItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | webKit1Flags;
305     _newWebKit2WindowItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | webKit2Flags;
306     _newWebKit1EditorItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | webKit1Flags;
307     _newWebKit2EditorItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | webKit2Flags;
308
309     _newWebKit1WindowItem.keyEquivalent = normalWindowEquivalent;
310     _newWebKit2WindowItem.keyEquivalent = normalWindowEquivalent;
311     _newWebKit1EditorItem.keyEquivalent = editorEquivalent;
312     _newWebKit2EditorItem.keyEquivalent = editorEquivalent;
313 }
314
315 - (IBAction)showExtensionsManager:(id)sender
316 {
317 #if WK_API_ENABLED
318     [_extensionManagerWindowController showWindow:sender];
319 #endif
320 }
321
322 #if WK_API_ENABLED
323 - (WKUserContentController *)userContentContoller
324 {
325     return defaultConfiguration().userContentController;
326 }
327
328 - (IBAction)fetchDefaultStoreWebsiteData:(id)sender
329 {
330     [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray *websiteDataRecords) {
331         NSLog(@"did fetch default store website data %@.", websiteDataRecords);
332     }];
333 }
334
335 - (IBAction)fetchAndClearDefaultStoreWebsiteData:(id)sender
336 {
337     [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray *websiteDataRecords) {
338         [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] forDataRecords:websiteDataRecords completionHandler:^{
339             [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray *websiteDataRecords) {
340                 NSLog(@"did clear default store website data, after clearing data is %@.", websiteDataRecords);
341             }];
342         }];
343     }];
344 }
345
346 - (IBAction)clearDefaultStoreWebsiteData:(id)sender
347 {
348     [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^{
349         NSLog(@"Did clear default store website data.");
350     }];
351 }
352
353 #endif
354
355 @end