1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h" 6 7#import <Cocoa/Cocoa.h> 8 9#include "base/mac/scoped_nsautorelease_pool.h" 10#include "base/message_loop/message_loop.h" 11#include "content/browser/compositor/test/no_transport_image_transport_factory.h" 12#include "content/browser/gpu/compositor_util.h" 13#include "content/browser/renderer_host/render_widget_host_delegate.h" 14#include "content/browser/renderer_host/render_widget_host_impl.h" 15#include "content/common/input_messages.h" 16#include "content/public/test/mock_render_process_host.h" 17#include "content/public/test/test_browser_context.h" 18#include "testing/gmock/include/gmock/gmock.h" 19#include "testing/gtest/include/gtest/gtest.h" 20#include "testing/platform_test.h" 21#include "ui/base/layout.h" 22 23using content::RenderWidgetHostViewMac; 24 25// Bare bones obj-c class for testing purposes. 26@interface RenderWidgetHostViewMacEditCommandHelperTestClass : NSObject 27@end 28 29@implementation RenderWidgetHostViewMacEditCommandHelperTestClass 30@end 31 32// Class that owns a RenderWidgetHostViewMac. 33@interface RenderWidgetHostViewMacOwner : 34 NSObject<RenderWidgetHostViewMacOwner> { 35 RenderWidgetHostViewMac* rwhvm_; 36} 37 38- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)rwhvm; 39@end 40 41@implementation RenderWidgetHostViewMacOwner 42 43- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)rwhvm { 44 if ((self = [super init])) { 45 rwhvm_ = rwhvm; 46 } 47 return self; 48} 49 50- (RenderWidgetHostViewMac*)renderWidgetHostViewMac { 51 return rwhvm_; 52} 53 54@end 55 56namespace content { 57namespace { 58 59// Returns true if all the edit command names in the array are present in 60// test_obj. edit_commands is a list of NSStrings, selector names are formed 61// by appending a trailing ':' to the string. 62bool CheckObjectRespondsToEditCommands(NSArray* edit_commands, id test_obj) { 63 for (NSString* edit_command_name in edit_commands) { 64 NSString* sel_str = [edit_command_name stringByAppendingString:@":"]; 65 if (![test_obj respondsToSelector:NSSelectorFromString(sel_str)]) { 66 return false; 67 } 68 } 69 return true; 70} 71 72class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { 73 public: 74 MockRenderWidgetHostDelegate() {} 75 virtual ~MockRenderWidgetHostDelegate() {} 76}; 77 78// Create a RenderWidget for which we can filter messages. 79class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl { 80 public: 81 RenderWidgetHostEditCommandCounter( 82 RenderWidgetHostDelegate* delegate, 83 RenderProcessHost* process, 84 int routing_id) 85 : RenderWidgetHostImpl(delegate, process, routing_id, false), 86 edit_command_message_count_(0) { 87 } 88 89 virtual bool Send(IPC::Message* message) OVERRIDE { 90 if (message->type() == InputMsg_ExecuteEditCommand::ID) 91 edit_command_message_count_++; 92 return RenderWidgetHostImpl::Send(message); 93 } 94 95 unsigned int edit_command_message_count_; 96}; 97 98class RenderWidgetHostViewMacEditCommandHelperTest : public PlatformTest { 99 protected: 100 virtual void SetUp() { 101 if (IsDelegatedRendererEnabled()) { 102 ImageTransportFactory::InitializeForUnitTests( 103 scoped_ptr<ImageTransportFactory>( 104 new NoTransportImageTransportFactory)); 105 } 106 } 107 virtual void TearDown() { 108 if (IsDelegatedRendererEnabled()) 109 ImageTransportFactory::Terminate(); 110 } 111}; 112 113} // namespace 114 115// Tests that editing commands make it through the pipeline all the way to 116// RenderWidgetHost. 117TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, 118 TestEditingCommandDelivery) { 119 MockRenderWidgetHostDelegate delegate; 120 TestBrowserContext browser_context; 121 MockRenderProcessHost process_host(&browser_context); 122 123 // Populates |g_supported_scale_factors|. 124 std::vector<ui::ScaleFactor> supported_factors; 125 supported_factors.push_back(ui::SCALE_FACTOR_100P); 126 ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); 127 128 RenderWidgetHostEditCommandCounter* render_widget = 129 new RenderWidgetHostEditCommandCounter( 130 &delegate, &process_host, MSG_ROUTING_NONE); 131 132 base::mac::ScopedNSAutoreleasePool pool; 133 134 // Owned by its |cocoa_view()|, i.e. |rwhv_cocoa|. 135 RenderWidgetHostViewMac* rwhv_mac = new RenderWidgetHostViewMac( 136 render_widget); 137 base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa( 138 [rwhv_mac->cocoa_view() retain]); 139 140 RenderWidgetHostViewMacEditCommandHelper helper; 141 NSArray* edit_command_strings = helper.GetEditSelectorNames(); 142 RenderWidgetHostViewMacOwner* rwhwvm_owner = 143 [[[RenderWidgetHostViewMacOwner alloc] 144 initWithRenderWidgetHostViewMac:rwhv_mac] autorelease]; 145 146 helper.AddEditingSelectorsToClass([rwhwvm_owner class]); 147 148 for (NSString* edit_command_name in edit_command_strings) { 149 NSString* sel_str = [edit_command_name stringByAppendingString:@":"]; 150 [rwhwvm_owner performSelector:NSSelectorFromString(sel_str) withObject:nil]; 151 } 152 153 size_t num_edit_commands = [edit_command_strings count]; 154 EXPECT_EQ(render_widget->edit_command_message_count_, num_edit_commands); 155 rwhv_cocoa.reset(); 156 pool.Recycle(); 157 158 { 159 // The |render_widget|'s process needs to be deleted within |message_loop|. 160 base::MessageLoop message_loop; 161 delete render_widget; 162 } 163} 164 165// Test RenderWidgetHostViewMacEditCommandHelper::AddEditingSelectorsToClass 166TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, 167 TestAddEditingSelectorsToClass) { 168 RenderWidgetHostViewMacEditCommandHelper helper; 169 NSArray* edit_command_strings = helper.GetEditSelectorNames(); 170 ASSERT_GT([edit_command_strings count], 0U); 171 172 // Create a class instance and add methods to the class. 173 RenderWidgetHostViewMacEditCommandHelperTestClass* test_obj = 174 [[[RenderWidgetHostViewMacEditCommandHelperTestClass alloc] init] 175 autorelease]; 176 177 // Check that edit commands aren't already attached to the object. 178 ASSERT_FALSE(CheckObjectRespondsToEditCommands(edit_command_strings, 179 test_obj)); 180 181 helper.AddEditingSelectorsToClass([test_obj class]); 182 183 // Check that all edit commands where added. 184 ASSERT_TRUE(CheckObjectRespondsToEditCommands(edit_command_strings, 185 test_obj)); 186 187 // AddEditingSelectorsToClass() should be idempotent. 188 helper.AddEditingSelectorsToClass([test_obj class]); 189 190 // Check that all edit commands are still there. 191 ASSERT_TRUE(CheckObjectRespondsToEditCommands(edit_command_strings, 192 test_obj)); 193} 194 195// Test RenderWidgetHostViewMacEditCommandHelper::IsMenuItemEnabled. 196TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, TestMenuItemEnabling) { 197 RenderWidgetHostViewMacEditCommandHelper helper; 198 RenderWidgetHostViewMacOwner* rwhvm_owner = 199 [[[RenderWidgetHostViewMacOwner alloc] init] autorelease]; 200 201 // The select all menu should always be enabled. 202 SEL select_all = NSSelectorFromString(@"selectAll:"); 203 ASSERT_TRUE(helper.IsMenuItemEnabled(select_all, rwhvm_owner)); 204 205 // Random selectors should be enabled by the function. 206 SEL garbage_selector = NSSelectorFromString(@"randomGarbageSelector:"); 207 ASSERT_FALSE(helper.IsMenuItemEnabled(garbage_selector, rwhvm_owner)); 208 209 // TODO(jeremy): Currently IsMenuItemEnabled just returns true for all edit 210 // selectors. Once we go past that we should do more extensive testing here. 211} 212 213} // namespace content 214