OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/views/page_info/page_info_popup_view.h" | |
6 | |
7 #include "base/macros.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" | |
10 #include "chrome/browser/ui/views/page_info/chosen_object_row.h" | |
11 #include "chrome/browser/ui/views/page_info/permission_selector_row.h" | |
12 #include "chrome/browser/usb/usb_chooser_context.h" | |
13 #include "chrome/browser/usb/usb_chooser_context_factory.h" | |
14 #include "chrome/test/base/testing_profile.h" | |
15 #include "content/public/browser/ssl_status.h" | |
16 #include "content/public/test/test_browser_thread_bundle.h" | |
17 #include "content/public/test/test_web_contents_factory.h" | |
18 #include "device/base/mock_device_client.h" | |
19 #include "device/usb/mock_usb_device.h" | |
20 #include "device/usb/mock_usb_service.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 #include "ui/events/event_utils.h" | |
23 #include "ui/views/controls/button/menu_button.h" | |
24 #include "ui/views/controls/combobox/combobox.h" | |
25 #include "ui/views/controls/label.h" | |
26 #include "ui/views/test/scoped_views_test_helper.h" | |
27 | |
28 const char* kUrl = "http://www.example.com/index.html"; | |
29 | |
30 namespace test { | |
31 | |
32 class PageInfoPopupViewTestApi { | |
33 public: | |
34 PageInfoPopupViewTestApi(gfx::NativeView parent, | |
35 Profile* profile, | |
36 content::WebContents* web_contents) | |
37 : view_(nullptr), | |
38 parent_(parent), | |
39 profile_(profile), | |
40 web_contents_(web_contents) { | |
41 CreateView(); | |
42 } | |
43 | |
44 void CreateView() { | |
45 if (view_) | |
46 view_->GetWidget()->CloseNow(); | |
47 | |
48 security_state::SecurityInfo security_info; | |
49 views::View* anchor_view = nullptr; | |
50 view_ = new PageInfoPopupView(anchor_view, parent_, profile_, web_contents_, | |
51 GURL(kUrl), security_info); | |
52 } | |
53 | |
54 PageInfoPopupView* view() { return view_; } | |
55 views::View* permissions_view() { return view_->permissions_view_; } | |
56 | |
57 PermissionSelectorRow* GetPermissionSelectorAt(int index) { | |
58 return view_->selector_rows_[index].get(); | |
59 } | |
60 | |
61 // Returns the permission label text of the |index|th permission selector row. | |
62 // This function returns an empty string if the permission selector row's | |
63 // |label_| element isn't actually a |views::Label|. | |
64 base::string16 GetPermissionLabelTextAt(int index) { | |
65 views::View* view = GetPermissionSelectorAt(index)->label_; | |
66 if (view->GetClassName() == views::Label::kViewClassName) | |
67 return static_cast<views::Label*>(view)->text(); | |
68 return base::string16(); | |
69 } | |
70 | |
71 base::string16 GetPermissionButtonTextAt(int index) { | |
72 views::View* view = GetPermissionSelectorAt(index)->button(); | |
73 if (view->GetClassName() == views::MenuButton::kViewClassName) { | |
74 return static_cast<views::MenuButton*>(view)->GetText(); | |
75 } else if (view->GetClassName() == views::Combobox::kViewClassName) { | |
76 views::Combobox* combobox = static_cast<views::Combobox*>(view); | |
77 return combobox->GetTextForRow(combobox->GetSelectedRow()); | |
78 } else { | |
79 NOTREACHED() << "Unknown class " << view->GetClassName(); | |
80 return base::string16(); | |
81 } | |
82 } | |
83 | |
84 // Simulates recreating the dialog with a new PermissionInfoList. | |
85 void SetPermissionInfo(const PermissionInfoList& list) { | |
86 for (const PageInfoPopupView::PermissionInfo& info : list) | |
87 view_->presenter_->OnSitePermissionChanged(info.type, info.setting); | |
88 CreateView(); | |
89 } | |
90 | |
91 private: | |
92 PageInfoPopupView* view_; // Weak. Owned by its Widget. | |
93 | |
94 // For recreating the view. | |
95 gfx::NativeView parent_; | |
96 Profile* profile_; | |
97 content::WebContents* web_contents_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(PageInfoPopupViewTestApi); | |
100 }; | |
101 | |
102 } // namespace test | |
103 | |
104 namespace { | |
105 | |
106 // Helper class that wraps a TestingProfile and a TestWebContents for a test | |
107 // harness. Inspired by RenderViewHostTestHarness, but doesn't use inheritance | |
108 // so the helper can be composed with other helpers in the test harness. | |
109 class ScopedWebContentsTestHelper { | |
110 public: | |
111 ScopedWebContentsTestHelper() { | |
112 web_contents_ = factory_.CreateWebContents(&profile_); | |
113 } | |
114 | |
115 Profile* profile() { return &profile_; } | |
116 content::WebContents* web_contents() { return web_contents_; } | |
117 | |
118 private: | |
119 content::TestBrowserThreadBundle thread_bundle_; | |
120 TestingProfile profile_; | |
121 content::TestWebContentsFactory factory_; | |
122 content::WebContents* web_contents_; // Weak. Owned by factory_. | |
123 | |
124 DISALLOW_COPY_AND_ASSIGN(ScopedWebContentsTestHelper); | |
125 }; | |
126 | |
127 class PageInfoPopupViewTest : public testing::Test { | |
128 public: | |
129 PageInfoPopupViewTest() {} | |
130 | |
131 // testing::Test: | |
132 void SetUp() override { | |
133 views::Widget::InitParams parent_params; | |
134 parent_params.context = views_helper_.GetContext(); | |
135 parent_window_ = new views::Widget(); | |
136 parent_window_->Init(parent_params); | |
137 | |
138 content::WebContents* web_contents = web_contents_helper_.web_contents(); | |
139 TabSpecificContentSettings::CreateForWebContents(web_contents); | |
140 api_.reset(new test::PageInfoPopupViewTestApi( | |
141 parent_window_->GetNativeView(), web_contents_helper_.profile(), | |
142 web_contents)); | |
143 } | |
144 | |
145 void TearDown() override { parent_window_->CloseNow(); } | |
146 | |
147 protected: | |
148 device::MockDeviceClient device_client_; | |
149 ScopedWebContentsTestHelper web_contents_helper_; | |
150 views::ScopedViewsTestHelper views_helper_; | |
151 | |
152 views::Widget* parent_window_ = nullptr; // Weak. Owned by the NativeWidget. | |
153 std::unique_ptr<test::PageInfoPopupViewTestApi> api_; | |
154 | |
155 private: | |
156 DISALLOW_COPY_AND_ASSIGN(PageInfoPopupViewTest); | |
157 }; | |
158 | |
159 } // namespace | |
160 | |
161 // TODO(ellyjones): re-enable this test for OSX. | |
162 // This test exercises PermissionSelectorRow in a way that it is not used in | |
163 // practice. In practice, every setting in PermissionSelectorRow starts off | |
164 // "set", so there is always one option checked in the resulting MenuModel. This | |
165 // test creates settings that are left at their defaults, leading to zero | |
166 // checked options, and checks that the text on the MenuButtons is right. Since | |
167 // the Comboboxes the MacViews version of this dialog uses don't have separate | |
168 // text, this test doesn't work. | |
169 #if defined(OS_MACOSX) | |
170 #define MAYBE_SetPermissionInfo DISABLED_SetPermissionInfo | |
171 #else | |
172 #define MAYBE_SetPermissionInfo SetPermissionInfo | |
173 #endif | |
174 | |
175 // Each permission selector row is like this: [icon] [label] [selector] | |
176 constexpr int kViewsPerPermissionRow = 3; | |
177 | |
178 // Test UI construction and reconstruction via | |
179 // PageInfoPopupView::SetPermissionInfo(). | |
180 TEST_F(PageInfoPopupViewTest, MAYBE_SetPermissionInfo) { | |
181 PermissionInfoList list(1); | |
182 list.back().type = CONTENT_SETTINGS_TYPE_GEOLOCATION; | |
183 list.back().source = content_settings::SETTING_SOURCE_USER; | |
184 list.back().is_incognito = false; | |
185 list.back().setting = CONTENT_SETTING_DEFAULT; | |
186 | |
187 const int kExpectedChildren = | |
188 kViewsPerPermissionRow * | |
189 (ExclusiveAccessManager::IsSimplifiedFullscreenUIEnabled() ? 11 : 13); | |
190 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
191 | |
192 list.back().setting = CONTENT_SETTING_ALLOW; | |
193 api_->SetPermissionInfo(list); | |
194 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
195 | |
196 PermissionSelectorRow* selector = api_->GetPermissionSelectorAt(0); | |
197 EXPECT_TRUE(selector); | |
198 | |
199 // Verify labels match the settings on the PermissionInfoList. | |
200 EXPECT_EQ(base::ASCIIToUTF16("Location"), api_->GetPermissionLabelTextAt(0)); | |
201 EXPECT_EQ(base::ASCIIToUTF16("Allow"), api_->GetPermissionButtonTextAt(0)); | |
202 | |
203 // Verify calling SetPermisisonInfo() directly updates the UI. | |
204 list.back().setting = CONTENT_SETTING_BLOCK; | |
205 api_->SetPermissionInfo(list); | |
206 EXPECT_EQ(base::ASCIIToUTF16("Block"), api_->GetPermissionButtonTextAt(0)); | |
207 | |
208 // Simulate a user selection via the UI. Note this will also cover logic in | |
209 // PageInfo to update the pref. | |
210 list.back().setting = CONTENT_SETTING_ALLOW; | |
211 api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); | |
212 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
213 EXPECT_EQ(base::ASCIIToUTF16("Allow"), api_->GetPermissionButtonTextAt(0)); | |
214 | |
215 // Setting to the default via the UI should keep the button around. | |
216 list.back().setting = CONTENT_SETTING_ASK; | |
217 api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); | |
218 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
219 EXPECT_EQ(base::ASCIIToUTF16("Ask"), api_->GetPermissionButtonTextAt(0)); | |
220 | |
221 // However, since the setting is now default, recreating the dialog with those | |
222 // settings should omit the permission from the UI. | |
223 api_->SetPermissionInfo(list); | |
224 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
225 } | |
226 | |
227 // Test UI construction and reconstruction with USB devices. | |
228 TEST_F(PageInfoPopupViewTest, SetPermissionInfoWithUsbDevice) { | |
229 const int kExpectedChildren = | |
230 kViewsPerPermissionRow * | |
231 (ExclusiveAccessManager::IsSimplifiedFullscreenUIEnabled() ? 11 : 13); | |
232 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
233 | |
234 const GURL origin = GURL(kUrl).GetOrigin(); | |
235 scoped_refptr<device::UsbDevice> device = | |
236 new device::MockUsbDevice(0, 0, "Google", "Gizmo", "1234567890"); | |
237 device_client_.usb_service()->AddDevice(device); | |
238 UsbChooserContext* store = | |
239 UsbChooserContextFactory::GetForProfile(web_contents_helper_.profile()); | |
240 store->GrantDevicePermission(origin, origin, device->guid()); | |
241 | |
242 PermissionInfoList list; | |
243 api_->SetPermissionInfo(list); | |
244 EXPECT_EQ(kExpectedChildren + 1, api_->permissions_view()->child_count()); | |
245 | |
246 ChosenObjectRow* object_view = static_cast<ChosenObjectRow*>( | |
247 api_->permissions_view()->child_at(kExpectedChildren)); | |
248 EXPECT_EQ(3, object_view->child_count()); | |
249 | |
250 const int kLabelIndex = 1; | |
251 views::Label* label = | |
252 static_cast<views::Label*>(object_view->child_at(kLabelIndex)); | |
253 EXPECT_EQ(base::ASCIIToUTF16("Gizmo"), label->text()); | |
254 | |
255 const int kButtonIndex = 2; | |
256 views::Button* button = | |
257 static_cast<views::Button*>(object_view->child_at(kButtonIndex)); | |
258 | |
259 const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), | |
260 ui::EventTimeForNow(), 0, 0); | |
261 views::ButtonListener* button_listener = | |
262 static_cast<views::ButtonListener*>(object_view); | |
263 button_listener->ButtonPressed(button, event); | |
264 api_->SetPermissionInfo(list); | |
265 EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count()); | |
266 EXPECT_FALSE(store->HasDevicePermission(origin, origin, device)); | |
267 } | |
OLD | NEW |