summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 20:20:49 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 20:20:49 +0000
commitee2df648776cc000aded2b737608b805039cf5e8 (patch)
treea49a6c4aeee53e399f7751be1d9f39037aef109b /chrome/browser
parent084820e2662059decc9b3281b37c05ae55a13da0 (diff)
downloadchromium_src-ee2df648776cc000aded2b737608b805039cf5e8.zip
chromium_src-ee2df648776cc000aded2b737608b805039cf5e8.tar.gz
chromium_src-ee2df648776cc000aded2b737608b805039cf5e8.tar.bz2
Fix http://crbug.com/13971: OSX: Text copied from Omnibox is styled
Provide a custom field editor for the location bar that overrides cut/copy to only write plain text to the clipboard. BUG=13971 TEST=Type a URL in the Omnibox, select all and copy url, open Textedit and paste the url into it. Expected results: url should be unstyled previous behavior: styled text (as it appeared in the Omnibox was pasted) Review URL: http://codereview.chromium.org/126075 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18425 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm6
-rw-r--r--chrome/browser/cocoa/location_bar_fieldeditor_unittest.mm88
-rw-r--r--chrome/browser/cocoa/toolbar_controller.h17
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm45
4 files changed, 152 insertions, 4 deletions
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index f363008..d071f7c 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -766,4 +766,10 @@ willPositionSheet:(NSWindow *)sheet
browser_->ExecuteCommand(command);
}
+- (id)windowWillReturnFieldEditor:(NSWindow*)sender toObject:(id)obj {
+ // Ask the toolbar controller if it wants to return a custom field editor
+ // for the specific object.
+ return [toolbarController_ customFieldEditorForObject:obj];
+}
+
@end
diff --git a/chrome/browser/cocoa/location_bar_fieldeditor_unittest.mm b/chrome/browser/cocoa/location_bar_fieldeditor_unittest.mm
new file mode 100644
index 0000000..fca4411
--- /dev/null
+++ b/chrome/browser/cocoa/location_bar_fieldeditor_unittest.mm
@@ -0,0 +1,88 @@
+// 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/toolbar_controller.h"
+
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+int NumTypesOnPasteboard(NSPasteboard* pb) {
+ return [[pb types] count];
+}
+
+void ClearPasteboard(NSPasteboard* pb) {
+ [pb declareTypes:[NSArray array] owner:nil];
+}
+
+bool NoRichTextOnClipboard(NSPasteboard* pb) {
+ return ([pb dataForType:NSRTFPboardType] == nil) &&
+ ([pb dataForType:NSRTFDPboardType] == nil) &&
+ ([pb dataForType:NSHTMLPboardType] == nil);
+}
+
+bool ClipboardContainsText(NSPasteboard* pb, NSString* cmp) {
+ NSString* clipboard_text = [pb stringForType:NSStringPboardType];
+ return [clipboard_text isEqualToString:cmp];
+}
+
+} // namespace
+
+class LocationBarFieldEditorTest : public PlatformTest {
+ public:
+ virtual void SetUp() {
+ PlatformTest::SetUp();
+ pb_ = [NSPasteboard pasteboardWithUniqueName];
+ }
+
+ virtual void TearDown() {
+ [pb_ releaseGlobally];
+ pb_ = nil;
+ PlatformTest::TearDown();
+ }
+
+ NSPasteboard *clipboard() {
+ DCHECK(pb_);
+ return pb_;
+ }
+
+ private:
+ NSPasteboard *pb_;
+};
+
+TEST_F(LocationBarFieldEditorTest, CutCopyTest) {
+ // Make sure pasteboard is empty before we start.
+ ASSERT_EQ(NumTypesOnPasteboard(clipboard()), 0);
+
+ NSString* test_string_1 = @"astring";
+ NSString* test_string_2 = @"another string";
+
+ scoped_nsobject<LocationBarFieldEditor> field_editor(
+ [[LocationBarFieldEditor alloc] init]);
+ [field_editor.get() setRichText:YES];
+
+ // Put some text on the clipboard.
+ [field_editor.get() setString:test_string_1];
+ [field_editor.get() selectAll:nil];
+ [field_editor.get() alignRight:nil]; // Add a rich text attribute.
+ ASSERT_TRUE(NoRichTextOnClipboard(clipboard()));
+
+ // Check that copying it works and we only get plain text.
+ NSPasteboard* pb = clipboard();
+ [field_editor.get() performCopy:pb];
+ ASSERT_TRUE(NoRichTextOnClipboard(clipboard()));
+ ASSERT_TRUE(ClipboardContainsText(clipboard(), test_string_1));
+
+ // Check that cutting it works and we only get plain text.
+ [field_editor.get() setString:test_string_2];
+ [field_editor.get() selectAll:nil];
+ [field_editor.get() alignLeft:nil]; // Add a rich text attribute.
+ [field_editor.get() performCut:pb];
+ ASSERT_TRUE(NoRichTextOnClipboard(clipboard()));
+ ASSERT_TRUE(ClipboardContainsText(clipboard(), test_string_2));
+ ASSERT_EQ([[field_editor.get() textStorage] length], 0U);
+}
diff --git a/chrome/browser/cocoa/toolbar_controller.h b/chrome/browser/cocoa/toolbar_controller.h
index 1909800..1aa38bb 100644
--- a/chrome/browser/cocoa/toolbar_controller.h
+++ b/chrome/browser/cocoa/toolbar_controller.h
@@ -8,6 +8,7 @@
#import <Cocoa/Cocoa.h>
#include "base/scoped_ptr.h"
+#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/command_observer_bridge.h"
class CommandUpdater;
@@ -18,6 +19,15 @@ class TabContents;
class ToolbarModel;
class ToolbarView;
+// Field editor used for the location bar.
+@interface LocationBarFieldEditor : NSTextView
+// Copy contents of the TextView to the designated clipboard as plain text.
+- (void)performCopy:(NSPasteboard*)pb;
+
+// Same as above, note that this calls through to performCopy.
+- (void)performCut:(NSPasteboard*)pb;
+@end
+
// A controller for the toolbar in the browser window. Manages updating the
// state for location bar and back/fwd/reload/go buttons.
@@ -28,6 +38,7 @@ class ToolbarView;
Profile* profile_; // weak, one per window
scoped_ptr<CommandObserverBridge> commandObserver_;
scoped_ptr<LocationBarViewMac> locationBarView_;
+ scoped_nsobject<LocationBarFieldEditor> locationBarFieldEditor_; // strong
// The ordering is important for unit tests. If new items are added or the
// ordering is changed, make sure to update |-toolbarViews| and the
@@ -49,6 +60,12 @@ class ToolbarView;
// Get the C++ bridge object representing the location bar for this tab.
- (LocationBar*)locationBar;
+// Called by the Window delegate so we can provide a custom field editor if
+// needed.
+// Note that this may be called for objects unrelated to the toolbar.
+// returns nil if we don't want to override the custom field editor for |obj|.
+- (id)customFieldEditorForObject:(id)obj;
+
// Make the location bar the first responder, if possible.
- (void)focusLocationBar;
diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm
index 74f319f..81fdf04 100644
--- a/chrome/browser/cocoa/toolbar_controller.mm
+++ b/chrome/browser/cocoa/toolbar_controller.mm
@@ -14,6 +14,30 @@
static NSString* const kStarImageName = @"star";
static NSString* const kStarredImageName = @"starred";
+@implementation LocationBarFieldEditor
+- (void)copy:(id)sender {
+ NSPasteboard* pb = [NSPasteboard generalPasteboard];
+ [self performCopy:pb];
+}
+
+- (void)cut:(id)sender {
+ NSPasteboard* pb = [NSPasteboard generalPasteboard];
+ [self performCut:pb];
+}
+
+- (void)performCopy:(NSPasteboard*)pb {
+ [pb declareTypes:[NSArray array] owner:nil];
+ [self writeSelectionToPasteboard:pb types:
+ [NSArray arrayWithObject:NSStringPboardType]];
+}
+
+- (void)performCut:(NSPasteboard*)pb {
+ [self performCopy:pb];
+ [self delete:nil];
+}
+
+@end
+
@interface ToolbarController(Private)
- (void)initCommandStatus:(CommandUpdater*)commands;
@end
@@ -51,10 +75,6 @@ static NSString* const kStarredImageName = @"starred";
[locationBar_ setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
}
-- (void)dealloc {
- [super dealloc];
-}
-
- (LocationBar*)locationBar {
return locationBarView_.get();
}
@@ -121,6 +141,23 @@ static NSString* const kStarredImageName = @"starred";
[goButton_ setTag:tag];
}
+- (id)customFieldEditorForObject:(id)obj {
+ if (obj == locationBar_) {
+ // Lazilly construct Field editor, Cocoa UI code always runs on the
+ // same thread, so there shoudn't be a race condition here.
+ if (locationBarFieldEditor_.get() == nil) {
+ locationBarFieldEditor_.reset([[LocationBarFieldEditor alloc] init]);
+ }
+
+ // This needs to be called every time, otherwise notifications
+ // aren't sent correctly.
+ DCHECK(locationBarFieldEditor_.get());
+ [locationBarFieldEditor_.get() setFieldEditor:YES];
+ return locationBarFieldEditor_.get();
+ }
+ return nil;
+}
+
// Returns an array of views in the order of the outlets above.
- (NSArray*)toolbarViews {
return [NSArray arrayWithObjects:backButton_, forwardButton_, reloadButton_,