diff options
-rw-r--r-- | chrome/test/testing_browser_process.h | 9 | ||||
-rw-r--r-- | chrome/views/controls/text_field.cc | 14 | ||||
-rw-r--r-- | chrome/views/controls/text_field.h | 2 | ||||
-rw-r--r-- | chrome/views/view_unittest.cc | 113 |
4 files changed, 134 insertions, 4 deletions
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h index e2fff16..a507586 100644 --- a/chrome/test/testing_browser_process.h +++ b/chrome/test/testing_browser_process.h @@ -17,6 +17,7 @@ #include "base/string_util.h" #include "base/waitable_event.h" #include "chrome/browser/browser_process.h" +#include "chrome/common/clipboard_service.h" #include "chrome/common/notification_service.h" class TestingBrowserProcess : public BrowserProcess { @@ -80,7 +81,11 @@ class TestingBrowserProcess : public BrowserProcess { } virtual ClipboardService* clipboard_service() { - return NULL; + if (!clipboard_service_.get()) { + // Note that we need a MessageLoop for the next call to work. + clipboard_service_.reset(new ClipboardService); + } + return clipboard_service_.get(); } virtual GoogleURLTracker* google_url_tracker() { @@ -132,6 +137,8 @@ class TestingBrowserProcess : public BrowserProcess { private: NotificationService notification_service_; scoped_ptr<base::WaitableEvent> shutdown_event_; + scoped_ptr<ClipboardService> clipboard_service_; + DISALLOW_COPY_AND_ASSIGN(TestingBrowserProcess); }; diff --git a/chrome/views/controls/text_field.cc b/chrome/views/controls/text_field.cc index 5114d83c..1485427 100644 --- a/chrome/views/controls/text_field.cc +++ b/chrome/views/controls/text_field.cc @@ -375,8 +375,9 @@ void TextField::Edit::SetBackgroundColor(COLORREF bg_color) { bool TextField::Edit::IsCommandEnabled(int id) const { switch (id) { case IDS_UNDO: return !parent_->IsReadOnly() && !!CanUndo(); - case IDS_CUT: return !parent_->IsReadOnly() && !!CanCut(); - case IDS_COPY: return !!CanCopy(); + case IDS_CUT: return !parent_->IsReadOnly() && + !parent_->IsPassword() && !!CanCut(); + case IDS_COPY: return !!CanCopy() && !parent_->IsPassword(); case IDS_PASTE: return !parent_->IsReadOnly() && !!CanPaste(); case IDS_SELECT_ALL: return !!CanSelectAll(); default: NOTREACHED(); @@ -412,6 +413,9 @@ void TextField::Edit::OnContextMenu(HWND window, const CPoint& point) { } void TextField::Edit::OnCopy() { + if (parent_->IsPassword()) + return; + const std::wstring text(GetSelectedText()); if (!text.empty()) { @@ -427,7 +431,7 @@ LRESULT TextField::Edit::OnCreate(CREATESTRUCT* create_struct) { } void TextField::Edit::OnCut() { - if (parent_->IsReadOnly()) + if (parent_->IsReadOnly() || parent_->IsPassword()) return; OnCopy(); @@ -1032,6 +1036,10 @@ bool TextField::IsReadOnly() const { return edit_ ? ((edit_->GetStyle() & ES_READONLY) != 0) : read_only_; } +bool TextField::IsPassword() const { + return GetStyle() & TextField::STYLE_PASSWORD; +} + bool TextField::IsMultiLine() const { return (style_ & STYLE_MULTILINE) != 0; } diff --git a/chrome/views/controls/text_field.h b/chrome/views/controls/text_field.h index 2447e92..ffa5469 100644 --- a/chrome/views/controls/text_field.h +++ b/chrome/views/controls/text_field.h @@ -84,6 +84,8 @@ class TextField : public View { void SetReadOnly(bool read_only); bool IsReadOnly() const; + bool IsPassword() const; + // Whether the text field is multi-line or not, must be set when the text // field is created, using StyleFlags. bool IsMultiLine() const; diff --git a/chrome/views/view_unittest.cc b/chrome/views/view_unittest.cc index 60e54f0..182bfac 100644 --- a/chrome/views/view_unittest.cc +++ b/chrome/views/view_unittest.cc @@ -3,11 +3,14 @@ // found in the LICENSE file. #include "base/message_loop.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/clipboard_service.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/path.h" #include "chrome/common/notification_service.h" #include "chrome/views/background.h" #include "chrome/views/controls/button/checkbox.h" +#include "chrome/views/controls/text_field.h" #include "chrome/views/event.h" #include "chrome/views/view.h" #include "chrome/views/widget/root_view.h" @@ -589,6 +592,116 @@ TEST_F(ViewTest, HitTestMasks) { EXPECT_EQ(root_view, root_view->GetViewForPoint(v2_origin)); } +#if defined(OS_WIN) +// Tests that the TextField view respond appropiately to cut/copy/paste. +TEST_F(ViewTest, TextFieldCutCopyPaste) { + const std::wstring kNormalText = L"Normal"; + const std::wstring kReadOnlyText = L"Read only"; + const std::wstring kPasswordText = L"Password! ** Secret stuff **"; + + ClipboardService* clipboard = g_browser_process->clipboard_service(); + + WidgetWin* window = new WidgetWin; + window->Init(NULL, gfx::Rect(0, 0, 100, 100), true); + RootView* root_view = window->GetRootView(); + + TextField* normal = new TextField(); + TextField* read_only = new TextField(); + read_only->SetReadOnly(true); + TextField* password = new TextField(TextField::STYLE_PASSWORD); + + root_view->AddChildView(normal); + root_view->AddChildView(read_only); + root_view->AddChildView(password); + + normal->SetText(kNormalText); + read_only->SetText(kReadOnlyText); + password->SetText(kPasswordText); + + // + // Test cut. + // + ASSERT_TRUE(normal->GetNativeComponent()); + normal->SelectAll(); + ::SendMessage(normal->GetNativeComponent(), WM_CUT, 0, 0); + + string16 result; + clipboard->ReadText(&result); + EXPECT_EQ(kNormalText, result); + normal->SetText(kNormalText); // Let's revert to the original content. + + ASSERT_TRUE(read_only->GetNativeComponent()); + read_only->SelectAll(); + ::SendMessage(read_only->GetNativeComponent(), WM_CUT, 0, 0); + result.clear(); + clipboard->ReadText(&result); + // Cut should have failed, so the clipboard content should not have changed. + EXPECT_EQ(kNormalText, result); + + ASSERT_TRUE(password->GetNativeComponent()); + password->SelectAll(); + ::SendMessage(password->GetNativeComponent(), WM_CUT, 0, 0); + result.clear(); + clipboard->ReadText(&result); + // Cut should have failed, so the clipboard content should not have changed. + EXPECT_EQ(kNormalText, result); + + // + // Test copy. + // + + // Let's start with read_only as the clipboard already contains the content + // of normal. + read_only->SelectAll(); + ::SendMessage(read_only->GetNativeComponent(), WM_COPY, 0, 0); + result.clear(); + clipboard->ReadText(&result); + EXPECT_EQ(kReadOnlyText, result); + + normal->SelectAll(); + ::SendMessage(normal->GetNativeComponent(), WM_COPY, 0, 0); + result.clear(); + clipboard->ReadText(&result); + EXPECT_EQ(kNormalText, result); + + password->SelectAll(); + ::SendMessage(password->GetNativeComponent(), WM_COPY, 0, 0); + result.clear(); + clipboard->ReadText(&result); + // We don't let you copy from a password field, clipboard should not have + // changed. + EXPECT_EQ(kNormalText, result); + + // + // Test Paste. + // + // Note that we use GetWindowText instead of TextField::GetText below as the + // text in the TextField class is synced to the text of the HWND on + // WM_KEYDOWN messages that we are not simulating here. + + // Attempting to copy kNormalText in a read-only text-field should fail. + read_only->SelectAll(); + ::SendMessage(read_only->GetNativeComponent(), WM_KEYDOWN, 0, 0); + wchar_t buffer[1024] = { 0 }; + ::GetWindowText(read_only->GetNativeComponent(), buffer, 1024); + EXPECT_EQ(kReadOnlyText, std::wstring(buffer)); + + password->SelectAll(); + ::SendMessage(password->GetNativeComponent(), WM_PASTE, 0, 0); + ::GetWindowText(password->GetNativeComponent(), buffer, 1024); + EXPECT_EQ(kNormalText, std::wstring(buffer)); + + // Copy from read_only so the string we are pasting is not the same as the + // current one. + read_only->SelectAll(); + ::SendMessage(read_only->GetNativeComponent(), WM_COPY, 0, 0); + normal->SelectAll(); + ::SendMessage(normal->GetNativeComponent(), WM_PASTE, 0, 0); + ::GetWindowText(normal->GetNativeComponent(), buffer, 1024); + EXPECT_EQ(kReadOnlyText, std::wstring(buffer)); +} +#endif + //////////////////////////////////////////////////////////////////////////////// // Dialogs' default button //////////////////////////////////////////////////////////////////////////////// |