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 "base/command_line.h" |
| 6 #include "base/test/histogram_tester.h" |
| 7 #include "base/timer/mock_timer.h" |
| 8 #include "base/values.h" |
| 9 #include "chrome/browser/engagement/site_engagement_helper.h" |
| 10 #include "chrome/browser/engagement/site_engagement_service.h" |
| 11 #include "chrome/browser/engagement/site_engagement_service_factory.h" |
| 12 #include "chrome/browser/ui/browser.h" |
| 13 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 14 #include "chrome/common/chrome_switches.h" |
| 15 #include "chrome/test/base/browser_with_test_window_test.h" |
| 16 #include "content/public/browser/page_navigator.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 class SiteEngagementHelperTest : public BrowserWithTestWindowTest { |
| 20 public: |
| 21 // Create a SiteEngagementHelper. Called here as friend class methods cannot |
| 22 // be called in tests. |
| 23 scoped_ptr<SiteEngagementHelper> CreateHelper( |
| 24 content::WebContents* web_contents) { |
| 25 scoped_ptr<SiteEngagementHelper> helper( |
| 26 new SiteEngagementHelper(web_contents)); |
| 27 DCHECK(helper.get()); |
| 28 |
| 29 return helper.Pass(); |
| 30 } |
| 31 |
| 32 void StartTracking(SiteEngagementHelper* helper) { |
| 33 helper->input_tracker_.StartTracking(); |
| 34 } |
| 35 |
| 36 // Simulate a user interaction event and handle it. |
| 37 void HandleUserInput(SiteEngagementHelper* helper, |
| 38 blink::WebInputEvent::Type type) { |
| 39 helper->input_tracker_.DidGetUserInteraction(type); |
| 40 } |
| 41 |
| 42 // Simulate a user interaction event and handle it. Reactivates tracking |
| 43 // immediately. |
| 44 void HandleUserInputAndRestartTracking(SiteEngagementHelper* helper, |
| 45 blink::WebInputEvent::Type type) { |
| 46 helper->input_tracker_.DidGetUserInteraction(type); |
| 47 helper->input_tracker_.StartTracking(); |
| 48 } |
| 49 |
| 50 // Set a pause timer on the input tracker for test purposes. |
| 51 void SetInputTrackerPauseTimer(SiteEngagementHelper* helper, |
| 52 scoped_ptr<base::Timer> timer) { |
| 53 helper->input_tracker_.SetPauseTimerForTesting(timer.Pass()); |
| 54 } |
| 55 |
| 56 bool IsTracking(SiteEngagementHelper* helper) { |
| 57 return helper->input_tracker_.is_tracking(); |
| 58 } |
| 59 |
| 60 void NavigateWithDisposition(GURL& url, WindowOpenDisposition disposition) { |
| 61 content::NavigationController* controller = |
| 62 &browser()->tab_strip_model()->GetActiveWebContents()->GetController(); |
| 63 browser()->OpenURL( |
| 64 content::OpenURLParams(url, content::Referrer(), disposition, |
| 65 ui::PAGE_TRANSITION_TYPED, false)); |
| 66 CommitPendingLoad(controller); |
| 67 } |
| 68 |
| 69 void UserInputAccumulation(const blink::WebInputEvent::Type type) { |
| 70 AddTab(browser(), GURL("about:blank")); |
| 71 GURL url1("https://www.google.com/"); |
| 72 GURL url2("http://www.google.com/"); |
| 73 content::WebContents* web_contents = |
| 74 browser()->tab_strip_model()->GetActiveWebContents(); |
| 75 |
| 76 scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents)); |
| 77 SiteEngagementService* service = |
| 78 SiteEngagementServiceFactory::GetForProfile(browser()->profile()); |
| 79 DCHECK(service); |
| 80 |
| 81 // Check that navigation triggers engagement. |
| 82 NavigateWithDisposition(url1, CURRENT_TAB); |
| 83 StartTracking(helper.get()); |
| 84 |
| 85 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1)); |
| 86 EXPECT_EQ(0, service->GetScore(url2)); |
| 87 |
| 88 // Simulate a user input trigger and ensure it is treated correctly. |
| 89 HandleUserInputAndRestartTracking(helper.get(), type); |
| 90 |
| 91 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1)); |
| 92 EXPECT_EQ(0, service->GetScore(url2)); |
| 93 |
| 94 // Simulate three inputs , and ensure they are treated correctly. |
| 95 HandleUserInputAndRestartTracking(helper.get(), type); |
| 96 HandleUserInputAndRestartTracking(helper.get(), type); |
| 97 HandleUserInputAndRestartTracking(helper.get(), type); |
| 98 |
| 99 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1)); |
| 100 EXPECT_EQ(0, service->GetScore(url2)); |
| 101 |
| 102 // Simulate inputs for a different link. |
| 103 NavigateWithDisposition(url2, CURRENT_TAB); |
| 104 StartTracking(helper.get()); |
| 105 |
| 106 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1)); |
| 107 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2)); |
| 108 EXPECT_DOUBLE_EQ(1.2, service->GetTotalEngagementPoints()); |
| 109 |
| 110 HandleUserInputAndRestartTracking(helper.get(), type); |
| 111 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1)); |
| 112 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2)); |
| 113 EXPECT_DOUBLE_EQ(1.25, service->GetTotalEngagementPoints()); |
| 114 } |
| 115 }; |
| 116 |
| 117 TEST_F(SiteEngagementHelperTest, KeyPressEngagementAccumulation) { |
| 118 UserInputAccumulation(blink::WebInputEvent::RawKeyDown); |
| 119 } |
| 120 |
| 121 TEST_F(SiteEngagementHelperTest, MouseEventEngagementAccumulation) { |
| 122 UserInputAccumulation(blink::WebInputEvent::MouseDown); |
| 123 } |
| 124 |
| 125 TEST_F(SiteEngagementHelperTest, GestureEngagementAccumulation) { |
| 126 UserInputAccumulation(blink::WebInputEvent::GestureTapDown); |
| 127 } |
| 128 |
| 129 TEST_F(SiteEngagementHelperTest, MixedInputEngagementAccumulation) { |
| 130 AddTab(browser(), GURL("about:blank")); |
| 131 GURL url1("https://www.google.com/"); |
| 132 GURL url2("http://www.google.com/"); |
| 133 content::WebContents* web_contents = |
| 134 browser()->tab_strip_model()->GetActiveWebContents(); |
| 135 |
| 136 scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents)); |
| 137 SiteEngagementService* service = |
| 138 SiteEngagementServiceFactory::GetForProfile(browser()->profile()); |
| 139 DCHECK(service); |
| 140 |
| 141 base::HistogramTester histograms; |
| 142 |
| 143 // Histograms should start off empty. |
| 144 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 145 0); |
| 146 |
| 147 NavigateWithDisposition(url1, CURRENT_TAB); |
| 148 StartTracking(helper.get()); |
| 149 |
| 150 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1)); |
| 151 EXPECT_EQ(0, service->GetScore(url2)); |
| 152 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 153 1); |
| 154 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 155 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION, 1); |
| 156 |
| 157 HandleUserInputAndRestartTracking(helper.get(), |
| 158 blink::WebInputEvent::RawKeyDown); |
| 159 HandleUserInputAndRestartTracking(helper.get(), |
| 160 blink::WebInputEvent::GestureTapDown); |
| 161 HandleUserInputAndRestartTracking(helper.get(), |
| 162 blink::WebInputEvent::GestureTapDown); |
| 163 HandleUserInputAndRestartTracking(helper.get(), |
| 164 blink::WebInputEvent::RawKeyDown); |
| 165 HandleUserInputAndRestartTracking(helper.get(), |
| 166 blink::WebInputEvent::MouseDown); |
| 167 |
| 168 EXPECT_DOUBLE_EQ(0.75, service->GetScore(url1)); |
| 169 EXPECT_EQ(0, service->GetScore(url2)); |
| 170 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 171 6); |
| 172 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 173 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION, 1); |
| 174 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 175 SiteEngagementMetrics::ENGAGEMENT_KEYPRESS, 2); |
| 176 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 177 SiteEngagementMetrics::ENGAGEMENT_MOUSE, 1); |
| 178 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 179 SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE, |
| 180 2); |
| 181 |
| 182 HandleUserInputAndRestartTracking(helper.get(), |
| 183 blink::WebInputEvent::MouseDown); |
| 184 HandleUserInputAndRestartTracking(helper.get(), |
| 185 blink::WebInputEvent::MouseDown); |
| 186 HandleUserInputAndRestartTracking(helper.get(), |
| 187 blink::WebInputEvent::GestureTapDown); |
| 188 |
| 189 EXPECT_DOUBLE_EQ(0.9, service->GetScore(url1)); |
| 190 EXPECT_EQ(0, service->GetScore(url2)); |
| 191 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 192 9); |
| 193 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 194 SiteEngagementMetrics::ENGAGEMENT_MOUSE, 3); |
| 195 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 196 SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE, |
| 197 3); |
| 198 |
| 199 NavigateWithDisposition(url2, CURRENT_TAB); |
| 200 StartTracking(helper.get()); |
| 201 |
| 202 EXPECT_DOUBLE_EQ(0.9, service->GetScore(url1)); |
| 203 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2)); |
| 204 EXPECT_DOUBLE_EQ(1.4, service->GetTotalEngagementPoints()); |
| 205 |
| 206 HandleUserInputAndRestartTracking(helper.get(), |
| 207 blink::WebInputEvent::GestureTapDown); |
| 208 HandleUserInputAndRestartTracking(helper.get(), |
| 209 blink::WebInputEvent::RawKeyDown); |
| 210 |
| 211 EXPECT_DOUBLE_EQ(0.9, service->GetScore(url1)); |
| 212 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url2)); |
| 213 EXPECT_DOUBLE_EQ(1.5, service->GetTotalEngagementPoints()); |
| 214 histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 215 12); |
| 216 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 217 SiteEngagementMetrics::ENGAGEMENT_NAVIGATION, 2); |
| 218 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 219 SiteEngagementMetrics::ENGAGEMENT_KEYPRESS, 3); |
| 220 histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, |
| 221 SiteEngagementMetrics::ENGAGEMENT_TOUCH_GESTURE, |
| 222 4); |
| 223 } |
| 224 |
| 225 TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) { |
| 226 AddTab(browser(), GURL("about:blank")); |
| 227 GURL url1("https://www.google.com/"); |
| 228 GURL url2("http://www.google.com/"); |
| 229 content::WebContents* web_contents = |
| 230 browser()->tab_strip_model()->GetActiveWebContents(); |
| 231 |
| 232 base::MockTimer* input_tracker_timer = new base::MockTimer(true, false); |
| 233 scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents)); |
| 234 SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer)); |
| 235 |
| 236 SiteEngagementService* service = |
| 237 SiteEngagementServiceFactory::GetForProfile(browser()->profile()); |
| 238 DCHECK(service); |
| 239 |
| 240 NavigateWithDisposition(url1, CURRENT_TAB); |
| 241 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1)); |
| 242 EXPECT_EQ(0, service->GetScore(url2)); |
| 243 |
| 244 // Timer should be running for navigation delay. |
| 245 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 246 EXPECT_FALSE(IsTracking(helper.get())); |
| 247 input_tracker_timer->Fire(); |
| 248 |
| 249 // Timer should start running again after input. |
| 250 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 251 EXPECT_TRUE(IsTracking(helper.get())); |
| 252 HandleUserInput(helper.get(), blink::WebInputEvent::RawKeyDown); |
| 253 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 254 EXPECT_FALSE(IsTracking(helper.get())); |
| 255 |
| 256 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1)); |
| 257 EXPECT_EQ(0, service->GetScore(url2)); |
| 258 |
| 259 input_tracker_timer->Fire(); |
| 260 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 261 EXPECT_TRUE(IsTracking(helper.get())); |
| 262 |
| 263 // Timer should start running again after input. |
| 264 HandleUserInput(helper.get(), blink::WebInputEvent::GestureTapDown); |
| 265 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 266 EXPECT_FALSE(IsTracking(helper.get())); |
| 267 |
| 268 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1)); |
| 269 EXPECT_EQ(0, service->GetScore(url2)); |
| 270 |
| 271 input_tracker_timer->Fire(); |
| 272 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 273 EXPECT_TRUE(IsTracking(helper.get())); |
| 274 |
| 275 // Timer should be running for navigation delay. |
| 276 NavigateWithDisposition(url2, CURRENT_TAB); |
| 277 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 278 EXPECT_FALSE(IsTracking(helper.get())); |
| 279 |
| 280 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1)); |
| 281 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2)); |
| 282 |
| 283 input_tracker_timer->Fire(); |
| 284 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 285 EXPECT_TRUE(IsTracking(helper.get())); |
| 286 |
| 287 HandleUserInput(helper.get(), blink::WebInputEvent::MouseDown); |
| 288 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 289 EXPECT_FALSE(IsTracking(helper.get())); |
| 290 |
| 291 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1)); |
| 292 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2)); |
| 293 EXPECT_DOUBLE_EQ(1.15, service->GetTotalEngagementPoints()); |
| 294 } |
| 295 |
| 296 // Ensure that navigation does not trigger input tracking until after a delay. |
| 297 // We must manually call WasShown/WasHidden as they are not triggered |
| 298 // automatically in this test environment. |
| 299 TEST_F(SiteEngagementHelperTest, ShowAndHide) { |
| 300 AddTab(browser(), GURL("about:blank")); |
| 301 GURL url1("https://www.google.com/"); |
| 302 GURL url2("http://www.google.com/"); |
| 303 content::WebContents* web_contents = |
| 304 browser()->tab_strip_model()->GetActiveWebContents(); |
| 305 |
| 306 base::MockTimer* input_tracker_timer = new base::MockTimer(true, false); |
| 307 scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents)); |
| 308 SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer)); |
| 309 |
| 310 NavigateWithDisposition(url1, CURRENT_TAB); |
| 311 input_tracker_timer->Fire(); |
| 312 |
| 313 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 314 EXPECT_TRUE(IsTracking(helper.get())); |
| 315 |
| 316 // Hiding the tab should stop input tracking. |
| 317 web_contents->WasHidden(); |
| 318 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 319 EXPECT_FALSE(IsTracking(helper.get())); |
| 320 |
| 321 // Showing the tab should start tracking again after another delay. |
| 322 web_contents->WasShown(); |
| 323 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 324 EXPECT_FALSE(IsTracking(helper.get())); |
| 325 |
| 326 input_tracker_timer->Fire(); |
| 327 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 328 EXPECT_TRUE(IsTracking(helper.get())); |
| 329 } |
| 330 |
| 331 // Ensure tracking behavior is correct for multiple navigations in a single tab. |
| 332 TEST_F(SiteEngagementHelperTest, SingleTabNavigation) { |
| 333 AddTab(browser(), GURL("about:blank")); |
| 334 GURL url1("https://www.google.com/"); |
| 335 GURL url2("https://www.example.com/"); |
| 336 content::WebContents* web_contents = |
| 337 browser()->tab_strip_model()->GetActiveWebContents(); |
| 338 |
| 339 base::MockTimer* input_tracker_timer = new base::MockTimer(true, false); |
| 340 scoped_ptr<SiteEngagementHelper> helper(CreateHelper(web_contents)); |
| 341 SetInputTrackerPauseTimer(helper.get(), make_scoped_ptr(input_tracker_timer)); |
| 342 |
| 343 // Navigation should start the initial delay timer. |
| 344 NavigateWithDisposition(url1, CURRENT_TAB); |
| 345 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 346 EXPECT_FALSE(IsTracking(helper.get())); |
| 347 |
| 348 // Navigating before the timer fires should simply reset the timer. |
| 349 NavigateWithDisposition(url2, CURRENT_TAB); |
| 350 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 351 EXPECT_FALSE(IsTracking(helper.get())); |
| 352 |
| 353 // When the timer fires, callbacks are added. |
| 354 input_tracker_timer->Fire(); |
| 355 EXPECT_FALSE(input_tracker_timer->IsRunning()); |
| 356 EXPECT_TRUE(IsTracking(helper.get())); |
| 357 |
| 358 // Navigation should start the initial delay timer again. |
| 359 NavigateWithDisposition(url1, CURRENT_TAB); |
| 360 EXPECT_TRUE(input_tracker_timer->IsRunning()); |
| 361 EXPECT_FALSE(IsTracking(helper.get())); |
| 362 } |
OLD | NEW |