summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 12:03:13 +0000
committerjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 12:03:13 +0000
commitfe6c81752c2e16344bfe703bce2fb3db610ecf55 (patch)
tree06a7103a1fade711e18f93d3d61b185b3b56507d
parent1bdb3530e57466f251f5c9a3f7d608b92fd7fe08 (diff)
downloadchromium_src-fe6c81752c2e16344bfe703bce2fb3db610ecf55.zip
chromium_src-fe6c81752c2e16344bfe703bce2fb3db610ecf55.tar.gz
chromium_src-fe6c81752c2e16344bfe703bce2fb3db610ecf55.tar.bz2
Implement the confirm infobar with link for mac.
BUG=11246 TEST=browser_tests.exe --gtest_filter=Geol* Review URL: http://codereview.chromium.org/1127001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42338 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/cocoa/infobar_controller.h2
-rw-r--r--chrome/browser/cocoa/infobar_controller.mm134
-rw-r--r--chrome/browser/cocoa/infobar_controller_unittest.mm30
-rw-r--r--chrome/browser/cocoa/infobar_test_helper.h12
4 files changed, 131 insertions, 47 deletions
diff --git a/chrome/browser/cocoa/infobar_controller.h b/chrome/browser/cocoa/infobar_controller.h
index b1aaaff..4d1ab4b 100644
--- a/chrome/browser/cocoa/infobar_controller.h
+++ b/chrome/browser/cocoa/infobar_controller.h
@@ -85,4 +85,6 @@ class InfoBarDelegate;
// Called when the ok and cancel buttons are clicked.
- (IBAction)ok:(id)sender;
- (IBAction)cancel:(id)sender;
+// Called when there is a click on the link in the infobar.
+- (void)linkClicked;
@end
diff --git a/chrome/browser/cocoa/infobar_controller.mm b/chrome/browser/cocoa/infobar_controller.mm
index 2db007e..b360041 100644
--- a/chrome/browser/cocoa/infobar_controller.mm
+++ b/chrome/browser/cocoa/infobar_controller.mm
@@ -36,6 +36,12 @@ const float kAnimateCloseDuration = 0.12;
// Removes the ok and cancel buttons, and resizes the textfield to use the
// space.
- (void)removeButtons;
+
+// Sets the info bar message to the specified |message|, with a hypertext
+// style link. |link| will be inserted into message at |link_offset|.
+-(void)setLabelToMessage:(NSString*)message
+ withLink:(NSString*)link
+ atOffset:(NSUInteger)link_offset;
@end
@implementation InfoBarController
@@ -179,6 +185,57 @@ const float kAnimateCloseDuration = 0.12;
[self cleanUpAfterAnimation:YES];
}
+// TODO(joth): This method factors out some common functionality between the
+// various derived infobar classes, however the class hierarchy itself could
+// use refactoring to reduce this duplication. http://crbug.com/38924
+-(void)setLabelToMessage:(NSString*)message
+ withLink:(NSString*)link
+ atOffset:(NSUInteger)link_offset {
+ // Create an attributes dictionary for the entire message. We have
+ // to expicitly set the font the control's font. We also override
+ // the cursor to give us the normal cursor rather than the text
+ // insertion cursor.
+ NSMutableDictionary* linkAttributes =
+ [NSMutableDictionary dictionaryWithObject:[NSCursor arrowCursor]
+ forKey:NSCursorAttributeName];
+ [linkAttributes setObject:[label_ font]
+ forKey:NSFontAttributeName];
+
+ // Create the attributed string for the main message text.
+ NSMutableAttributedString* infoText =
+ [[[NSMutableAttributedString alloc]
+ initWithString:message] autorelease];
+ [infoText addAttributes:linkAttributes
+ range:NSMakeRange(0, [infoText length])];
+
+ // Add additional attributes to style the link text appropriately as
+ // well as linkify it. We use an empty string for the NSLink
+ // attribute because the actual object we pass doesn't matter, but
+ // it cannot be nil.
+ [linkAttributes setObject:[NSColor blueColor]
+ forKey:NSForegroundColorAttributeName];
+ [linkAttributes setObject:[NSNumber numberWithBool:YES]
+ forKey:NSUnderlineStyleAttributeName];
+ [linkAttributes setObject:[NSCursor pointingHandCursor]
+ forKey:NSCursorAttributeName];
+ [linkAttributes setObject:[NSString string] // dummy value
+ forKey:NSLinkAttributeName];
+
+ // Insert the link text into the string at the appropriate offset.
+ NSAttributedString* attributed_string =
+ [[[NSAttributedString alloc] initWithString:link
+ attributes:linkAttributes] autorelease];
+ [infoText insertAttributedString:attributed_string
+ atIndex:link_offset];
+
+ // Update the label view with the new text. The view must be
+ // selectable and allow editing text attributes for the
+ // linkification to work correctly.
+ [label_ setAllowsEditingTextAttributes:YES];
+ [label_ setSelectable:YES];
+ [label_ setAttributedStringValue:infoText];
+}
+
@end
@@ -224,50 +281,9 @@ const float kAnimateCloseDuration = 0.12;
DCHECK(delegate);
size_t offset = std::wstring::npos;
std::wstring message = delegate->GetMessageTextWithOffset(&offset);
-
- // Create an attributes dictionary for the entire message. We have
- // to expicitly set the font the control's font. We also override
- // the cursor to give us the normal cursor rather than the text
- // insertion cursor.
- NSMutableDictionary* linkAttributes =
- [NSMutableDictionary dictionaryWithObject:[NSCursor arrowCursor]
- forKey:NSCursorAttributeName];
- [linkAttributes setObject:[label_ font]
- forKey:NSFontAttributeName];
-
- // Create the attributed string for the main message text.
- NSMutableAttributedString* infoText =
- [[[NSMutableAttributedString alloc]
- initWithString:base::SysWideToNSString(message)] autorelease];
- [infoText addAttributes:linkAttributes
- range:NSMakeRange(0, [infoText length])];
-
- // Add additional attributes to style the link text appropriately as
- // well as linkify it. We use an empty string for the NSLink
- // attribute because the actual object we pass doesn't matter, but
- // it cannot be nil.
- [linkAttributes setObject:[NSColor blueColor]
- forKey:NSForegroundColorAttributeName];
- [linkAttributes setObject:[NSNumber numberWithBool:YES]
- forKey:NSUnderlineStyleAttributeName];
- [linkAttributes setObject:[NSCursor pointingHandCursor]
- forKey:NSCursorAttributeName];
- [linkAttributes setObject:[NSString string] // dummy value
- forKey:NSLinkAttributeName];
-
- // Insert the link text into the string at the appropriate offset.
- [infoText insertAttributedString:
- [[[NSAttributedString alloc]
- initWithString:base::SysWideToNSString(delegate->GetLinkText())
- attributes:linkAttributes] autorelease]
- atIndex:offset];
-
- // Update the label view with the new text. The view must be
- // selectable and allow editing text attributes for the
- // linkification to work correctly.
- [label_ setAllowsEditingTextAttributes:YES];
- [label_ setSelectable:YES];
- [label_ setAttributedStringValue:infoText];
+ [self setLabelToMessage:base::SysWideToNSString(message)
+ withLink:base::SysWideToNSString(delegate->GetLinkText())
+ atOffset:offset];
}
// Called when someone clicks on the link in the infobar. This method
@@ -372,8 +388,34 @@ const float kAnimateCloseDuration = 0.12;
frame.size.width = rightEdge - NSMinX(frame);
[label_ setFrame:frame];
- // Set the text.
- [label_ setStringValue:base::SysWideToNSString(delegate->GetMessageText())];
+ // Set the text and link.
+ NSString* message = base::SysWideToNSString(delegate->GetMessageText());
+ std::wstring link = delegate->GetLinkText();
+ if (link.empty()) {
+ // Simple case: no link, so just set the message directly.
+ [label_ setStringValue:message];
+ } else {
+ // Inserting the link unintentionally causes the text to have a slightly
+ // different result to the simple case above: text is truncated on word
+ // boundaries (if needed) rather than elided with ellipses.
+
+ // Add spacing between the label and the link.
+ message = [message stringByAppendingString:@" "];
+ [self setLabelToMessage:message
+ withLink:base::SysWideToNSString(link)
+ atOffset:[message length]];
+ }
+}
+
+// Called when someone clicks on the link in the infobar. This method
+// is called by the InfobarTextField on its delegate (the
+// LinkInfoBarController).
+- (void)linkClicked {
+ WindowOpenDisposition disposition =
+ event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
+ if (delegate_ &&
+ delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
+ [self removeInfoBar];
}
@end
diff --git a/chrome/browser/cocoa/infobar_controller_unittest.mm b/chrome/browser/cocoa/infobar_controller_unittest.mm
index 6dbfb5d..5ed5f12 100644
--- a/chrome/browser/cocoa/infobar_controller_unittest.mm
+++ b/chrome/browser/cocoa/infobar_controller_unittest.mm
@@ -180,8 +180,9 @@ TEST_F(LinkInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
TEST_VIEW(ConfirmInfoBarControllerTest, [controller_ view]);
TEST_F(ConfirmInfoBarControllerTest, ShowAndDismiss) {
- // Make sure someone looked at the message and icon.
+ // Make sure someone looked at the message, link, and icon.
EXPECT_TRUE(delegate_.message_text_accessed);
+ EXPECT_TRUE(delegate_.link_text_accessed);
EXPECT_TRUE(delegate_.icon_accessed);
// Check to make sure the infobar message was set properly.
@@ -192,6 +193,7 @@ TEST_F(ConfirmInfoBarControllerTest, ShowAndDismiss) {
[controller_ dismiss:nil];
EXPECT_FALSE(delegate_.ok_clicked);
EXPECT_FALSE(delegate_.cancel_clicked);
+ EXPECT_FALSE(delegate_.link_clicked);
EXPECT_TRUE(delegate_.closed);
}
@@ -201,6 +203,7 @@ TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOK) {
[controller_ ok:nil];
EXPECT_TRUE(delegate_.ok_clicked);
EXPECT_FALSE(delegate_.cancel_clicked);
+ EXPECT_FALSE(delegate_.link_clicked);
EXPECT_TRUE(delegate_.closed);
}
@@ -212,6 +215,7 @@ TEST_F(ConfirmInfoBarControllerTest, ShowAndClickOKWithoutClosing) {
[controller_ ok:nil];
EXPECT_TRUE(delegate_.ok_clicked);
EXPECT_FALSE(delegate_.cancel_clicked);
+ EXPECT_FALSE(delegate_.link_clicked);
EXPECT_FALSE(delegate_.closed);
}
@@ -221,6 +225,7 @@ TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancel) {
[controller_ cancel:nil];
EXPECT_FALSE(delegate_.ok_clicked);
EXPECT_TRUE(delegate_.cancel_clicked);
+ EXPECT_FALSE(delegate_.link_clicked);
EXPECT_TRUE(delegate_.closed);
}
@@ -232,6 +237,29 @@ TEST_F(ConfirmInfoBarControllerTest, ShowAndClickCancelWithoutClosing) {
[controller_ cancel:nil];
EXPECT_FALSE(delegate_.ok_clicked);
EXPECT_TRUE(delegate_.cancel_clicked);
+ EXPECT_FALSE(delegate_.link_clicked);
+ EXPECT_FALSE(delegate_.closed);
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLink) {
+ // Check that clicking on the link calls LinkClicked() on the
+ // delegate. It should also close the infobar.
+ [controller_ linkClicked];
+ EXPECT_FALSE(delegate_.ok_clicked);
+ EXPECT_FALSE(delegate_.cancel_clicked);
+ EXPECT_TRUE(delegate_.link_clicked);
+ EXPECT_TRUE(delegate_.closed);
+}
+
+TEST_F(ConfirmInfoBarControllerTest, ShowAndClickLinkWithoutClosing) {
+ delegate_.closes_on_action = false;
+
+ // Check that clicking on the link calls LinkClicked() on the
+ // delegate. It should not close the infobar.
+ [controller_ linkClicked];
+ EXPECT_FALSE(delegate_.ok_clicked);
+ EXPECT_FALSE(delegate_.cancel_clicked);
+ EXPECT_TRUE(delegate_.link_clicked);
EXPECT_FALSE(delegate_.closed);
}
diff --git a/chrome/browser/cocoa/infobar_test_helper.h b/chrome/browser/cocoa/infobar_test_helper.h
index e8f5876..7c7b84c 100644
--- a/chrome/browser/cocoa/infobar_test_helper.h
+++ b/chrome/browser/cocoa/infobar_test_helper.h
@@ -100,6 +100,7 @@ class MockConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
icon_accessed(false),
ok_clicked(false),
cancel_clicked(false),
+ link_clicked(false),
closed(false),
closes_on_action(true) {
}
@@ -139,12 +140,23 @@ class MockConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
closed = true;
}
+ virtual std::wstring GetLinkText() {
+ link_text_accessed = true;
+ return std::wstring();
+ }
+
+ virtual bool LinkClicked(WindowOpenDisposition disposition) {
+ link_clicked = true;
+ return closes_on_action;
+ }
+
// These are declared mutable to get around const-ness issues.
mutable bool message_text_accessed;
mutable bool link_text_accessed;
mutable bool icon_accessed;
bool ok_clicked;
bool cancel_clicked;
+ bool link_clicked;
bool closed;
// Determines whether the infobar closes when an action is taken or not.