Commit 90d895e3 authored by Avi Drissman's avatar Avi Drissman Committed by Commit Bot

Don't offer known passwords for "Paste and Search" or zero-prefix suggest

If the clipboard contains data that has been marked by its originator
as confidential, don't offer it for "Paste and Search" and don't offer
it as a zero-prefix search suggestion.

This directly wires into the iOS zero-prefix search code, and adds an
expandable function to ui::Clipboard, implementing it for the Mac.

If there is a convention for other platforms, it can be implemented
via this mechanism.

Bug: 1067542, 1084244, 1071828
Change-Id: I064a0629c35b686e14772cec123a3fc1eec5487c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2213286Reviewed-by: default avatarJustin Donnelly <jdonnelly@chromium.org>
Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Commit-Queue: Avi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771982}
parent d58f5cfa
......@@ -5237,6 +5237,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PASTE_AND_SEARCH" desc="The text label of the Paste And Go menu item when the clipboard contains a string to search for">
Pa&amp;ste and search for “<ph name="SEARCH_TERMS">$1<ex>flowers</ex></ph>
</message>
<message name="IDS_PASTE_AND_GO_EMPTY" desc="The text label of the Paste And Go menu item when the clipboard is empty">
Pa&amp;ste and go
</message>
</if>
<if expr="use_titlecase">
<message name="IDS_PASTE_AND_GO" desc="In Title Case: The text label of the Paste And Go menu item when the clipboard contains a URL">
......@@ -5245,6 +5248,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_PASTE_AND_SEARCH" desc="In Title Case: The text label of the Paste And Go menu item when the clipboard contains a string to search for">
Pa&amp;ste and Search for “<ph name="SEARCH_TERMS">$1<ex>flowers</ex></ph>
</message>
<message name="IDS_PASTE_AND_GO_EMPTY" desc="In Title Case: The text label of the Paste And Go menu item when the clipboard is empty">
Pa&amp;ste and Go
</message>
</if>
<message name="IDS_SHOW_URL" desc="The text label of the Show URL menu item when the omnibox contains an elided URL or search query terms">
S&amp;how URL
......
......@@ -50,6 +50,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
......@@ -140,6 +141,11 @@ enum OmniboxMenuCommands {
kShowUrl = views::Textfield::MenuCommands::kLastCommandId + 1,
};
bool IsClipboardDataMarkedAsConfidential() {
return ui::Clipboard::GetForCurrentThread()
->IsMarkedByOriginatorAsConfidential();
}
} // namespace
// Animation chosen to match the default values in the edwardjung prototype.
......@@ -1063,8 +1069,14 @@ bool OmniboxViewViews::IsItemForCommandIdDynamic(int command_id) const {
base::string16 OmniboxViewViews::GetLabelForCommandId(int command_id) const {
DCHECK_EQ(IDC_PASTE_AND_GO, command_id);
// Don't paste-and-go data that was marked by its originator as confidential.
constexpr size_t kMaxSelectionTextLength = 50;
const base::string16 clipboard_text = GetClipboardText();
const base::string16 clipboard_text = IsClipboardDataMarkedAsConfidential()
? base::string16()
: GetClipboardText();
if (clipboard_text.empty())
return l10n_util::GetStringUTF16(IDS_PASTE_AND_GO_EMPTY);
base::string16 selection_text = gfx::TruncateString(
clipboard_text, kMaxSelectionTextLength, gfx::WORD_BREAK);
......@@ -1462,8 +1474,10 @@ void OmniboxViewViews::OnBlur() {
bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const {
if (command_id == Textfield::kPaste)
return !GetReadOnly() && !GetClipboardText().empty();
if (command_id == IDC_PASTE_AND_GO)
return !GetReadOnly() && model()->CanPasteAndGo(GetClipboardText());
if (command_id == IDC_PASTE_AND_GO) {
return !GetReadOnly() && !IsClipboardDataMarkedAsConfidential() &&
model()->CanPasteAndGo(GetClipboardText());
}
// Menu item is only shown when it is valid.
if (command_id == kShowUrl)
......
......@@ -99,6 +99,9 @@ NSData* WeakMD5FromPasteboardData(NSString* string,
// Returns the uptime.
- (NSTimeInterval)uptime;
// Returns whether the value of the clipboard should be returned.
- (BOOL)shouldReturnValueOfClipboard;
@end
@implementation ClipboardRecentContentImplIOS
......@@ -207,25 +210,28 @@ NSData* WeakMD5FromPasteboardData(NSString* string,
- (NSURL*)recentURLFromClipboard {
[self updateIfNeeded];
if ([self clipboardContentAge] > self.maximumAgeOfClipboard) {
if (![self shouldReturnValueOfClipboard])
return nil;
}
return [self URLFromPasteboard];
}
- (NSString*)recentTextFromClipboard {
[self updateIfNeeded];
if ([self clipboardContentAge] > self.maximumAgeOfClipboard) {
if (![self shouldReturnValueOfClipboard])
return nil;
}
return [UIPasteboard generalPasteboard].string;
}
- (UIImage*)recentImageFromClipboard {
[self updateIfNeeded];
if ([self clipboardContentAge] > self.maximumAgeOfClipboard) {
if (![self shouldReturnValueOfClipboard])
return nil;
}
return [UIPasteboard generalPasteboard].image;
}
......@@ -233,6 +239,22 @@ NSData* WeakMD5FromPasteboardData(NSString* string,
return -[self.lastPasteboardChangeDate timeIntervalSinceNow];
}
- (BOOL)shouldReturnValueOfClipboard {
if ([self clipboardContentAge] > self.maximumAgeOfClipboard)
return NO;
// It is the common convention on iOS that password managers tag confidential
// data with the flavor "org.nspasteboard.ConcealedType". Obey this
// convention; the user doesn't want for their confidential data to be
// suggested as a search, anyway. See http://nspasteboard.org/ for more info.
NSArray<NSString*>* types =
[[UIPasteboard generalPasteboard] pasteboardTypes];
if ([types containsObject:@"org.nspasteboard.ConcealedType"])
return NO;
return YES;
}
- (void)suppressClipboardContent {
// User cleared the user data. The pasteboard entry must be removed from the
// omnibox list. Force entry expiration by setting copy date to 1970.
......
......@@ -217,9 +217,22 @@ TEST_F(ClipboardRecentContentIOSTest, PasteboardURLObsolescence) {
VerifyClipboardTextDoesNotExist();
}
// Checks that if the pasteboard is marked as having confidential data, it is
// not returned.
TEST_F(ClipboardRecentContentIOSTest, ConfidentialPasteboardText) {
[[UIPasteboard generalPasteboard]
setItems:@[ @{
@"public.plain-text" : @"hunter2",
@"org.nspasteboard.ConcealedType" : @"hunter2"
} ]
options:@{}];
VerifyClipboardTextDoesNotExist();
}
// Checks that if the user suppresses content, no text will be returned,
// and if the text changes, the new text will be returned again.
TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardText) {
TEST_F(ClipboardRecentContentIOSTest, SuppressedPasteboardText) {
SetPasteboardContent(kRecognizedURL);
// Test that recent pasteboard data is provided.
......@@ -248,7 +261,7 @@ TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardText) {
VerifyClipboardTextDoesNotExist();
// Check that if the pasteboard changes, the new content is not
// supressed anymore.
// suppressed anymore.
SetPasteboardContent(kRecognizedURL2);
VerifyClipboardURLExists(kRecognizedURL2);
VerifyClipboardTextExists(kRecognizedURL2);
......@@ -256,7 +269,7 @@ TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardText) {
// Checks that if the user suppresses content, no image will be returned,
// and if the image changes, the new image will be returned again.
TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardImage) {
TEST_F(ClipboardRecentContentIOSTest, SuppressedPasteboardImage) {
SetPasteboardImage(TestUIImage());
// Test that recent pasteboard data is provided.
......@@ -281,7 +294,7 @@ TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboardImage) {
VerifyIfClipboardImageExists(false);
// Check that if the pasteboard changes, the new content is not
// supressed anymore.
// suppressed anymore.
SetPasteboardImage(TestUIImage([UIColor greenColor]));
VerifyIfClipboardImageExists(true);
}
......
......@@ -203,4 +203,8 @@ base::Lock& Clipboard::ClipboardMapLock() {
return *clipboard_map_lock;
}
bool Clipboard::IsMarkedByOriginatorAsConfidential() const {
return false;
}
} // namespace ui
......@@ -110,6 +110,12 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
virtual bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer) const = 0;
// Returns whether the clipboard has data that is marked by its originator as
// confidential. This is available for opt-in checking by the user of this API
// as confidential information, like passwords, might legitimately need to be
// manipulated.
virtual bool IsMarkedByOriginatorAsConfidential() const;
// Clear the clipboard data.
virtual void Clear(ClipboardBuffer buffer) = 0;
......
......@@ -33,6 +33,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer) const override;
bool IsMarkedByOriginatorAsConfidential() const override;
void Clear(ClipboardBuffer buffer) override;
void ReadAvailableTypes(ClipboardBuffer buffer,
std::vector<base::string16>* types) const override;
......
......@@ -85,6 +85,20 @@ bool ClipboardMac::IsFormatAvailable(const ClipboardFormatType& format,
return [types containsObject:format.ToNSString()];
}
bool ClipboardMac::IsMarkedByOriginatorAsConfidential() const {
// It is the common convention on the Mac that password managers tag
// confidential data with the flavor "org.nspasteboard.ConcealedType". Obey
// this convention. See http://nspasteboard.org/ for more info.
NSPasteboard* pb = GetPasteboard();
NSPasteboardType type =
[pb availableTypeFromArray:@[ @"org.nspasteboard.ConcealedType" ]];
if (type)
return true;
return false;
}
void ClipboardMac::Clear(ClipboardBuffer buffer) {
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment