blob: c89579e8c54ebec6b083d8ae6047abb2f069da6d [file] [log] [blame]
/*
* Copyright (C) 2006, 2007, 2008 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.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "WebInspectorClient.h"
#import "DOMNodeInternal.h"
#import "WebDelegateImplementationCaching.h"
#import "WebFrameInternal.h"
#import "WebFrameView.h"
#import "WebInspector.h"
#import "WebInspectorPrivate.h"
#import "WebInspectorFrontend.h"
#import "WebLocalizableStringsInternal.h"
#import "WebNodeHighlighter.h"
#import "WebUIDelegate.h"
#import "WebPolicyDelegate.h"
#import "WebViewInternal.h"
#import <WebCore/Frame.h>
#import <WebCore/InspectorController.h>
#import <WebCore/Page.h>
#import <WebCore/ScriptValue.h>
#import <WebCore/SoftLinking.h>
#import <WebKit/DOMExtensions.h>
#import <WebKitSystemInterface.h>
#import <wtf/PassOwnPtr.h>
SOFT_LINK_STAGED_FRAMEWORK_OPTIONAL(WebInspector, PrivateFrameworks, A)
// The margin from the top and right of the dock button (same as the full screen button).
static const CGFloat dockButtonMargin = 3;
using namespace WebCore;
@interface NSWindow (AppKitDetails)
- (NSCursor *)_cursorForResizeDirection:(NSInteger)direction;
- (NSRect)_customTitleFrame;
@end
@interface WebInspectorWindow : NSWindow {
@public
RetainPtr<NSButton> _dockButton;
}
@end
@implementation WebInspectorWindow
- (NSCursor *)_cursorForResizeDirection:(NSInteger)direction
{
// Don't show a resize cursor for the northeast (top right) direction if the dock button is visible.
// This matches what happens when the full screen button is visible.
if (direction == 1 && ![_dockButton isHidden])
return nil;
return [super _cursorForResizeDirection:direction];
}
- (NSRect)_customTitleFrame
{
// Adjust the title frame if needed to prevent it from intersecting the dock button.
NSRect titleFrame = [super _customTitleFrame];
NSRect dockButtonFrame = _dockButton.get().frame;
if (NSMaxX(titleFrame) > NSMinX(dockButtonFrame) - dockButtonMargin)
titleFrame.size.width -= (NSMaxX(titleFrame) - NSMinX(dockButtonFrame)) + dockButtonMargin;
return titleFrame;
}
@end
@interface WebInspectorWindowController : NSWindowController <NSWindowDelegate> {
@private
RetainPtr<WebView> _inspectedWebView;
RetainPtr<NSButton> _dockButton;
WebView *_webView;
WebInspectorFrontendClient* _frontendClient;
WebInspectorClient* _inspectorClient;
BOOL _attachedToInspectedWebView;
BOOL _shouldAttach;
BOOL _visible;
BOOL _destroyingInspectorView;
}
- (id)initWithInspectedWebView:(WebView *)webView;
- (NSString *)inspectorPagePath;
- (WebView *)webView;
- (void)attach;
- (void)detach;
- (BOOL)attached;
- (void)setFrontendClient:(WebInspectorFrontendClient*)frontendClient;
- (void)setInspectorClient:(WebInspectorClient*)inspectorClient;
- (WebInspectorClient*)inspectorClient;
- (void)setAttachedWindowHeight:(unsigned)height;
- (void)setDockingUnavailable:(BOOL)unavailable;
- (void)destroyInspectorView:(bool)notifyInspectorController;
@end
// MARK: -
WebInspectorClient::WebInspectorClient(WebView *webView)
: m_webView(webView)
, m_highlighter(AdoptNS, [[WebNodeHighlighter alloc] initWithInspectedWebView:webView])
, m_frontendPage(0)
, m_frontendClient(0)
{
}
void WebInspectorClient::inspectorDestroyed()
{
closeInspectorFrontend();
delete this;
}
InspectorFrontendChannel* WebInspectorClient::openInspectorFrontend(InspectorController* inspectorController)
{
RetainPtr<WebInspectorWindowController> windowController(AdoptNS, [[WebInspectorWindowController alloc] initWithInspectedWebView:m_webView]);
[windowController.get() setInspectorClient:this];
m_frontendPage = core([windowController.get() webView]);
OwnPtr<WebInspectorFrontendClient> frontendClient = adoptPtr(new WebInspectorFrontendClient(m_webView, windowController.get(), inspectorController, m_frontendPage, createFrontendSettings()));
m_frontendClient = frontendClient.get();
RetainPtr<WebInspectorFrontend> webInspectorFrontend(AdoptNS, [[WebInspectorFrontend alloc] initWithFrontendClient:frontendClient.get()]);
[[m_webView inspector] setFrontend:webInspectorFrontend.get()];
m_frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
return this;
}
void WebInspectorClient::closeInspectorFrontend()
{
if (m_frontendClient)
m_frontendClient->disconnectFromBackend();
}
void WebInspectorClient::bringFrontendToFront()
{
m_frontendClient->bringToFront();
}
void WebInspectorClient::didResizeMainFrame(Frame*)
{
if (m_frontendClient)
m_frontendClient->attachAvailabilityChanged(m_frontendClient->canAttachWindow());
}
void WebInspectorClient::highlight()
{
[m_highlighter.get() highlight];
}
void WebInspectorClient::hideHighlight()
{
[m_highlighter.get() hideHighlight];
}
void WebInspectorClient::releaseFrontend()
{
m_frontendClient = 0;
m_frontendPage = 0;
}
WebInspectorFrontendClient::WebInspectorFrontendClient(WebView* inspectedWebView, WebInspectorWindowController* windowController, InspectorController* inspectorController, Page* frontendPage, WTF::PassOwnPtr<Settings> settings)
: InspectorFrontendClientLocal(inspectorController, frontendPage, settings)
, m_inspectedWebView(inspectedWebView)
, m_windowController(windowController)
{
[windowController setFrontendClient:this];
}
void WebInspectorFrontendClient::attachAvailabilityChanged(bool available)
{
setDockingUnavailable(!available);
[m_windowController.get() setDockingUnavailable:!available];
}
void WebInspectorFrontendClient::frontendLoaded()
{
[m_windowController.get() showWindow:nil];
if ([m_windowController.get() attached])
restoreAttachedWindowHeight();
InspectorFrontendClientLocal::frontendLoaded();
WebFrame *frame = [m_inspectedWebView mainFrame];
WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(m_inspectedWebView);
if (implementations->didClearInspectorWindowObjectForFrameFunc)
CallFrameLoadDelegate(implementations->didClearInspectorWindowObjectForFrameFunc, m_inspectedWebView,
@selector(webView:didClearInspectorWindowObject:forFrame:), [frame windowObject], frame);
bool attached = [m_windowController.get() attached];
setAttachedWindow(attached);
}
static bool useWebKitWebInspector()
{
// Call the soft link framework function to dlopen it, then [NSBundle bundleWithIdentifier:] will work.
WebInspectorLibrary();
if (![[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"])
return true;
if (![[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"])
return false;
return [[NSUserDefaults standardUserDefaults] boolForKey:@"UseWebKitWebInspector"];
}
String WebInspectorFrontendClient::localizedStringsURL()
{
NSBundle *bundle = useWebKitWebInspector() ? [NSBundle bundleWithIdentifier:@"com.apple.WebCore"] : [NSBundle bundleWithIdentifier:@"com.apple.WebInspector"];
NSString *path = [bundle pathForResource:@"localizedStrings" ofType:@"js"];
if ([path length])
return [[NSURL fileURLWithPath:path] absoluteString];
return String();
}
void WebInspectorFrontendClient::bringToFront()
{
updateWindowTitle();
[m_windowController.get() showWindow:nil];
// Use the window from the WebView since m_windowController's window
// is not the same when the Inspector is docked.
WebView *webView = [m_windowController.get() webView];
[[webView window] makeFirstResponder:webView];
}
void WebInspectorFrontendClient::closeWindow()
{
[m_windowController.get() destroyInspectorView:true];
}
void WebInspectorFrontendClient::disconnectFromBackend()
{
[m_windowController.get() destroyInspectorView:false];
}
void WebInspectorFrontendClient::attachWindow()
{
if ([m_windowController.get() attached])
return;
[m_windowController.get() attach];
restoreAttachedWindowHeight();
}
void WebInspectorFrontendClient::detachWindow()
{
[m_windowController.get() detach];
}
void WebInspectorFrontendClient::setAttachedWindowHeight(unsigned height)
{
[m_windowController.get() setAttachedWindowHeight:height];
}
void WebInspectorFrontendClient::inspectedURLChanged(const String& newURL)
{
m_inspectedURL = newURL;
updateWindowTitle();
}
void WebInspectorFrontendClient::updateWindowTitle() const
{
NSString *title = [NSString stringWithFormat:UI_STRING_INTERNAL("Web Inspector — %@", "Web Inspector window title"), (NSString *)m_inspectedURL];
[[m_windowController.get() window] setTitle:title];
}
void WebInspectorFrontendClient::save(const String& refURL, const String& refContent, bool forceSaveAs)
{
String url = refURL;
String content = refContent;
auto saveToURL = ^(NSURL *URL) {
m_saveURLs.set(url, URL);
[content writeToURL:URL atomically:YES encoding:NSUTF8StringEncoding error:NULL];
core([m_windowController webView])->mainFrame()->script()->executeScript([NSString stringWithFormat:@"InspectorFrontendAPI.savedURL(\"%@\")", URL.absoluteString]);
};
NSURL *URL = m_saveURLs.get(url).get();
if (!URL)
URL = [NSURL URLWithString:url];
else if (!forceSaveAs) {
saveToURL(URL);
return;
}
NSSavePanel *panel = [NSSavePanel savePanel];
panel.nameFieldStringValue = URL.lastPathComponent;
panel.directoryURL = [URL URLByDeletingLastPathComponent];
[panel beginSheetModalForWindow:[[m_windowController webView] window] completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelCancelButton)
return;
ASSERT(result == NSFileHandlingPanelOKButton);
saveToURL(panel.URL);
}];
}
void WebInspectorFrontendClient::append(const String& url, const String& content)
{
RetainPtr<NSURL> URL = m_saveURLs.get(url);
if (!URL)
URL = [NSURL URLWithString:url];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:URL.get() error:NULL];
[handle seekToEndOfFile];
[handle writeData:[content dataUsingEncoding:NSUTF8StringEncoding]];
[handle closeFile];
core([m_windowController webView])->mainFrame()->script()->executeScript([NSString stringWithFormat:@"InspectorFrontendAPI.appendedToURL(\"%@\")", [URL absoluteString]]);
}
// MARK: -
@implementation WebInspectorWindowController
- (id)init
{
if (!(self = [super initWithWindow:nil]))
return nil;
// Keep preferences separate from the rest of the client, making sure we are using expected preference values.
WebPreferences *preferences = [[WebPreferences alloc] init];
[preferences setAllowsAnimatedImages:YES];
[preferences setApplicationChromeModeEnabled:YES];
[preferences setAuthorAndUserStylesEnabled:YES];
[preferences setAutosaves:NO];
[preferences setDefaultFixedFontSize:11];
[preferences setFixedFontFamily:@"Menlo"];
[preferences setJavaEnabled:NO];
[preferences setJavaScriptEnabled:YES];
[preferences setLoadsImagesAutomatically:YES];
[preferences setMinimumFontSize:0];
[preferences setMinimumLogicalFontSize:9];
[preferences setPlugInsEnabled:NO];
[preferences setTabsToLinks:NO];
[preferences setUserStyleSheetEnabled:NO];
_webView = [[WebView alloc] init];
[_webView setPreferences:preferences];
[_webView setDrawsBackground:NO];
[_webView setProhibitsMainFrameScrolling:YES];
[_webView setUIDelegate:self];
[_webView setPolicyDelegate:self];
[preferences release];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL fileURLWithPath:[self inspectorPagePath]]];
[[_webView mainFrame] loadRequest:request];
[request release];
[self setWindowFrameAutosaveName:@"Web Inspector 2"];
return self;
}
- (id)initWithInspectedWebView:(WebView *)webView
{
if (!(self = [self init]))
return nil;
_inspectedWebView = webView;
return self;
}
- (void)dealloc
{
[_webView release];
[super dealloc];
}
// MARK: -
- (NSString *)inspectorPagePath
{
NSString *path;
if (useWebKitWebInspector())
path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"];
else
path = [[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"];
ASSERT([path length]);
return path;
}
// MARK: -
- (WebView *)webView
{
return _webView;
}
- (NSWindow *)window
{
WebInspectorWindow *window = (WebInspectorWindow *)[super window];
if (window)
return window;
NSUInteger styleMask = (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask | NSTexturedBackgroundWindowMask);
window = [[WebInspectorWindow alloc] initWithContentRect:NSMakeRect(60.0, 200.0, 750.0, 650.0) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
[window setDelegate:self];
[window setMinSize:NSMakeSize(400.0, 400.0)];
[window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
[window setContentBorderThickness:55. forEdge:NSMaxYEdge];
WKNSWindowMakeBottomCornersSquare(window);
// Create a full screen button so we can turn it into a dock button.
_dockButton = [NSWindow standardWindowButton:NSWindowFullScreenButton forStyleMask:styleMask];
_dockButton.get().target = self;
_dockButton.get().action = @selector(attachWindow:);
// Store the dock button on the window too so it can check its visibility.
window->_dockButton = _dockButton;
// Get the dock image and make it a template so the button cell effects will apply.
NSImage *dockImage = [[NSBundle bundleForClass:[self class]] imageForResource:@"Dock"];
[dockImage setTemplate:YES];
// Set the dock image on the button cell.
NSCell *dockButtonCell = _dockButton.get().cell;
dockButtonCell.image = dockImage;
// Get the frame view, the superview of the content view, and its frame.
// This will be the superview of the dock button too.
NSView *contentView = window.contentView;
NSView *frameView = contentView.superview;
NSRect frameViewBounds = frameView.bounds;
NSSize dockButtonSize = _dockButton.get().frame.size;
ASSERT(!frameView.isFlipped);
// Position the dock button in the corner to match where the full screen button is normally.
NSPoint dockButtonOrigin;
dockButtonOrigin.x = NSMaxX(frameViewBounds) - dockButtonSize.width - dockButtonMargin;
dockButtonOrigin.y = NSMaxY(frameViewBounds) - dockButtonSize.height - dockButtonMargin;
_dockButton.get().frameOrigin = dockButtonOrigin;
// Set the autoresizing mask to keep the dock button pinned to the top right corner.
_dockButton.get().autoresizingMask = NSViewMinXMargin | NSViewMinYMargin;
[frameView addSubview:_dockButton.get()];
// Hide the dock button if we can't attach.
_dockButton.get().hidden = !_frontendClient->canAttachWindow();
[self setWindow:window];
[window release];
return window;
}
// MARK: -
- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect
{
// AppKit doesn't know about our HTML toolbar, and places the sheet just a little bit too high.
// FIXME: It would be better to get the height of the toolbar and use it in this calculation.
rect.origin.y -= 1;
return rect;
}
- (BOOL)windowShouldClose:(id)sender
{
[self destroyInspectorView:true];
return YES;
}
- (void)close
{
if (!_visible)
return;
_visible = NO;
if (_attachedToInspectedWebView) {
if ([_inspectedWebView.get() _isClosed])
return;
[_webView removeFromSuperview];
WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
NSRect frameViewRect = [frameView frame];
// Setting the height based on the previous height is done to work with
// Safari's find banner. This assumes the previous height is the Y origin.
frameViewRect.size.height += NSMinY(frameViewRect);
frameViewRect.origin.y = 0.0;
[frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[frameView setFrame:frameViewRect];
[_inspectedWebView.get() displayIfNeeded];
} else
[super close];
}
- (IBAction)attachWindow:(id)sender
{
_frontendClient->attachWindow();
}
- (IBAction)showWindow:(id)sender
{
if (_visible) {
if (!_attachedToInspectedWebView)
[super showWindow:sender]; // call super so the window will be ordered front if needed
return;
}
_visible = YES;
_shouldAttach = _inspectorClient->inspectorStartsAttached();
if (_shouldAttach && !_frontendClient->canAttachWindow())
_shouldAttach = NO;
if (_shouldAttach) {
WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
[_webView removeFromSuperview];
[_inspectedWebView.get() addSubview:_webView positioned:NSWindowBelow relativeTo:(NSView *)frameView];
[[_inspectedWebView.get() window] makeFirstResponder:_webView];
[_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin)];
[frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMinYMargin)];
_attachedToInspectedWebView = YES;
} else {
_attachedToInspectedWebView = NO;
NSView *contentView = [[self window] contentView];
[_webView setFrame:[contentView frame]];
[_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[_webView removeFromSuperview];
[contentView addSubview:_webView];
[super showWindow:nil];
}
}
// MARK: -
- (void)attach
{
if (_attachedToInspectedWebView)
return;
_inspectorClient->setInspectorStartsAttached(true);
_frontendClient->setAttachedWindow(true);
[self close];
[self showWindow:nil];
}
- (void)detach
{
if (!_attachedToInspectedWebView)
return;
_inspectorClient->setInspectorStartsAttached(false);
_frontendClient->setAttachedWindow(false);
[self close];
[self showWindow:nil];
}
- (BOOL)attached
{
return _attachedToInspectedWebView;
}
- (void)setFrontendClient:(WebInspectorFrontendClient*)frontendClient
{
_frontendClient = frontendClient;
}
- (void)setInspectorClient:(WebInspectorClient*)inspectorClient
{
_inspectorClient = inspectorClient;
}
- (WebInspectorClient*)inspectorClient
{
return _inspectorClient;
}
- (void)setAttachedWindowHeight:(unsigned)height
{
if (!_attachedToInspectedWebView)
return;
WebFrameView *frameView = [[_inspectedWebView.get() mainFrame] frameView];
NSRect frameViewRect = [frameView frame];
// Setting the height based on the difference is done to work with
// Safari's find banner. This assumes the previous height is the Y origin.
CGFloat heightDifference = (NSMinY(frameViewRect) - height);
frameViewRect.size.height += heightDifference;
frameViewRect.origin.y = height;
[_webView setFrame:NSMakeRect(0.0, 0.0, NSWidth(frameViewRect), height)];
[frameView setFrame:frameViewRect];
}
- (void)setDockingUnavailable:(BOOL)unavailable
{
_dockButton.get().hidden = unavailable;
}
- (void)destroyInspectorView:(bool)notifyInspectorController
{
[[_inspectedWebView.get() inspector] releaseFrontend];
_inspectorClient->releaseFrontend();
if (_destroyingInspectorView)
return;
_destroyingInspectorView = YES;
if (_attachedToInspectedWebView)
[self close];
_visible = NO;
if (notifyInspectorController) {
if (Page* inspectedPage = [_inspectedWebView.get() page])
inspectedPage->inspectorController()->disconnectFrontend();
}
RetainPtr<WebInspectorWindowController> protect(self);
[_webView close];
}
// MARK: -
// MARK: UI delegate
- (NSUInteger)webView:(WebView *)sender dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo
{
return WebDragDestinationActionNone;
}
- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
panel.canChooseDirectories = NO;
panel.canChooseFiles = YES;
panel.allowsMultipleSelection = allowMultipleFiles;
[panel beginSheetModalForWindow:_webView.window completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelCancelButton) {
[resultListener cancel];
return;
}
ASSERT(result == NSFileHandlingPanelOKButton);
NSArray *URLs = panel.URLs;
NSMutableArray *filenames = [NSMutableArray arrayWithCapacity:URLs.count];
for (NSURL *URL in URLs) {
[filenames addObject:URL.path];
}
[resultListener chooseFilenames:filenames];
}];
}
// MARK: -
// MARK: Policy delegate
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
{
// Allow non-main frames to navigate anywhere.
if (frame != [webView mainFrame]) {
[listener use];
return;
}
// Allow loading of the main inspector file.
if ([[request URL] isFileURL] && [[[request URL] path] isEqualToString:[self inspectorPagePath]]) {
[listener use];
return;
}
// Prevent everything else from loading in the inspector's page.
[listener ignore];
// And instead load it in the inspected page.
[[_inspectedWebView.get() mainFrame] loadRequest:request];
}
// MARK: -
// These methods can be used by UI elements such as menu items and toolbar buttons when the inspector is the key window.
// This method is really only implemented to keep any UI elements enabled.
- (void)showWebInspector:(id)sender
{
[[_inspectedWebView.get() inspector] show:sender];
}
- (void)showErrorConsole:(id)sender
{
[[_inspectedWebView.get() inspector] showConsole:sender];
}
- (void)toggleDebuggingJavaScript:(id)sender
{
[[_inspectedWebView.get() inspector] toggleDebuggingJavaScript:sender];
}
- (void)toggleProfilingJavaScript:(id)sender
{
[[_inspectedWebView.get() inspector] toggleProfilingJavaScript:sender];
}
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
{
BOOL isMenuItem = [(id)item isKindOfClass:[NSMenuItem class]];
if ([item action] == @selector(toggleDebuggingJavaScript:) && isMenuItem) {
NSMenuItem *menuItem = (NSMenuItem *)item;
if ([[_inspectedWebView.get() inspector] isDebuggingJavaScript])
[menuItem setTitle:UI_STRING_INTERNAL("Stop Debugging JavaScript", "title for Stop Debugging JavaScript menu item")];
else
[menuItem setTitle:UI_STRING_INTERNAL("Start Debugging JavaScript", "title for Start Debugging JavaScript menu item")];
} else if ([item action] == @selector(toggleProfilingJavaScript:) && isMenuItem) {
NSMenuItem *menuItem = (NSMenuItem *)item;
if ([[_inspectedWebView.get() inspector] isProfilingJavaScript])
[menuItem setTitle:UI_STRING_INTERNAL("Stop Profiling JavaScript", "title for Stop Profiling JavaScript menu item")];
else
[menuItem setTitle:UI_STRING_INTERNAL("Start Profiling JavaScript", "title for Start Profiling JavaScript menu item")];
}
return YES;
}
@end