Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: chrome/browser/ui/views/tabs/tab_unittest.cc

Issue 591963002: Tab audio mute control (views UI), behind a switch (off by default). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase + add about:flags experiment Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/views/tabs/tab_strip_controller.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/tabs/tab.h" 5 #include "chrome/browser/ui/views/tabs/tab.h"
6 6
7 #include "base/i18n/rtl.h"
7 #include "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/ui/views/tabs/media_indicator_button.h"
8 #include "chrome/browser/ui/views/tabs/tab_controller.h" 10 #include "chrome/browser/ui/views/tabs/tab_controller.h"
9 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/base/models/list_selection_model.h" 12 #include "ui/base/models/list_selection_model.h"
11 #include "ui/views/controls/button/image_button.h" 13 #include "ui/views/controls/button/image_button.h"
12 #include "ui/views/controls/label.h" 14 #include "ui/views/controls/label.h"
13 #include "ui/views/test/views_test_base.h" 15 #include "ui/views/test/views_test_base.h"
14 #include "ui/views/widget/widget.h" 16 #include "ui/views/widget/widget.h"
15 17
16 using views::Widget; 18 using views::Widget;
17 19
18 class FakeTabController : public TabController { 20 class FakeTabController : public TabController {
19 public: 21 public:
20 FakeTabController() : immersive_style_(false), active_tab_(false) { 22 FakeTabController() : immersive_style_(false), active_tab_(false) {
21 } 23 }
22 virtual ~FakeTabController() {} 24 virtual ~FakeTabController() {}
23 25
24 void set_immersive_style(bool value) { immersive_style_ = value; } 26 void set_immersive_style(bool value) { immersive_style_ = value; }
25 void set_active_tab(bool value) { active_tab_ = value; } 27 void set_active_tab(bool value) { active_tab_ = value; }
26 28
27 virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE { 29 virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE {
28 return selection_model_; 30 return selection_model_;
29 } 31 }
30 virtual bool SupportsMultipleSelection() OVERRIDE { return false; } 32 virtual bool SupportsMultipleSelection() OVERRIDE { return false; }
31 virtual void SelectTab(Tab* tab) OVERRIDE {} 33 virtual void SelectTab(Tab* tab) OVERRIDE {}
32 virtual void ExtendSelectionTo(Tab* tab) OVERRIDE {} 34 virtual void ExtendSelectionTo(Tab* tab) OVERRIDE {}
33 virtual void ToggleSelected(Tab* tab) OVERRIDE {} 35 virtual void ToggleSelected(Tab* tab) OVERRIDE {}
34 virtual void AddSelectionFromAnchorTo(Tab* tab) OVERRIDE {} 36 virtual void AddSelectionFromAnchorTo(Tab* tab) OVERRIDE {}
35 virtual void CloseTab(Tab* tab, CloseTabSource source) OVERRIDE {} 37 virtual void CloseTab(Tab* tab, CloseTabSource source) OVERRIDE {}
38 virtual void ToggleTabAudioMute(Tab* tab) OVERRIDE {}
36 virtual void ShowContextMenuForTab(Tab* tab, 39 virtual void ShowContextMenuForTab(Tab* tab,
37 const gfx::Point& p, 40 const gfx::Point& p,
38 ui::MenuSourceType source_type) OVERRIDE {} 41 ui::MenuSourceType source_type) OVERRIDE {}
39 virtual bool IsActiveTab(const Tab* tab) const OVERRIDE { 42 virtual bool IsActiveTab(const Tab* tab) const OVERRIDE {
40 return active_tab_; 43 return active_tab_;
41 } 44 }
42 virtual bool IsTabSelected(const Tab* tab) const OVERRIDE { 45 virtual bool IsTabSelected(const Tab* tab) const OVERRIDE {
43 return false; 46 return false;
44 } 47 }
45 virtual bool IsTabPinned(const Tab* tab) const OVERRIDE { return false; } 48 virtual bool IsTabPinned(const Tab* tab) const OVERRIDE { return false; }
(...skipping 18 matching lines...) Expand all
64 ui::AXViewState* state) OVERRIDE{}; 67 ui::AXViewState* state) OVERRIDE{};
65 68
66 private: 69 private:
67 ui::ListSelectionModel selection_model_; 70 ui::ListSelectionModel selection_model_;
68 bool immersive_style_; 71 bool immersive_style_;
69 bool active_tab_; 72 bool active_tab_;
70 73
71 DISALLOW_COPY_AND_ASSIGN(FakeTabController); 74 DISALLOW_COPY_AND_ASSIGN(FakeTabController);
72 }; 75 };
73 76
74 class TabTest : public views::ViewsTestBase { 77 class TabTest : public views::ViewsTestBase,
78 public ::testing::WithParamInterface<bool> {
75 public: 79 public:
76 TabTest() {} 80 TabTest() {}
77 virtual ~TabTest() {} 81 virtual ~TabTest() {}
78 82
79 static void DisableMediaIndicatorAnimation(Tab* tab) { 83 bool testing_for_rtl_locale() const { return GetParam(); }
80 tab->media_indicator_animation_.reset(); 84
81 tab->animating_media_state_ = tab->data_.media_state; 85 virtual void SetUp() OVERRIDE {
86 if (testing_for_rtl_locale()) {
87 original_locale_ = base::i18n::GetConfiguredLocale();
88 base::i18n::SetICUDefaultLocale("he");
89 }
90 views::ViewsTestBase::SetUp();
91 }
92
93 virtual void TearDown() OVERRIDE {
94 views::ViewsTestBase::TearDown();
95 if (testing_for_rtl_locale())
96 base::i18n::SetICUDefaultLocale(original_locale_);
82 } 97 }
83 98
84 static void CheckForExpectedLayoutAndVisibilityOfElements(const Tab& tab) { 99 static void CheckForExpectedLayoutAndVisibilityOfElements(const Tab& tab) {
85 // Check whether elements are visible when they are supposed to be, given 100 // Check whether elements are visible when they are supposed to be, given
86 // Tab size and TabRendererData state. 101 // Tab size and TabRendererData state.
87 if (tab.data_.mini) { 102 if (tab.data_.mini) {
88 EXPECT_EQ(1, tab.IconCapacity()); 103 EXPECT_EQ(1, tab.IconCapacity());
89 if (tab.data_.media_state != TAB_MEDIA_STATE_NONE) { 104 if (tab.data_.media_state != TAB_MEDIA_STATE_NONE) {
90 EXPECT_FALSE(tab.ShouldShowIcon()); 105 EXPECT_FALSE(tab.ShouldShowIcon());
91 EXPECT_TRUE(tab.ShouldShowMediaIndicator()); 106 EXPECT_TRUE(tab.ShouldShowMediaIndicator());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 // are fully within the contents bounds. 167 // are fully within the contents bounds.
153 const gfx::Rect contents_bounds = tab.GetContentsBounds(); 168 const gfx::Rect contents_bounds = tab.GetContentsBounds();
154 if (tab.ShouldShowIcon()) { 169 if (tab.ShouldShowIcon()) {
155 EXPECT_LE(contents_bounds.x(), tab.favicon_bounds_.x()); 170 EXPECT_LE(contents_bounds.x(), tab.favicon_bounds_.x());
156 if (tab.title_->width() > 0) 171 if (tab.title_->width() > 0)
157 EXPECT_LE(tab.favicon_bounds_.right(), tab.title_->x()); 172 EXPECT_LE(tab.favicon_bounds_.right(), tab.title_->x());
158 EXPECT_LE(contents_bounds.y(), tab.favicon_bounds_.y()); 173 EXPECT_LE(contents_bounds.y(), tab.favicon_bounds_.y());
159 EXPECT_LE(tab.favicon_bounds_.bottom(), contents_bounds.bottom()); 174 EXPECT_LE(tab.favicon_bounds_.bottom(), contents_bounds.bottom());
160 } 175 }
161 if (tab.ShouldShowIcon() && tab.ShouldShowMediaIndicator()) 176 if (tab.ShouldShowIcon() && tab.ShouldShowMediaIndicator())
162 EXPECT_LE(tab.favicon_bounds_.right(), tab.media_indicator_bounds_.x()); 177 EXPECT_LE(tab.favicon_bounds_.right(), GetMediaIndicatorBounds(tab).x());
163 if (tab.ShouldShowMediaIndicator()) { 178 if (tab.ShouldShowMediaIndicator()) {
164 if (tab.title_->width() > 0) { 179 if (tab.title_->width() > 0) {
165 EXPECT_LE(tab.title_->bounds().right(), 180 EXPECT_LE(tab.title_->bounds().right(),
166 tab.media_indicator_bounds_.x()); 181 GetMediaIndicatorBounds(tab).x());
167 } 182 }
168 EXPECT_LE(tab.media_indicator_bounds_.right(), contents_bounds.right()); 183 EXPECT_LE(GetMediaIndicatorBounds(tab).right(), contents_bounds.right());
169 EXPECT_LE(contents_bounds.y(), tab.media_indicator_bounds_.y()); 184 EXPECT_LE(contents_bounds.y(), GetMediaIndicatorBounds(tab).y());
170 EXPECT_LE(tab.media_indicator_bounds_.bottom(), contents_bounds.bottom()); 185 EXPECT_LE(GetMediaIndicatorBounds(tab).bottom(),
186 contents_bounds.bottom());
171 } 187 }
172 if (tab.ShouldShowMediaIndicator() && tab.ShouldShowCloseBox()) { 188 if (tab.ShouldShowMediaIndicator() && tab.ShouldShowCloseBox()) {
173 // Note: The media indicator can overlap the left-insets of the close box, 189 // Note: The media indicator can overlap the left-insets of the close box,
174 // but should otherwise be to the left of the close button. 190 // but should otherwise be to the left of the close button.
175 EXPECT_LE(tab.media_indicator_bounds_.right(), 191 EXPECT_LE(GetMediaIndicatorBounds(tab).right(),
176 tab.close_button_->bounds().x() + 192 tab.close_button_->bounds().x() +
177 tab.close_button_->GetInsets().left()); 193 tab.close_button_->GetInsets().left());
178 } 194 }
179 if (tab.ShouldShowCloseBox()) { 195 if (tab.ShouldShowCloseBox()) {
180 // Note: The title bounds can overlap the left-insets of the close box, 196 // Note: The title bounds can overlap the left-insets of the close box,
181 // but should otherwise be to the left of the close button. 197 // but should otherwise be to the left of the close button.
182 if (tab.title_->width() > 0) { 198 if (tab.title_->width() > 0) {
183 EXPECT_LE(tab.title_->bounds().right(), 199 EXPECT_LE(tab.title_->bounds().right(),
184 tab.close_button_->bounds().x() + 200 tab.close_button_->bounds().x() +
185 tab.close_button_->GetInsets().left()); 201 tab.close_button_->GetInsets().left());
186 } 202 }
187 EXPECT_LE(tab.close_button_->bounds().right(), contents_bounds.right()); 203 EXPECT_LE(tab.close_button_->bounds().right(), contents_bounds.right());
188 EXPECT_LE(contents_bounds.y(), tab.close_button_->bounds().y()); 204 EXPECT_LE(contents_bounds.y(), tab.close_button_->bounds().y());
189 EXPECT_LE(tab.close_button_->bounds().bottom(), contents_bounds.bottom()); 205 EXPECT_LE(tab.close_button_->bounds().bottom(), contents_bounds.bottom());
190 } 206 }
191 } 207 }
208
209 private:
210 static gfx::Rect GetMediaIndicatorBounds(const Tab& tab) {
211 if (!tab.media_indicator_button_) {
212 ADD_FAILURE();
213 return gfx::Rect();
214 }
215 return tab.media_indicator_button_->bounds();
216 }
217
218 std::string original_locale_;
192 }; 219 };
193 220
194 TEST_F(TabTest, HitTestTopPixel) { 221 TEST_P(TabTest, HitTestTopPixel) {
222 if (testing_for_rtl_locale() && !base::i18n::IsRTL()) {
223 LOG(WARNING) << "Testing of RTL locale not supported on current platform.";
224 return;
225 }
226
195 Widget widget; 227 Widget widget;
196 Widget::InitParams params(CreateParams(Widget::InitParams::TYPE_WINDOW)); 228 Widget::InitParams params(CreateParams(Widget::InitParams::TYPE_WINDOW));
197 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 229 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
198 params.bounds.SetRect(10, 20, 300, 400); 230 params.bounds.SetRect(10, 20, 300, 400);
199 widget.Init(params); 231 widget.Init(params);
200 232
201 FakeTabController tab_controller; 233 FakeTabController tab_controller;
202 Tab tab(&tab_controller); 234 Tab tab(&tab_controller);
203 widget.GetContentsView()->AddChildView(&tab); 235 widget.GetContentsView()->AddChildView(&tab);
204 tab.SetBoundsRect(gfx::Rect(gfx::Point(0, 0), Tab::GetStandardSize())); 236 tab.SetBoundsRect(gfx::Rect(gfx::Point(0, 0), Tab::GetStandardSize()));
205 237
206 // Tabs have some shadow in the top, so by default we don't hit the tab there. 238 // Tabs have some shadow in the top, so by default we don't hit the tab there.
207 int middle_x = tab.width() / 2; 239 int middle_x = tab.width() / 2;
208 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(middle_x, 0))); 240 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(middle_x, 0)));
209 241
210 // Tabs are slanted, so a click halfway down the left edge won't hit it. 242 // Tabs are slanted, so a click halfway down the left edge won't hit it.
211 int middle_y = tab.height() / 2; 243 int middle_y = tab.height() / 2;
212 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, middle_y))); 244 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, middle_y)));
213 245
214 // If the window is maximized, however, we want clicks in the top edge to 246 // If the window is maximized, however, we want clicks in the top edge to
215 // select the tab. 247 // select the tab.
216 widget.Maximize(); 248 widget.Maximize();
217 EXPECT_TRUE(tab.HitTestPoint(gfx::Point(middle_x, 0))); 249 EXPECT_TRUE(tab.HitTestPoint(gfx::Point(middle_x, 0)));
218 250
219 // But clicks in the area above the slanted sides should still miss. 251 // But clicks in the area above the slanted sides should still miss.
220 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, 0))); 252 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, 0)));
221 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(tab.width() - 1, 0))); 253 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(tab.width() - 1, 0)));
222 } 254 }
223 255
224 TEST_F(TabTest, LayoutAndVisibilityOfElements) { 256 TEST_P(TabTest, LayoutAndVisibilityOfElements) {
257 if (testing_for_rtl_locale() && !base::i18n::IsRTL()) {
258 LOG(WARNING) << "Testing of RTL locale not supported on current platform.";
259 return;
260 }
261
225 static const TabMediaState kMediaStatesToTest[] = { 262 static const TabMediaState kMediaStatesToTest[] = {
226 TAB_MEDIA_STATE_NONE, TAB_MEDIA_STATE_CAPTURING, 263 TAB_MEDIA_STATE_NONE, TAB_MEDIA_STATE_CAPTURING,
227 TAB_MEDIA_STATE_AUDIO_PLAYING 264 TAB_MEDIA_STATE_AUDIO_PLAYING, TAB_MEDIA_STATE_AUDIO_MUTING
228 }; 265 };
229 266
230 FakeTabController controller; 267 FakeTabController controller;
231 Tab tab(&controller); 268 Tab tab(&controller);
232 269
233 SkBitmap bitmap; 270 SkBitmap bitmap;
234 bitmap.allocN32Pixels(16, 16); 271 bitmap.allocN32Pixels(16, 16);
235 TabRendererData data; 272 TabRendererData data;
236 data.favicon = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); 273 data.favicon = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
237 274
238 // Perform layout over all possible combinations, checking for correct 275 // Perform layout over all possible combinations, checking for correct
239 // results. 276 // results.
240 for (int is_mini_tab = 0; is_mini_tab < 2; ++is_mini_tab) { 277 for (int is_mini_tab = 0; is_mini_tab < 2; ++is_mini_tab) {
241 for (int is_active_tab = 0; is_active_tab < 2; ++is_active_tab) { 278 for (int is_active_tab = 0; is_active_tab < 2; ++is_active_tab) {
242 for (size_t media_state_index = 0; 279 for (size_t media_state_index = 0;
243 media_state_index < arraysize(kMediaStatesToTest); 280 media_state_index < arraysize(kMediaStatesToTest);
244 ++media_state_index) { 281 ++media_state_index) {
245 const TabMediaState media_state = kMediaStatesToTest[media_state_index]; 282 const TabMediaState media_state = kMediaStatesToTest[media_state_index];
246 SCOPED_TRACE(::testing::Message() 283 SCOPED_TRACE(::testing::Message()
247 << (is_active_tab ? "Active" : "Inactive") << ' ' 284 << (is_active_tab ? "Active" : "Inactive") << ' '
248 << (is_mini_tab ? "Mini " : "") 285 << (is_mini_tab ? "Mini " : "")
249 << "Tab with media indicator state " << media_state); 286 << "Tab with media indicator state " << media_state);
250 287
251 data.mini = !!is_mini_tab; 288 data.mini = !!is_mini_tab;
252 controller.set_active_tab(!!is_active_tab); 289 controller.set_active_tab(!!is_active_tab);
253 data.media_state = media_state; 290 data.media_state = media_state;
254 tab.SetData(data); 291 tab.SetData(data);
255 292
256 // Disable the media indicator animation so that the layout/visibility
257 // logic can be tested effectively. If the animation was left enabled,
258 // the ShouldShowMediaIndicator() method would return true during
259 // fade-out transitions.
260 DisableMediaIndicatorAnimation(&tab);
261
262 // Test layout for every width from standard to minimum. 293 // Test layout for every width from standard to minimum.
263 gfx::Rect bounds(gfx::Point(0, 0), Tab::GetStandardSize()); 294 gfx::Rect bounds(gfx::Point(0, 0), Tab::GetStandardSize());
264 int min_width; 295 int min_width;
265 if (is_mini_tab) { 296 if (is_mini_tab) {
266 bounds.set_width(Tab::GetMiniWidth()); 297 bounds.set_width(Tab::GetMiniWidth());
267 min_width = Tab::GetMiniWidth(); 298 min_width = Tab::GetMiniWidth();
268 } else { 299 } else {
269 min_width = is_active_tab ? Tab::GetMinimumSelectedSize().width() : 300 min_width = is_active_tab ? Tab::GetMinimumSelectedSize().width() :
270 Tab::GetMinimumUnselectedSize().width(); 301 Tab::GetMinimumUnselectedSize().width();
271 } 302 }
272 while (bounds.width() >= min_width) { 303 while (bounds.width() >= min_width) {
273 SCOPED_TRACE(::testing::Message() << "bounds=" << bounds.ToString()); 304 SCOPED_TRACE(::testing::Message() << "bounds=" << bounds.ToString());
274 tab.SetBoundsRect(bounds); // Invokes Tab::Layout(). 305 tab.SetBoundsRect(bounds); // Invokes Tab::Layout().
275 CheckForExpectedLayoutAndVisibilityOfElements(tab); 306 CheckForExpectedLayoutAndVisibilityOfElements(tab);
276 bounds.set_width(bounds.width() - 1); 307 bounds.set_width(bounds.width() - 1);
277 } 308 }
278 } 309 }
279 } 310 }
280 } 311 }
281 } 312 }
282 313
283 // Regression test for http://crbug.com/226253. Calling Layout() more than once 314 // Regression test for http://crbug.com/226253. Calling Layout() more than once
284 // shouldn't change the insets of the close button. 315 // shouldn't change the insets of the close button.
285 TEST_F(TabTest, CloseButtonLayout) { 316 TEST_P(TabTest, CloseButtonLayout) {
317 if (testing_for_rtl_locale() && !base::i18n::IsRTL()) {
318 LOG(WARNING) << "Testing of RTL locale not supported on current platform.";
319 return;
320 }
321
286 FakeTabController tab_controller; 322 FakeTabController tab_controller;
287 Tab tab(&tab_controller); 323 Tab tab(&tab_controller);
288 tab.SetBounds(0, 0, 100, 50); 324 tab.SetBounds(0, 0, 100, 50);
289 tab.Layout(); 325 tab.Layout();
290 gfx::Insets close_button_insets = tab.close_button_->GetInsets(); 326 gfx::Insets close_button_insets = tab.close_button_->GetInsets();
291 tab.Layout(); 327 tab.Layout();
292 gfx::Insets close_button_insets_2 = tab.close_button_->GetInsets(); 328 gfx::Insets close_button_insets_2 = tab.close_button_->GetInsets();
293 EXPECT_EQ(close_button_insets.top(), close_button_insets_2.top()); 329 EXPECT_EQ(close_button_insets.top(), close_button_insets_2.top());
294 EXPECT_EQ(close_button_insets.left(), close_button_insets_2.left()); 330 EXPECT_EQ(close_button_insets.left(), close_button_insets_2.left());
295 EXPECT_EQ(close_button_insets.bottom(), close_button_insets_2.bottom()); 331 EXPECT_EQ(close_button_insets.bottom(), close_button_insets_2.bottom());
296 EXPECT_EQ(close_button_insets.right(), close_button_insets_2.right()); 332 EXPECT_EQ(close_button_insets.right(), close_button_insets_2.right());
297 333
298 // Also make sure the close button is sized as large as the tab. 334 // Also make sure the close button is sized as large as the tab.
299 EXPECT_EQ(50, tab.close_button_->bounds().height()); 335 EXPECT_EQ(50, tab.close_button_->bounds().height());
300 } 336 }
337
338 // Test in both a LTR and a RTL locale. Note: The fact that the UI code is
339 // configured for an RTL locale does *not* change how the coordinates are
340 // examined in the tests above because views::View and friends are supposed to
341 // auto-mirror the widgets when painting. Thus, what we're testing here is that
342 // there's no code in Tab that will erroneously subvert this automatic
343 // coordinate translation. http://crbug.com/384179
344 INSTANTIATE_TEST_CASE_P(, TabTest, ::testing::Values(false, true));
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab_strip_controller.h ('k') | chrome/chrome_browser_ui.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698