diff options
author | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-23 16:00:25 +0000 |
---|---|---|
committer | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-23 16:00:25 +0000 |
commit | 68b1e92848aebead28f92118e698a1b644d6f572 (patch) | |
tree | ed7d70696afd92878d2637ab9bd47c7ab87a9f9f /chrome | |
parent | eb888d2f99d7de22640caa2da7cd707261afc2e4 (diff) | |
download | chromium_src-68b1e92848aebead28f92118e698a1b644d6f572.zip chromium_src-68b1e92848aebead28f92118e698a1b644d6f572.tar.gz chromium_src-68b1e92848aebead28f92118e698a1b644d6f572.tar.bz2 |
Re-land r18853
Review URL: http://codereview.chromium.org/141008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19023 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/cocoa/rwhvm_editcommand_helper.h | 65 | ||||
-rw-r--r-- | chrome/browser/cocoa/rwhvm_editcommand_helper.mm | 224 | ||||
-rw-r--r-- | chrome/browser/cocoa/rwhvm_editcommand_helper_unittest.mm | 172 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 8 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.cc | 7 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.h | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.h | 10 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 15 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 1 |
13 files changed, 522 insertions, 1 deletions
diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper.h b/chrome/browser/cocoa/rwhvm_editcommand_helper.h new file mode 100644 index 0000000..aa948db --- /dev/null +++ b/chrome/browser/cocoa/rwhvm_editcommand_helper.h @@ -0,0 +1,65 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_RWHVM_EDITCOMMAND_HELPER_H_ +#define CHROME_BROWSER_COCOA_RWHVM_EDITCOMMAND_HELPER_H_ + +#import <Cocoa/Cocoa.h> + +#include "base/hash_tables.h" +#include "base/logging.h" +#include "chrome/browser/renderer_host/render_widget_host_view_mac.h" +#include "testing/gtest/include/gtest/gtest_prod.h" + +// RenderWidgetHostViewMacEditCommandHelper is the real name of this class +// but that's too long, so we use a shorter version. +// +// This class mimics the behavior of WebKit's WebView class in a way that makes +// sense for Chrome. +// +// WebCore has the concept of "core commands", basically named actions such as +// "Select All" and "Move Cursor Left". The commands are executed using their +// string value by WebCore. +// +// This class is responsible for 2 things: +// 1. Provide an abstraction to determine the enabled/disabled state of menu +// items that correspond to edit commands. +// 2. Hook up a bunch of objc selectors to the RenderWidgetHostViewCocoa object. +// (note that this is not a misspelling of RenderWidgetHostViewMac, it's in +// fact a distinct object) When these selectors are called, the relevant +// edit command is executed in WebCore. +class RWHVMEditCommandHelper { + FRIEND_TEST(RWHVMEditCommandHelperTest, TestAddEditingSelectorsToClass); + FRIEND_TEST(RWHVMEditCommandHelperTest, TestEditingCommandDelivery); + + public: + RWHVMEditCommandHelper(); + + // Adds editing selectors to the objc class using the objc runtime APIs. + // Each selector is connected to a single c method which forwards the message + // to WebCore's ExecuteCoreCommand() function. + // This method is idempotent. + // The class passed in must conform to the RenderWidgetHostViewMacOwner + // protocol. + void AddEditingSelectorsToClass(Class klass); + + // Is a given menu item currently enabled? + // SEL - the objc selector currently associated with an NSMenuItem. + // owner - An object we can retrieve a RenderWidgetHostViewMac from to + // determine the command states. + bool IsMenuItemEnabled(SEL item_action, + id<RenderWidgetHostViewMacOwner> owner); + + protected: + // Gets a list of all the selectors that AddEditingSelectorsToClass adds to + // the aforementioned class. + // returns an array of NSStrings WITHOUT the trailing ':'s. + NSArray* GetEditSelectorNames(); + + private: + base::hash_set<std::string> edit_command_set_; + DISALLOW_COPY_AND_ASSIGN(RWHVMEditCommandHelper); +}; + +#endif // CHROME_BROWSER_COCOA_RWHVM_EDITCOMMAND_HELPER_H_ diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper.mm b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm new file mode 100644 index 0000000..87956b0 --- /dev/null +++ b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm @@ -0,0 +1,224 @@ +// Copyright (c), 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" + +#import <objc/runtime.h> + +#include "chrome/browser/renderer_host/render_widget_host.h" +#import "chrome/browser/renderer_host/render_widget_host_view_mac.h" + +namespace { +// The names of all the objc selectors w/o ':'s added to an object by +// AddEditingSelectorsToClass(). +// +// This needs to be kept in Sync with WEB_COMMAND list in the WebKit tree at: +// WebKit/mac/WebView/WebHTMLView.mm . +const char* kEditCommands[] = { + "alignCenter", + "alignJustified", + "alignLeft", + "alignRight", + "copy", + "cut", + "delete", + "deleteBackward", + "deleteBackwardByDecomposingPreviousCharacter", + "deleteForward", + "deleteToBeginningOfLine", + "deleteToBeginningOfParagraph", + "deleteToEndOfLine", + "deleteToEndOfParagraph", + "deleteToMark", + "deleteWordBackward", + "deleteWordForward", + "ignoreSpelling", + "indent", + "insertBacktab", + "insertLineBreak", + "insertNewline", + "insertNewlineIgnoringFieldEditor", + "insertParagraphSeparator", + "insertTab", + "insertTabIgnoringFieldEditor", + "makeTextWritingDirectionLeftToRight", + "makeTextWritingDirectionNatural", + "makeTextWritingDirectionRightToLeft", + "moveBackward", + "moveBackwardAndModifySelection", + "moveDown", + "moveDownAndModifySelection", + "moveForward", + "moveForwardAndModifySelection", + "moveLeft", + "moveLeftAndModifySelection", + "moveParagraphBackwardAndModifySelection", + "moveParagraphForwardAndModifySelection", + "moveRight", + "moveRightAndModifySelection", + "moveToBeginningOfDocument", + "moveToBeginningOfDocumentAndModifySelection", + "moveToBeginningOfLine", + "moveToBeginningOfLineAndModifySelection", + "moveToBeginningOfParagraph", + "moveToBeginningOfParagraphAndModifySelection", + "moveToBeginningOfSentence", + "moveToBeginningOfSentenceAndModifySelection", + "moveToEndOfDocument", + "moveToEndOfDocumentAndModifySelection", + "moveToEndOfLine", + "moveToEndOfLineAndModifySelection", + "moveToEndOfParagraph", + "moveToEndOfParagraphAndModifySelection", + "moveToEndOfSentence", + "moveToEndOfSentenceAndModifySelection", + "moveUp", + "moveUpAndModifySelection", + "moveWordBackward", + "moveWordBackwardAndModifySelection", + "moveWordForward", + "moveWordForwardAndModifySelection", + "moveWordLeft", + "moveWordLeftAndModifySelection", + "moveWordRight", + "moveWordRightAndModifySelection", + "outdent", + "pageDown", + "pageDownAndModifySelection", + "pageUp", + "pageUpAndModifySelection", + "selectAll", + "selectLine", + "selectParagraph", + "selectSentence", + "selectToMark", + "selectWord", + "setMark", + "subscript", + "superscript", + "swapWithMark", + "transpose", + "underline", + "unscript", + "yank", + "yankAndSelect"}; + +// Maps an objc-selector to a core command name. +// +// Returns the core command name (which is the selector name with the trailing +// ':' stripped in most cases). +// +// Adapted from a function by the same name in +// WebKit/mac/WebView/WebHTMLView.mm . +// Capitalized names are returned from this function, but that's simply +// matching WebHTMLView.mm. +NSString* CommandNameForSelector(SEL selector) { + if (selector == @selector(insertParagraphSeparator:) || + selector == @selector(insertNewlineIgnoringFieldEditor:)) + return @"InsertNewline"; + if (selector == @selector(insertTabIgnoringFieldEditor:)) + return @"InsertTab"; + if (selector == @selector(pageDown:)) + return @"MovePageDown"; + if (selector == @selector(pageDownAndModifySelection:)) + return @"MovePageDownAndModifySelection"; + if (selector == @selector(pageUp:)) + return @"MovePageUp"; + if (selector == @selector(pageUpAndModifySelection:)) + return @"MovePageUpAndModifySelection"; + + // Remove the trailing colon. + NSString* selector_str = NSStringFromSelector(selector); + int selector_len = [selector_str length]; + return [selector_str substringToIndex:selector_len - 1]; +} + +// This function is installed via the objc runtime as the implementation of all +// the various editing selectors. +// The objc runtime hookup occurs in +// RWHVMEditCommandHelper::AddEditingSelectorsToClass(). +// +// self - the object we're attached to; it must implement the +// RenderWidgetHostViewMacOwner protocol. +// _cmd - the selector that fired. +// sender - the id of the object that sent the message. +// +// The selector is translated into an edit comand and then forwarded down the +// pipeline to WebCore. +// The route the message takes is: +// RenderWidgetHostViewMac -> RenderViewHost -> +// | IPC | -> +// RenderView -> currently focused WebFrame. +// The WebFrame is in the Chrome glue layer and forwards the message to WebCore. +void EditCommandImp(id self, SEL _cmd, id sender) { + // Make sure |self| is the right type. + DCHECK([self conformsToProtocol:@protocol(RenderWidgetHostViewMacOwner)]); + + // SEL -> command name string. + NSString* command_name_ns = CommandNameForSelector(_cmd); + std::string edit_command([command_name_ns UTF8String]); + + // Forward the edit command string down the pipeline. + RenderWidgetHostViewMac* rwhv = [(id<RenderWidgetHostViewMacOwner>)self + renderWidgetHostViewMac]; + DCHECK(rwhv); + + // The second parameter is the core command value which isn't used here. + rwhv->GetRenderWidgetHost()->ForwardEditCommand(edit_command, ""); +} + +} // namespace + +RWHVMEditCommandHelper::RWHVMEditCommandHelper() { + for (size_t i = 0; i < arraysize(kEditCommands); ++i) { + edit_command_set_.insert(kEditCommands[i]); + } +} + +// Dynamically adds Selectors to the aformentioned class. +void RWHVMEditCommandHelper::AddEditingSelectorsToClass(Class klass) { + for (size_t i = 0; i < arraysize(kEditCommands); ++i) { + // Append trailing ':' to command name to get selector name. + NSString* sel_str = [NSString stringWithFormat: @"%s:", kEditCommands[i]]; + + SEL edit_selector = NSSelectorFromString(sel_str); + // May want to use @encode() for the last parameter to this method. + // If class_addMethod fails we assume that all the editing selectors where + // added to the class. + // If a certain class already implements a method then class_addMethod + // returns NO, which we can safely ignore. + class_addMethod(klass, edit_selector, (IMP)EditCommandImp, "v@:@"); + } +} + +bool RWHVMEditCommandHelper::IsMenuItemEnabled(SEL item_action, + id<RenderWidgetHostViewMacOwner> owner) { + const char* selector_name = sel_getName(item_action); + // TODO(jeremy): The final form of this function will check state + // associated with the Browser. + + // For now just mark all edit commands as enabled. + NSString* selector_name_ns = [NSString stringWithUTF8String:selector_name]; + + // Remove trailing ':' + size_t str_len = [selector_name_ns length]; + selector_name_ns = [selector_name_ns substringToIndex:str_len - 1]; + std::string edit_command_name([selector_name_ns UTF8String]); + + // search for presence in set and return. + bool ret = edit_command_set_.find(edit_command_name) != + edit_command_set_.end(); + return ret; +} + +NSArray* RWHVMEditCommandHelper::GetEditSelectorNames() { + size_t num_edit_commands = arraysize(kEditCommands); + NSMutableArray* ret = [NSMutableArray arrayWithCapacity:num_edit_commands]; + + for (size_t i = 0; i < num_edit_commands; ++i) { + [ret addObject:[NSString stringWithUTF8String:kEditCommands[i]]]; + } + + return ret; +} diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper_unittest.mm b/chrome/browser/cocoa/rwhvm_editcommand_helper_unittest.mm new file mode 100644 index 0000000..4fd5452 --- /dev/null +++ b/chrome/browser/cocoa/rwhvm_editcommand_helper_unittest.mm @@ -0,0 +1,172 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" + +#import <Cocoa/Cocoa.h> + +#include "chrome/browser/renderer_host/mock_render_process_host.h" +#include "chrome/browser/renderer_host/render_widget_host.h" +#include "chrome/test/testing_profile.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +class RWHVMEditCommandHelperTest : public PlatformTest { +}; + +// Bare bones obj-c class for testing purposes. +@interface RWHVMEditCommandHelperTestClass : NSObject +@end + +@implementation RWHVMEditCommandHelperTestClass +@end + +// Class that owns a RenderWidgetHostViewMac. +@interface RenderWidgetHostViewMacOwner : + NSObject<RenderWidgetHostViewMacOwner> { + RenderWidgetHostViewMac* rwhvm_; +} + +- (id) initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)rwhvm; +@end + +@implementation RenderWidgetHostViewMacOwner + +- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)rwhvm { + if ((self = [super init])) { + rwhvm_ = rwhvm; + } + return self; +} + +- (RenderWidgetHostViewMac*)renderWidgetHostViewMac { + return rwhvm_; +} + +@end + + +namespace { + // Returns true if all the edit command names in the array are present + // in test_obj. + // edit_commands is a list of NSStrings, selector names are formed by + // appending a trailing ':' to the string. + bool CheckObjectRespondsToEditCommands(NSArray* edit_commands, id test_obj) { + for (NSString* edit_command_name in edit_commands) { + NSString* sel_str = [edit_command_name stringByAppendingString:@":"]; + if (![test_obj respondsToSelector:NSSelectorFromString(sel_str)]) { + return false; + } + } + + return true; + } +} // namespace + +// Create a Mock RenderWidget +class MockRenderWidgetHostEditCommandCounter : public RenderWidgetHost { + public: + MockRenderWidgetHostEditCommandCounter(RenderProcessHost* process, + int routing_id) : + RenderWidgetHost(process, routing_id) {} + + MOCK_METHOD2(ForwardEditCommand, void(const std::string&, + const std::string&)); +}; + + +// Tests that editing commands make it through the pipeline all the way to +// RenderWidgetHost. +TEST_F(RWHVMEditCommandHelperTest, TestEditingCommandDelivery) { + RWHVMEditCommandHelper helper; + NSArray* edit_command_strings = helper.GetEditSelectorNames(); + + // Set up a mock render widget and set expectations. + MessageLoopForUI message_loop; + TestingProfile profile; + MockRenderProcessHost mock_process(&profile); + MockRenderWidgetHostEditCommandCounter mock_render_widget(&mock_process, 0); + + size_t num_edit_commands = [edit_command_strings count]; + EXPECT_CALL(mock_render_widget, + ForwardEditCommand(testing::_, testing::_)).Times(num_edit_commands); + +// TODO(jeremy): Figure this out and reenable this test. +// For some bizarre reason this code doesn't work, running the code in the +// debugger confirms that the function is called with the correct parameters +// however gmock appears not to be able to match up parameters correctly. +// Disable for now till we can figure this out. +#if 0 + // Tell Mock object that we expect to recieve each edit command once. + std::string empty_str; + for (NSString* edit_command_name in edit_command_strings) { + std::string command([edit_command_name UTF8String]); + EXPECT_CALL(mock_render_widget, + ForwardEditCommand(command, empty_str)).Times(1); + } +#endif // 0 + + // RenderWidgetHostViewMac self destructs (RenderWidgetHostViewMacCocoa + // takes ownership) so no need to delete it ourselves. + RenderWidgetHostViewMac* rwhvm = new RenderWidgetHostViewMac( + &mock_render_widget); + + RenderWidgetHostViewMacOwner* rwhwvm_owner = + [[[RenderWidgetHostViewMacOwner alloc] + initWithRenderWidgetHostViewMac:rwhvm] autorelease]; + + helper.AddEditingSelectorsToClass([rwhwvm_owner class]); + + for (NSString* edit_command_name in edit_command_strings) { + NSString* sel_str = [edit_command_name stringByAppendingString:@":"]; + [rwhwvm_owner performSelector:NSSelectorFromString(sel_str) withObject:nil]; + } +} + +// Test RWHVMEditCommandHelper::AddEditingSelectorsToClass +TEST_F(RWHVMEditCommandHelperTest, TestAddEditingSelectorsToClass) { + RWHVMEditCommandHelper helper; + NSArray* edit_command_strings = helper.GetEditSelectorNames(); + ASSERT_GT([edit_command_strings count], 0U); + + // Create a class instance and add methods to the class. + RWHVMEditCommandHelperTestClass* test_obj = + [[[RWHVMEditCommandHelperTestClass alloc] init] autorelease]; + + // Check that edit commands aren't already attached to the object. + ASSERT_FALSE(CheckObjectRespondsToEditCommands(edit_command_strings, + test_obj)); + + helper.AddEditingSelectorsToClass([test_obj class]); + + // Check that all edit commands where added. + ASSERT_TRUE(CheckObjectRespondsToEditCommands(edit_command_strings, + test_obj)); + + // AddEditingSelectorsToClass() should be idempotent. + helper.AddEditingSelectorsToClass([test_obj class]); + + // Check that all edit commands are still there. + ASSERT_TRUE(CheckObjectRespondsToEditCommands(edit_command_strings, + test_obj)); +} + +// Test RWHVMEditCommandHelper::IsMenuItemEnabled. +TEST_F(RWHVMEditCommandHelperTest, TestMenuItemEnabling) { + RWHVMEditCommandHelper helper; + RenderWidgetHostViewMacOwner* rwhvm_owner = + [[[RenderWidgetHostViewMacOwner alloc] init] autorelease]; + + // The select all menu should always be enabled. + SEL select_all = NSSelectorFromString(@"selectAll:"); + ASSERT_TRUE(helper.IsMenuItemEnabled(select_all, rwhvm_owner)); + + // Random selectors should be enabled by the function. + SEL garbage_selector = NSSelectorFromString(@"randomGarbageSelector:"); + ASSERT_FALSE(helper.IsMenuItemEnabled(garbage_selector, rwhvm_owner)); + + // TODO(jeremy): Currently IsMenuItemEnabled just returns true for all edit + // selectors. Once we go past that we should do more extensive testing here. +} diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index d5376f44..f486cb7 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1445,6 +1445,14 @@ void RenderViewHost::ForwardMouseEvent( } } +void RenderViewHost::ForwardEditCommand(const std::string& name, + const std::string& value) { + IPC::Message* message = new ViewMsg_HandleExecuteEditCommand(routing_id(), + name, + value); + Send(message); +} + void RenderViewHost::OnDebugDisconnect() { if (debugger_attached_) { debugger_attached_ = false; diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index be31a607..101bc2b 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -424,6 +424,8 @@ class RenderViewHost : public RenderWidgetHost { virtual void GotFocus(); virtual bool CanBlur() const; virtual void ForwardMouseEvent(const WebKit::WebMouseEvent& mouse_event); + virtual void ForwardEditCommand(const std::string& name, + const std::string& value); virtual gfx::Rect GetRootWindowResizerRect() const; // Creates a new RenderView with the given route id. diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 51d2b3b..9b18841 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -382,6 +382,13 @@ void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs)); } +void RenderWidgetHost::ForwardEditCommand(const std::string& name, + const std::string& value) { + // We don't need an implementation of this function here since the + // only place we use this is for the case of dropdown menus and other + // edge cases for which edit commands don't make sense. +} + void RenderWidgetHost::RendererExited() { // Clearing this flag causes us to re-create the renderer when recovering // from a crashed renderer. diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index c5913ef..783c147 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -239,6 +239,8 @@ class RenderWidgetHost : public IPC::Channel::Listener { virtual void ForwardMouseEvent(const WebKit::WebMouseEvent& mouse_event); void ForwardWheelEvent(const WebKit::WebMouseWheelEvent& wheel_event); void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event); + virtual void ForwardEditCommand(const std::string& name, + const std::string& value); // Update the text direction of the focused input element and notify it to a // renderer process. diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index ab97232..cdfee6a 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -8,25 +8,33 @@ #import <Cocoa/Cocoa.h> #include "base/scoped_nsobject.h" +#include "base/scoped_ptr.h" #include "base/task.h" #include "base/time.h" #include "chrome/browser/cocoa/base_view.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" + #include "webkit/glue/webcursor.h" class RenderWidgetHostViewMac; +class RWHVMEditCommandHelper; @class ToolTip; +@protocol RenderWidgetHostViewMacOwner +- (RenderWidgetHostViewMac*)renderWidgetHostViewMac; +@end + // This is the view that lives in the Cocoa view hierarchy. In Windows-land, // RenderWidgetHostViewWin is both the view and the delegate. We split the roles // but that means that the view needs to own the delegate and will dispose of it // when it's removed from the view system. -@interface RenderWidgetHostViewCocoa : BaseView { +@interface RenderWidgetHostViewCocoa : BaseView <RenderWidgetHostViewMacOwner> { @private RenderWidgetHostViewMac* renderWidgetHostView_; BOOL canBeKeyView_; BOOL closeOnDeactivate_; + scoped_ptr<RWHVMEditCommandHelper> editCommand_helper_; } - (void)setCanBeKeyView:(BOOL)can; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index 377e073..bf01fd0 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -7,6 +7,7 @@ #include "base/histogram.h" #include "base/sys_string_conversions.h" #include "chrome/browser/browser_trial.h" +#import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" #include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" @@ -362,6 +363,9 @@ void RenderWidgetHostViewMac::ShutdownHost() { - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { self = [super initWithFrame:NSZeroRect]; if (self != nil) { + editCommand_helper_.reset(new RWHVMEditCommandHelper); + editCommand_helper_->AddEditingSelectorsToClass([self class]); + renderWidgetHostView_ = r; canBeKeyView_ = YES; closeOnDeactivate_ = NO; @@ -509,4 +513,15 @@ void RenderWidgetHostViewMac::ShutdownHost() { return YES; } +- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { + SEL action = [item action]; + + return editCommand_helper_->IsMenuItemEnabled(action, self); +} + +- (RenderWidgetHostViewMac*)renderWidgetHostViewMac { + return renderWidgetHostView_; +} + @end + diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 89c6006..d62389d 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -764,6 +764,8 @@ 'browser/cocoa/preferences_localizer.mm', 'browser/cocoa/preferences_window_controller.h', 'browser/cocoa/preferences_window_controller.mm', + 'browser/cocoa/rwhvm_editcommand_helper.h', + 'browser/cocoa/rwhvm_editcommand_helper.mm', 'browser/cocoa/sad_tab_view.h', 'browser/cocoa/sad_tab_view.mm', 'browser/cocoa/search_engine_list_model.h', @@ -3392,6 +3394,7 @@ 'browser/cocoa/gradient_button_cell_unittest.mm', 'browser/cocoa/grow_box_view_unittest.mm', 'browser/cocoa/preferences_window_controller_unittest.mm', + 'browser/cocoa/rwhvm_editcommand_helper_unittest.mm', 'browser/cocoa/sad_tab_view_unittest.mm', 'browser/cocoa/search_engine_list_model_unittest.mm', 'browser/cocoa/status_bubble_mac_unittest.mm', diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 5debd5f..7743244 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -113,6 +113,11 @@ IPC_BEGIN_MESSAGES(View) // Message payload is a blob that should be cast to WebInputEvent IPC_MESSAGE_ROUTED0(ViewMsg_HandleInputEvent) + // Message payload is the name/value of a core command to execute. + IPC_MESSAGE_ROUTED2(ViewMsg_HandleExecuteEditCommand, + std::string, /* name */ + std::string /* value */) + IPC_MESSAGE_ROUTED0(ViewMsg_MouseCaptureLost) // TODO(darin): figure out how this meshes with RestoreFocus diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 9ea36fb..6376ee7 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -354,6 +354,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete) IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll) IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt) + IPC_MESSAGE_HANDLER(ViewMsg_HandleExecuteEditCommand, OnExecuteEditCommand) IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind) IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom) IPC_MESSAGE_HANDLER(ViewMsg_InsertText, OnInsertText) @@ -717,6 +718,14 @@ void RenderView::OnCopyImageAt(int x, int y) { webview()->CopyImageAt(x, y); } +void RenderView::OnExecuteEditCommand(const std::string& name, + const std::string& value) { + if (!webview() || !webview()->GetFocusedFrame()) + return; + + webview()->GetFocusedFrame()->ExecuteCoreCommandByName(name, value); +} + void RenderView::OnInspectElement(int x, int y) { webview()->InspectElement(x, y); } diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 19f3c43..3ab950a 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -481,6 +481,7 @@ class RenderView : public RenderWidget, void OnDelete(); void OnSelectAll(); void OnCopyImageAt(int x, int y); + void OnExecuteEditCommand(const std::string& name, const std::string& value); void OnInspectElement(int x, int y); void OnShowJavaScriptConsole(); void OnSetupDevToolsClient(); |