Adjust the Web Inspector window title frame if needed to prevent it from intersecting...
[WebKit-https.git] / Source / WebKit / mac / WebCoreSupport / WebInspectorClient.mm
1 /*
2  * Copyright (C) 2006, 2007, 2008 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "WebInspectorClient.h"
30
31 #import "DOMNodeInternal.h"
32 #import "WebDelegateImplementationCaching.h"
33 #import "WebFrameInternal.h"
34 #import "WebFrameView.h"
35 #import "WebInspector.h"
36 #import "WebInspectorPrivate.h"
37 #import "WebInspectorFrontend.h"
38 #import "WebLocalizableStringsInternal.h"
39 #import "WebNodeHighlighter.h"
40 #import "WebUIDelegate.h"
41 #import "WebPolicyDelegate.h"
42 #import "WebViewInternal.h"
43 #import <WebCore/InspectorController.h>
44 #import <WebCore/Page.h>
45 #import <WebCore/SoftLinking.h>
46 #import <WebKit/DOMExtensions.h>
47 #import <WebKitSystemInterface.h>
48 #import <wtf/PassOwnPtr.h>
49
50 SOFT_LINK_STAGED_FRAMEWORK_OPTIONAL(WebInspector, PrivateFrameworks, A)
51
52 // The margin from the top and right of the dock button (same as the full screen button).
53 static const CGFloat dockButtonMargin = 3;
54
55 using namespace WebCore;
56
57 @interface NSWindow (AppKitDetails)
58 - (NSCursor *)_cursorForResizeDirection:(NSInteger)direction;
59 - (NSRect)_customTitleFrame;
60 @end
61
62 @interface WebInspectorWindow : NSWindow {
63 @public
64     RetainPtr<NSButton> _dockButton;
65 }
66 @end
67
68 @implementation WebInspectorWindow
69
70 - (NSCursor *)_cursorForResizeDirection:(NSInteger)direction
71 {
72     // Don't show a resize cursor for the northeast (top right) direction if the dock button is visible.
73     // This matches what happens when the full screen button is visible.
74     if (direction == 1 && ![_dockButton isHidden])
75         return nil;
76     return [super _cursorForResizeDirection:direction];
77 }
78
79 - (NSRect)_customTitleFrame
80 {
81     // Adjust the title frame if needed to prevent it from intersecting the dock button.
82     NSRect titleFrame = [super _customTitleFrame];
83     NSRect dockButtonFrame = _dockButton.get().frame;
84     if (NSMaxX(titleFrame) > NSMinX(dockButtonFrame) - dockButtonMargin)
85         titleFrame.size.width -= (NSMaxX(titleFrame) - NSMinX(dockButtonFrame)) + dockButtonMargin;
86     return titleFrame;
87 }
88
89 @end
90
91 @interface WebInspectorWindowController : NSWindowController <NSWindowDelegate> {
92 @private
93     RetainPtr<WebView> _inspectedWebView;
94     RetainPtr<NSButton> _dockButton;
95     WebView *_webView;
96     WebInspectorFrontendClient* _frontendClient;
97     WebInspectorClient* _inspectorClient;
98     BOOL _attachedToInspectedWebView;
99     BOOL _shouldAttach;
100     BOOL _visible;
101     BOOL _destroyingInspectorView;
102 }
103 - (id)initWithInspectedWebView:(WebView *)webView;
104 - (NSString *)inspectorPagePath;
105 - (WebView *)webView;
106 - (void)attach;
107 - (void)detach;
108 - (BOOL)attached;
109 - (void)setFrontendClient:(WebInspectorFrontendClient*)frontendClient;
110 - (void)setInspectorClient:(WebInspectorClient*)inspectorClient;
111 - (WebInspectorClient*)inspectorClient;
112 - (void)setAttachedWindowHeight:(unsigned)height;
113 - (void)setDockingUnavailable:(BOOL)unavailable;
114 - (void)destroyInspectorView:(bool)notifyInspectorController;
115 @end
116
117
118 // MARK: -
119
120 WebInspectorClient::WebInspectorClient(WebView *webView)
121     : m_webView(webView)
122     , m_highlighter(AdoptNS, [[WebNodeHighlighter alloc] initWithInspectedWebView:webView])
123     , m_frontendPage(0)
124     , m_frontendClient(0)
125 {
126 }
127
128 void WebInspectorClient::inspectorDestroyed()
129 {
130     closeInspectorFrontend();
131     delete this;
132 }
133
134 InspectorFrontendChannel* WebInspectorClient::openInspectorFrontend(InspectorController* inspectorController)
135 {
136     RetainPtr<WebInspectorWindowController> windowController(AdoptNS, [[WebInspectorWindowController alloc] initWithInspectedWebView:m_webView]);
137     [windowController.get() setInspectorClient:this];
138
139     m_frontendPage = core([windowController.get() webView]);
140     OwnPtr<WebInspectorFrontendClient> frontendClient = adoptPtr(new WebInspectorFrontendClient(m_webView, windowController.get(), inspectorController, m_frontendPage, createFrontendSettings()));
141     m_frontendClient = frontendClient.get();
142     RetainPtr<WebInspectorFrontend> webInspectorFrontend(AdoptNS, [[WebInspectorFrontend alloc] initWithFrontendClient:frontendClient.get()]);
143     [[m_webView inspector] setFrontend:webInspectorFrontend.get()];
144     m_frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
145     return this;
146 }
147
148 void WebInspectorClient::closeInspectorFrontend()
149 {
150     if (m_frontendClient)
151         m_frontendClient->disconnectFromBackend();
152 }
153
154 void WebInspectorClient::bringFrontendToFront()
155 {
156     m_frontendClient->bringToFront();
157 }
158
159 void WebInspectorClient::didResizeMainFrame(Frame*)
160 {
161     if (m_frontendClient)
162         m_frontendClient->attachAvailabilityChanged(m_frontendClient->canAttachWindow());
163 }
164
165 void WebInspectorClient::highlight()
166 {
167     [m_highlighter.get() highlight];
168 }
169
170 void WebInspectorClient::hideHighlight()
171 {
172     [m_highlighter.get() hideHighlight];
173 }
174
175 void WebInspectorClient::releaseFrontend()
176 {
177     m_frontendClient = 0;
178     m_frontendPage = 0;
179 }
180
181 WebInspectorFrontendClient::WebInspectorFrontendClient(WebView* inspectedWebView, WebInspectorWindowController* windowController, InspectorController* inspectorController, Page* frontendPage, WTF::PassOwnPtr<Settings> settings)
182     : InspectorFrontendClientLocal(inspectorController,  frontendPage, settings)
183     , m_inspectedWebView(inspectedWebView)
184     , m_windowController(windowController)
185 {
186     [windowController setFrontendClient:this];
187 }
188
189 void WebInspectorFrontendClient::attachAvailabilityChanged(bool available)
190 {
191     setDockingUnavailable(!available);
192     [m_windowController.get() setDockingUnavailable:!available];
193 }
194
195 void WebInspectorFrontendClient::frontendLoaded()
196 {
197     [m_windowController.get() showWindow:nil];
198     if ([m_windowController.get() attached])
199         restoreAttachedWindowHeight();
200
201     InspectorFrontendClientLocal::frontendLoaded();
202
203     WebFrame *frame = [m_inspectedWebView mainFrame];
204     
205     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(m_inspectedWebView);
206     if (implementations->didClearInspectorWindowObjectForFrameFunc)
207         CallFrameLoadDelegate(implementations->didClearInspectorWindowObjectForFrameFunc, m_inspectedWebView,
208                               @selector(webView:didClearInspectorWindowObject:forFrame:), [frame windowObject], frame);
209
210     bool attached = [m_windowController.get() attached];
211     setAttachedWindow(attached);
212 }
213
214 static bool useWebKitWebInspector()
215 {
216     // Call the soft link framework function to dlopen it, then [NSBundle bundleWithIdentifier:] will work.
217     WebInspectorLibrary();
218
219     if (![[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"])
220         return true;
221
222     if (![[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"])
223         return false;
224
225     return [[NSUserDefaults standardUserDefaults] boolForKey:@"UseWebKitWebInspector"];
226 }
227
228 String WebInspectorFrontendClient::localizedStringsURL()
229 {
230     NSBundle *bundle = useWebKitWebInspector() ? [NSBundle bundleWithIdentifier:@"com.apple.WebCore"] : [NSBundle bundleWithIdentifier:@"com.apple.WebInspector"]; 
231     NSString *path = [bundle pathForResource:@"localizedStrings" ofType:@"js"];
232     if ([path length])
233         return [[NSURL fileURLWithPath:path] absoluteString];
234     return String();
235 }
236
237 String WebInspectorFrontendClient::hiddenPanels()
238 {
239     NSString *hiddenPanels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebKitInspectorHiddenPanels"];
240     if (hiddenPanels)
241         return hiddenPanels;
242     return String();
243 }
244
245 void WebInspectorFrontendClient::bringToFront()
246 {
247     updateWindowTitle();
248
249     [m_windowController.get() showWindow:nil];
250
251     // Use the window from the WebView since m_windowController's window
252     // is not the same when the Inspector is docked.
253     WebView *webView = [m_windowController.get() webView];
254     [[webView window] makeFirstResponder:webView];
255 }
256
257 void WebInspectorFrontendClient::closeWindow()
258 {
259     [m_windowController.get() destroyInspectorView:true];
260 }
261
262 void WebInspectorFrontendClient::disconnectFromBackend()
263 {
264     [m_windowController.get() destroyInspectorView:false];
265 }
266
267 void WebInspectorFrontendClient::attachWindow()
268 {
269     if ([m_windowController.get() attached])
270         return;
271     [m_windowController.get() attach];
272     restoreAttachedWindowHeight();
273 }
274
275 void WebInspectorFrontendClient::detachWindow()
276 {
277     [m_windowController.get() detach];
278 }
279
280 void WebInspectorFrontendClient::setAttachedWindowHeight(unsigned height)
281 {
282     [m_windowController.get() setAttachedWindowHeight:height];
283 }
284
285 void WebInspectorFrontendClient::inspectedURLChanged(const String& newURL)
286 {
287     m_inspectedURL = newURL;
288     updateWindowTitle();
289 }
290
291 void WebInspectorFrontendClient::updateWindowTitle() const
292 {
293     NSString *title = [NSString stringWithFormat:UI_STRING_INTERNAL("Web Inspector — %@", "Web Inspector window title"), (NSString *)m_inspectedURL];
294     [[m_windowController.get() window] setTitle:title];
295 }
296
297
298 // MARK: -
299
300 @implementation WebInspectorWindowController
301 - (id)init
302 {
303     if (!(self = [super initWithWindow:nil]))
304         return nil;
305
306     // Keep preferences separate from the rest of the client, making sure we are using expected preference values.
307
308     WebPreferences *preferences = [[WebPreferences alloc] init];
309     [preferences setAllowsAnimatedImages:YES];
310     [preferences setApplicationChromeModeEnabled:YES];
311     [preferences setAuthorAndUserStylesEnabled:YES];
312     [preferences setAutosaves:NO];
313     [preferences setDefaultFixedFontSize:11];
314     [preferences setFixedFontFamily:@"Menlo"];
315     [preferences setJavaEnabled:NO];
316     [preferences setJavaScriptEnabled:YES];
317     [preferences setLoadsImagesAutomatically:YES];
318     [preferences setMinimumFontSize:0];
319     [preferences setMinimumLogicalFontSize:9];
320     [preferences setPlugInsEnabled:NO];
321     [preferences setSuppressesIncrementalRendering:YES];
322     [preferences setTabsToLinks:NO];
323     [preferences setUserStyleSheetEnabled:NO];
324
325     _webView = [[WebView alloc] init];
326     [_webView setPreferences:preferences];
327     [_webView setDrawsBackground:NO];
328     [_webView setProhibitsMainFrameScrolling:YES];
329     [_webView setUIDelegate:self];
330     [_webView setPolicyDelegate:self];
331
332     [preferences release];
333
334     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL fileURLWithPath:[self inspectorPagePath]]];
335     [[_webView mainFrame] loadRequest:request];
336     [request release];
337
338     [self setWindowFrameAutosaveName:@"Web Inspector 2"];
339     return self;
340 }
341
342 - (id)initWithInspectedWebView:(WebView *)webView
343 {
344     if (!(self = [self init]))
345         return nil;
346
347     _inspectedWebView = webView;
348     return self;
349 }
350
351 - (void)dealloc
352 {
353     [_webView release];
354     [super dealloc];
355 }
356
357 // MARK: -
358
359 - (NSString *)inspectorPagePath
360 {
361     NSString *path;
362     if (useWebKitWebInspector())
363         path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"];
364     else
365         path = [[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"];
366
367     ASSERT([path length]);
368     return path;
369 }
370
371 // MARK: -
372
373 - (WebView *)webView
374 {
375     return _webView;
376 }
377
378 - (NSWindow *)window
379 {
380     WebInspectorWindow *window = (WebInspectorWindow *)[super window];
381     if (window)
382         return window;
383
384     NSUInteger styleMask = (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask | NSTexturedBackgroundWindowMask);
385     window = [[WebInspectorWindow alloc] initWithContentRect:NSMakeRect(60.0, 200.0, 750.0, 650.0) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
386     [window setDelegate:self];
387     [window setMinSize:NSMakeSize(400.0, 400.0)];
388     [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
389     [window setContentBorderThickness:55. forEdge:NSMaxYEdge];
390     WKNSWindowMakeBottomCornersSquare(window);
391
392     // Create a full screen button so we can turn it into a dock button.
393     _dockButton = [NSWindow standardWindowButton:NSWindowFullScreenButton forStyleMask:styleMask];
394     _dockButton.get().target = self;
395     _dockButton.get().action = @selector(attachWindow:);
396
397     // Store the dock button on the window too so it can check its visibility.
398     window->_dockButton = _dockButton;
399
400     // Get the dock image and make it a template so the button cell effects will apply.
401     NSImage *dockImage = [[NSBundle bundleForClass:[self class]] imageForResource:@"Dock"];
402     [dockImage setTemplate:YES];
403
404     // Set the dock image on the button cell.
405     NSCell *dockButtonCell = _dockButton.get().cell;
406     dockButtonCell.image = dockImage;
407
408     // Get the frame view, the superview of the content view, and its frame.
409     // This will be the superview of the dock button too.
410     NSView *contentView = window.contentView;
411     NSView *frameView = contentView.superview;
412     NSRect frameViewBounds = frameView.bounds;
413     NSSize dockButtonSize = _dockButton.get().frame.size;
414
415     ASSERT(!frameView.isFlipped);
416
417     // Position the dock button in the corner to match where the full screen button is normally.
418     NSPoint dockButtonOrigin;
419     dockButtonOrigin.x = NSMaxX(frameViewBounds) - dockButtonSize.width - dockButtonMargin;
420     dockButtonOrigin.y = NSMaxY(frameViewBounds) - dockButtonSize.height - dockButtonMargin;
421     _dockButton.get().frameOrigin = dockButtonOrigin;
422
423     // Set the autoresizing mask to keep the dock button pinned to the top right corner.
424     _dockButton.get().autoresizingMask = NSViewMinXMargin | NSViewMinYMargin;
425
426     [frameView addSubview:_dockButton.get()];
427
428     // Hide the dock button if we can't attach.
429     _dockButton.get().hidden = !_frontendClient->canAttachWindow();
430
431     [self setWindow:window];
432     [window release];
433
434     return window;
435 }
436
437 // MARK: -
438
439 - (BOOL)windowShouldClose:(id)sender
440 {
441     [self destroyInspectorView:true];
442
443     return YES;
444 }
445
446 - (void)close
447 {
448     if (!_visible)
449         return;
450
451     _visible = NO;
452
453     if (_attachedToInspectedWebView) {
454         if ([_inspectedWebView.get() _isClosed])
455             return;
456
457         [_webView removeFromSuperview];
458
459         WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
460         NSRect frameViewRect = [frameView frame];
461
462         // Setting the height based on the previous height is done to work with
463         // Safari's find banner. This assumes the previous height is the Y origin.
464         frameViewRect.size.height += NSMinY(frameViewRect);
465         frameViewRect.origin.y = 0.0;
466
467         [frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
468         [frameView setFrame:frameViewRect];
469
470         [_inspectedWebView.get() displayIfNeeded];
471     } else
472         [super close];
473 }
474
475 - (IBAction)attachWindow:(id)sender
476 {
477     _frontendClient->attachWindow();
478 }
479
480 - (IBAction)showWindow:(id)sender
481 {
482     if (_visible) {
483         if (!_attachedToInspectedWebView)
484             [super showWindow:sender]; // call super so the window will be ordered front if needed
485         return;
486     }
487
488     _visible = YES;
489     
490     _shouldAttach = _inspectorClient->inspectorStartsAttached();
491     
492     if (_shouldAttach && !_frontendClient->canAttachWindow())
493         _shouldAttach = NO;
494
495     if (_shouldAttach) {
496         WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
497
498         [_webView removeFromSuperview];
499         [_inspectedWebView.get() addSubview:_webView positioned:NSWindowBelow relativeTo:(NSView *)frameView];
500         [[_inspectedWebView.get() window] makeFirstResponder:_webView];
501
502         [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin)];
503         [frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMinYMargin)];
504
505         _attachedToInspectedWebView = YES;
506     } else {
507         _attachedToInspectedWebView = NO;
508
509         NSView *contentView = [[self window] contentView];
510         [_webView setFrame:[contentView frame]];
511         [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
512         [_webView removeFromSuperview];
513         [contentView addSubview:_webView];
514
515         [super showWindow:nil];
516     }
517 }
518
519 // MARK: -
520
521 - (void)attach
522 {
523     if (_attachedToInspectedWebView)
524         return;
525
526     _inspectorClient->setInspectorStartsAttached(true);
527     _frontendClient->setAttachedWindow(true);
528
529     [self close];
530     [self showWindow:nil];
531 }
532
533 - (void)detach
534 {
535     if (!_attachedToInspectedWebView)
536         return;
537
538     _inspectorClient->setInspectorStartsAttached(false);
539     _frontendClient->setAttachedWindow(false);
540
541     [self close];
542     [self showWindow:nil];
543 }
544
545 - (BOOL)attached
546 {
547     return _attachedToInspectedWebView;
548 }
549
550 - (void)setFrontendClient:(WebInspectorFrontendClient*)frontendClient
551 {
552     _frontendClient = frontendClient;
553 }
554
555 - (void)setInspectorClient:(WebInspectorClient*)inspectorClient
556 {
557     _inspectorClient = inspectorClient;
558 }
559
560 - (WebInspectorClient*)inspectorClient
561 {
562     return _inspectorClient;
563 }
564
565 - (void)setAttachedWindowHeight:(unsigned)height
566 {
567     if (!_attachedToInspectedWebView)
568         return;
569
570     WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
571     NSRect frameViewRect = [frameView frame];
572
573     // Setting the height based on the difference is done to work with
574     // Safari's find banner. This assumes the previous height is the Y origin.
575     CGFloat heightDifference = (NSMinY(frameViewRect) - height);
576     frameViewRect.size.height += heightDifference;
577     frameViewRect.origin.y = height;
578
579     [_webView setFrame:NSMakeRect(0.0, 0.0, NSWidth(frameViewRect), height)];
580     [frameView setFrame:frameViewRect];
581 }
582
583 - (void)setDockingUnavailable:(BOOL)unavailable
584 {
585     _dockButton.get().hidden = unavailable;
586 }
587
588 - (void)destroyInspectorView:(bool)notifyInspectorController
589 {
590     [[_inspectedWebView.get() inspector] releaseFrontend];
591     _inspectorClient->releaseFrontend();
592
593     if (_destroyingInspectorView)
594         return;
595     _destroyingInspectorView = YES;
596
597     if (_attachedToInspectedWebView)
598         [self close];
599
600     _visible = NO;
601
602     if (notifyInspectorController) {
603         if (Page* inspectedPage = [_inspectedWebView.get() page])
604             inspectedPage->inspectorController()->disconnectFrontend();
605     }
606
607     RetainPtr<WebInspectorWindowController> protect(self);
608     [_webView close];
609 }
610
611 // MARK: -
612 // MARK: UI delegate
613
614 - (NSUInteger)webView:(WebView *)sender dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
615 {
616     return WebDragDestinationActionNone;
617 }
618
619 // MARK: -
620 // MARK: Policy delegate
621
622 - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
623 {
624     // Allow non-main frames to navigate anywhere.
625     if (frame != [webView mainFrame]) {
626         [listener use];
627         return;
628     }
629
630     // Allow loading of the main inspector file.
631     if ([[request URL] isFileURL] && [[[request URL] path] isEqualToString:[self inspectorPagePath]]) {
632         [listener use];
633         return;
634     }
635
636     // Prevent everything else from loading in the inspector's page.
637     [listener ignore];
638
639     // And instead load it in the inspected page.
640     [[_inspectedWebView.get() mainFrame] loadRequest:request];
641 }
642
643 // MARK: -
644 // These methods can be used by UI elements such as menu items and toolbar buttons when the inspector is the key window.
645
646 // This method is really only implemented to keep any UI elements enabled.
647 - (void)showWebInspector:(id)sender
648 {
649     [[_inspectedWebView.get() inspector] show:sender];
650 }
651
652 - (void)showErrorConsole:(id)sender
653 {
654     [[_inspectedWebView.get() inspector] showConsole:sender];
655 }
656
657 - (void)toggleDebuggingJavaScript:(id)sender
658 {
659     [[_inspectedWebView.get() inspector] toggleDebuggingJavaScript:sender];
660 }
661
662 - (void)toggleProfilingJavaScript:(id)sender
663 {
664     [[_inspectedWebView.get() inspector] toggleProfilingJavaScript:sender];
665 }
666
667 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
668 {
669     BOOL isMenuItem = [(id)item isKindOfClass:[NSMenuItem class]];
670     if ([item action] == @selector(toggleDebuggingJavaScript:) && isMenuItem) {
671         NSMenuItem *menuItem = (NSMenuItem *)item;
672         if ([[_inspectedWebView.get() inspector] isDebuggingJavaScript])
673             [menuItem setTitle:UI_STRING_INTERNAL("Stop Debugging JavaScript", "title for Stop Debugging JavaScript menu item")];
674         else
675             [menuItem setTitle:UI_STRING_INTERNAL("Start Debugging JavaScript", "title for Start Debugging JavaScript menu item")];
676     } else if ([item action] == @selector(toggleProfilingJavaScript:) && isMenuItem) {
677         NSMenuItem *menuItem = (NSMenuItem *)item;
678         if ([[_inspectedWebView.get() inspector] isProfilingJavaScript])
679             [menuItem setTitle:UI_STRING_INTERNAL("Stop Profiling JavaScript", "title for Stop Profiling JavaScript menu item")];
680         else
681             [menuItem setTitle:UI_STRING_INTERNAL("Start Profiling JavaScript", "title for Start Profiling JavaScript menu item")];
682     }
683
684     return YES;
685 }
686
687
688 @end