// Copyright (c) 2012 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 "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h" #import #include #include #include "base/mac/scoped_nsautorelease_pool.h" #include "base/message_loop/message_loop.h" #include "content/browser/compositor/test/no_transport_image_transport_factory.h" #include "content/browser/gpu/compositor_util.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/input_messages.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "ui/base/layout.h" using content::RenderWidgetHostViewMac; // Bare bones obj-c class for testing purposes. @interface RenderWidgetHostViewMacEditCommandHelperTestClass : NSObject @end @implementation RenderWidgetHostViewMacEditCommandHelperTestClass @end // Class that owns a RenderWidgetHostViewMac. @interface RenderWidgetHostViewMacOwner : NSObject { 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 content { 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; } class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { public: MockRenderWidgetHostDelegate() {} ~MockRenderWidgetHostDelegate() override {} private: void Cut() override {} void Copy() override {} void Paste() override {} void SelectAll() override {} }; // Create a RenderWidget for which we can filter messages. class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl { public: RenderWidgetHostEditCommandCounter(RenderWidgetHostDelegate* delegate, RenderProcessHost* process, int32_t routing_id) : RenderWidgetHostImpl(delegate, process, routing_id, false), edit_command_message_count_(0) {} bool Send(IPC::Message* message) override { if (message->type() == InputMsg_ExecuteEditCommand::ID) edit_command_message_count_++; return RenderWidgetHostImpl::Send(message); } unsigned int edit_command_message_count_; }; class RenderWidgetHostViewMacEditCommandHelperTest : public PlatformTest { protected: void SetUp() override { ImageTransportFactory::InitializeForUnitTests( scoped_ptr( new NoTransportImageTransportFactory)); } void TearDown() override { ImageTransportFactory::Terminate(); } }; } // namespace // Tests that editing commands make it through the pipeline all the way to // RenderWidgetHost. TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, TestEditingCommandDelivery) { MockRenderWidgetHostDelegate delegate; TestBrowserContext browser_context; MockRenderProcessHost process_host(&browser_context); // Populates |g_supported_scale_factors|. std::vector supported_factors; supported_factors.push_back(ui::SCALE_FACTOR_100P); ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); int32_t routing_id = process_host.GetNextRoutingID(); RenderWidgetHostEditCommandCounter* render_widget = new RenderWidgetHostEditCommandCounter(&delegate, &process_host, routing_id); base::mac::ScopedNSAutoreleasePool pool; // Owned by its |cocoa_view()|, i.e. |rwhv_cocoa|. RenderWidgetHostViewMac* rwhv_mac = new RenderWidgetHostViewMac( render_widget, false); base::scoped_nsobject rwhv_cocoa( [rwhv_mac->cocoa_view() retain]); RenderWidgetHostViewMacEditCommandHelper helper; NSArray* edit_command_strings = helper.GetEditSelectorNames(); RenderWidgetHostViewMacOwner* rwhwvm_owner = [[[RenderWidgetHostViewMacOwner alloc] initWithRenderWidgetHostViewMac:rwhv_mac] 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]; } size_t num_edit_commands = [edit_command_strings count]; EXPECT_EQ(render_widget->edit_command_message_count_, num_edit_commands); rwhv_cocoa.reset(); pool.Recycle(); { // The |render_widget|'s process needs to be deleted within |message_loop|. base::MessageLoop message_loop; delete render_widget; } } // Test RenderWidgetHostViewMacEditCommandHelper::AddEditingSelectorsToClass TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, TestAddEditingSelectorsToClass) { RenderWidgetHostViewMacEditCommandHelper helper; NSArray* edit_command_strings = helper.GetEditSelectorNames(); ASSERT_GT([edit_command_strings count], 0U); // Create a class instance and add methods to the class. RenderWidgetHostViewMacEditCommandHelperTestClass* test_obj = [[[RenderWidgetHostViewMacEditCommandHelperTestClass 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 RenderWidgetHostViewMacEditCommandHelper::IsMenuItemEnabled. TEST_F(RenderWidgetHostViewMacEditCommandHelperTest, TestMenuItemEnabling) { RenderWidgetHostViewMacEditCommandHelper 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. } } // namespace content