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

Side by Side Diff: chrome/browser/engagement/site_engagement_service_browsertest.cc

Issue 1338603002: Implement a site engagement score based on time-on-site. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding a TestSiteEngagementHelper Created 5 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
OLDNEW
(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/observer_list.h"
7 #include "base/run_loop.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/task_runner.h"
10 #include "base/test/simple_test_clock.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/timer/mock_timer.h"
13 #include "base/values.h"
14 #include "chrome/browser/engagement/site_engagement_helper.h"
15 #include "chrome/browser/engagement/site_engagement_service.h"
16 #include "chrome/browser/engagement/site_engagement_service_factory.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/test/base/browser_with_test_window_test.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "content/public/test/test_navigation_observer.h"
25 #include "net/test/embedded_test_server/embedded_test_server.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/events/keycodes/keyboard_codes.h"
28
29 class TestSiteEngagementHelper : public SiteEngagementHelper {
30 public:
31 class Observer {
benwells 2015/09/29 01:48:39 Why do you need all this observer stuff still? The
dominickn 2015/09/29 03:19:47 Done.
32 public:
33 Observer(TestSiteEngagementHelper* helper, base::Closure quit_closure)
34 : helper_(helper), quit_closure_(quit_closure) { }
35 ~Observer() {
36 helper_->RemoveObserver(this);
37 }
38
39 void OnInputRecorded(TestSiteEngagementHelper* helper) {
40 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
41 }
42
43 private:
44 TestSiteEngagementHelper* helper_;
45 base::Closure quit_closure_;
46 };
47
48 explicit TestSiteEngagementHelper(content::WebContents* web_contents)
49 : SiteEngagementHelper(web_contents), enable_callbacks_(false) { }
50
51 ~TestSiteEngagementHelper() override { }
52
53 void AddObserver(Observer* observer) {
54 observer_list_.AddObserver(observer);
55 }
56
57 void RemoveObserver(Observer* observer) {
58 observer_list_.RemoveObserver(observer);
59 }
60
61 void EnableCallbackRegistration() {
62 enable_callbacks_ = true;
63 }
64
65 void DisableCallbackRegistration() {
66 enable_callbacks_ = false;
67 }
68
69 void RecordUserInput() override {
70 SiteEngagementHelper::RecordUserInput();
71 FOR_EACH_OBSERVER(Observer, observer_list_, OnInputRecorded(this));
72 }
73
74 private:
75 friend class SiteEngagementServiceBrowserTest;
76 base::ObserverList<Observer> observer_list_;
77 bool enable_callbacks_;
78
79 };
80
81 class SiteEngagementServiceBrowserTest : public InProcessBrowserTest {
82 public:
83 void SetUpOnMainThread() override {
84 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
85 InProcessBrowserTest::SetUpOnMainThread();
86 }
87
88 // Create a SiteEngagementHelper. Called here as friend class methods cannot
89 // be called in tests.
90 scoped_ptr<TestSiteEngagementHelper> CreateHelper(
91 content::WebContents* web_contents,
92 bool enable_callbacks) {
93 scoped_ptr<TestSiteEngagementHelper> helper(
94 new TestSiteEngagementHelper(web_contents));
95 DCHECK(helper.get());
96
97 // Selectively enable or disable the input listening callbacks to avoid
98 // interference in tests.
99 if (enable_callbacks)
100 helper->EnableCallbackRegistration();
101 else
102 helper->DisableCallbackRegistration();
103
104 return helper.Pass();
105 }
106
107 // Simulate a key press event and handle it.
108 void HandleKeyPress(TestSiteEngagementHelper* helper, ui::KeyboardCode key) {
109 content::NativeWebKeyboardEvent event;
110 event.windowsKeyCode = key;
111 event.type = blink::WebKeyboardEvent::RawKeyDown;
112 helper->input_tracker_.HandleKeyPressEvent(event);
113 }
114
115 // Simulate a mouse event and handle it.
116 void HandleMouseEvent(TestSiteEngagementHelper* helper,
117 blink::WebMouseEvent::Button button,
118 blink::WebInputEvent::Type type) {
119 blink::WebMouseEvent event;
120 event.button = button;
121 event.type = type;
122 helper->input_tracker_.HandleMouseEvent(event);
123 }
124
125 // Set a timer object for test purposes.
126 void SetHelperTimer(TestSiteEngagementHelper* helper,
127 scoped_ptr<base::Timer> timer) {
128 helper->input_tracker_.SetTimerForTesting(timer.Pass());
129 }
130
131 bool CallbacksAdded(TestSiteEngagementHelper* helper) {
132 return helper->input_tracker_.callbacks_added();
133 }
134 };
135
136 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
137 KeyPressEngagementAccumulation) {
138 GURL url1("https://www.google.com/");
139 GURL url2("http://www.google.com/");
140 content::WebContents* web_contents =
141 browser()->tab_strip_model()->GetActiveWebContents();
142
143 scoped_ptr<TestSiteEngagementHelper> helper(
144 CreateHelper(web_contents, false));
145 SiteEngagementService* service =
146 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
147 DCHECK(service);
148
149 // Check that navigation triggers engagement.
150 ui_test_utils::NavigateToURL(browser(), url1);
151 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
152 EXPECT_EQ(0, service->GetScore(url2));
153
154 // Simulate a key press trigger and ensure it is treated correctly.
155 HandleKeyPress(helper.get(), ui::VKEY_DOWN);
156
157 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
158 EXPECT_EQ(0, service->GetScore(url2));
159
160 // Simulate three key presses, and ensure they are treated correctly.
161 HandleKeyPress(helper.get(), ui::VKEY_UP);
162 HandleKeyPress(helper.get(), ui::VKEY_RETURN);
163 HandleKeyPress(helper.get(), ui::VKEY_J);
164
165 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
166 EXPECT_EQ(0, service->GetScore(url2));
167
168 // Simulate key presses for a different link.
169 ui_test_utils::NavigateToURL(browser(), url2);
170
171 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
172 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
173 EXPECT_DOUBLE_EQ(1.2, service->GetTotalEngagementPoints());
174
175 HandleKeyPress(helper.get(), ui::VKEY_K);
176 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
177 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2));
178 EXPECT_DOUBLE_EQ(1.25, service->GetTotalEngagementPoints());
179 }
180
181 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
182 MouseEventEngagementAccumulation) {
183 GURL url1("https://www.google.com/");
184 GURL url2("http://www.google.com/");
185 content::WebContents* web_contents =
186 browser()->tab_strip_model()->GetActiveWebContents();
187
188 scoped_ptr<TestSiteEngagementHelper> helper(
189 CreateHelper(web_contents, false));
190 SiteEngagementService* service =
191 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
192 DCHECK(service);
193
194 ui_test_utils::NavigateToURL(browser(), url1);
195 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
196 EXPECT_EQ(0, service->GetScore(url2));
197
198 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonLeft,
199 blink::WebInputEvent::MouseDown);
200
201 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
202 EXPECT_EQ(0, service->GetScore(url2));
203
204 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonRight,
205 blink::WebInputEvent::MouseWheel);
206 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonMiddle,
207 blink::WebInputEvent::MouseDown);
208 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonLeft,
209 blink::WebInputEvent::MouseDown);
210
211 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
212 EXPECT_EQ(0, service->GetScore(url2));
213
214 ui_test_utils::NavigateToURL(browser(), url2);
215
216 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
217 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
218 EXPECT_DOUBLE_EQ(1.2, service->GetTotalEngagementPoints());
219
220 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonLeft,
221 blink::WebInputEvent::MouseDown);
222 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
223 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2));
224 EXPECT_DOUBLE_EQ(1.25, service->GetTotalEngagementPoints());
225 }
226
227 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
228 MixedInputEngagementAccumulation) {
229 GURL url1("https://www.google.com/");
230 GURL url2("http://www.google.com/");
231 content::WebContents* web_contents =
232 browser()->tab_strip_model()->GetActiveWebContents();
233
234 scoped_ptr<TestSiteEngagementHelper> helper(
235 CreateHelper(web_contents, false));
236 SiteEngagementService* service =
237 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
238 DCHECK(service);
239
240 ui_test_utils::NavigateToURL(browser(), url1);
241 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
242 EXPECT_EQ(0, service->GetScore(url2));
243
244 HandleKeyPress(helper.get(), ui::VKEY_UP);
245 HandleKeyPress(helper.get(), ui::VKEY_RETURN);
246 HandleKeyPress(helper.get(), ui::VKEY_J);
247
248 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonLeft,
249 blink::WebInputEvent::MouseDown);
250
251 EXPECT_DOUBLE_EQ(0.7, service->GetScore(url1));
252 EXPECT_EQ(0, service->GetScore(url2));
253
254 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonRight,
255 blink::WebInputEvent::MouseDown);
256 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonMiddle,
257 blink::WebInputEvent::MouseDown);
258 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonNone,
259 blink::WebInputEvent::MouseWheel);
260
261 EXPECT_DOUBLE_EQ(0.85, service->GetScore(url1));
262 EXPECT_EQ(0, service->GetScore(url2));
263
264 ui_test_utils::NavigateToURL(browser(), url2);
265
266 EXPECT_DOUBLE_EQ(0.85, service->GetScore(url1));
267 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
268 EXPECT_DOUBLE_EQ(1.35, service->GetTotalEngagementPoints());
269
270 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonNone,
271 blink::WebInputEvent::MouseWheel);
272 HandleKeyPress(helper.get(), ui::VKEY_DOWN);
273
274 EXPECT_DOUBLE_EQ(0.85, service->GetScore(url1));
275 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url2));
276 EXPECT_DOUBLE_EQ(1.45, service->GetTotalEngagementPoints());
277 }
278
279 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
280 CheckTimer) {
281 GURL url1("https://www.google.com/");
282 GURL url2("http://www.google.com/");
283 content::WebContents* web_contents =
284 browser()->tab_strip_model()->GetActiveWebContents();
285
286 scoped_ptr<base::MockTimer> mock_timer(new base::MockTimer(true, false));
287 base::MockTimer* timer = mock_timer.get();
288 scoped_ptr<TestSiteEngagementHelper> helper(
289 CreateHelper(web_contents, false));
290 SetHelperTimer(helper.get(), mock_timer.Pass());
291
292 SiteEngagementService* service =
293 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
294 DCHECK(service);
295
296 ui_test_utils::NavigateToURL(browser(), url1);
297 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
298 EXPECT_EQ(0, service->GetScore(url2));
299
300 // Timer should not be running after navigation. It should start after input.
301 EXPECT_FALSE(timer->IsRunning());
302 HandleKeyPress(helper.get(), ui::VKEY_RETURN);
303 EXPECT_TRUE(timer->IsRunning());
304
305 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
306 EXPECT_EQ(0, service->GetScore(url2));
307 timer->Fire();
308
309 EXPECT_FALSE(timer->IsRunning());
310 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonNone,
311 blink::WebInputEvent::MouseWheel);
312 EXPECT_TRUE(timer->IsRunning());
313
314 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1));
315 EXPECT_EQ(0, service->GetScore(url2));
316 timer->Fire();
317
318 EXPECT_FALSE(timer->IsRunning());
319 ui_test_utils::NavigateToURL(browser(), url2);
320 EXPECT_FALSE(timer->IsRunning());
321
322 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1));
323 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url2));
324
325 HandleMouseEvent(helper.get(), blink::WebMouseEvent::ButtonRight,
326 blink::WebInputEvent::MouseDown);
327 EXPECT_TRUE(timer->IsRunning());
328
329 EXPECT_DOUBLE_EQ(0.6, service->GetScore(url1));
330 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url2));
331 EXPECT_DOUBLE_EQ(1.15, service->GetTotalEngagementPoints());
332 }
333
334 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
335 SimulateInput) {
336 GURL url1("https://www.google.com/");
337 GURL url2("http://www.google.com/");
338 content::WebContents* web_contents =
339 browser()->tab_strip_model()->GetActiveWebContents();
340
341 scoped_ptr<base::MockTimer> mock_timer(new base::MockTimer(true, false));
342 base::MockTimer* timer = mock_timer.get();
343 scoped_ptr<TestSiteEngagementHelper> helper(CreateHelper(web_contents, true));
344 SetHelperTimer(helper.get(), mock_timer.Pass());
345
346 SiteEngagementService* service =
347 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
348 DCHECK(service);
349 EXPECT_FALSE(timer->IsRunning());
350
351 // Navigate and click. Ensure that the timer is running as expected.
352 {
353 base::RunLoop run_loop;
354 TestSiteEngagementHelper::Observer observer(helper.get(),
355 run_loop.QuitClosure());
356 helper->AddObserver(&observer);
357
358 ui_test_utils::NavigateToURL(browser(), url1);
359 EXPECT_DOUBLE_EQ(0.5, service->GetScore(url1));
360 EXPECT_EQ(0, service->GetScore(url2));
361 EXPECT_FALSE(timer->IsRunning());
362 EXPECT_TRUE(CallbacksAdded(helper.get()));
363
364 // Click and wait until the observer exits.
365 content::SimulateMouseClick(web_contents, 0,
366 blink::WebMouseEvent::ButtonLeft);
367 run_loop.Run();
368
369 EXPECT_DOUBLE_EQ(0.55, service->GetScore(url1));
370 EXPECT_EQ(0, service->GetScore(url2));
371 EXPECT_TRUE(timer->IsRunning());
372 EXPECT_FALSE(CallbacksAdded(helper.get()));
373 timer->Fire();
374 }
375
376 // Navigate and click.
377 {
378 base::RunLoop run_loop;
379 TestSiteEngagementHelper::Observer observer(helper.get(),
380 run_loop.QuitClosure());
381 helper->AddObserver(&observer);
382
383 EXPECT_FALSE(timer->IsRunning());
384 EXPECT_TRUE(CallbacksAdded(helper.get()));
385 ui_test_utils::NavigateToURL(browser(), url1);
386 EXPECT_DOUBLE_EQ(1.05, service->GetScore(url1));
387 EXPECT_EQ(0, service->GetScore(url2));
388 EXPECT_FALSE(timer->IsRunning());
389 EXPECT_TRUE(CallbacksAdded(helper.get()));
390
391 content::SimulateMouseClick(web_contents, 0,
392 blink::WebMouseEvent::ButtonLeft);
393 run_loop.Run();
394
395 EXPECT_DOUBLE_EQ(1.1, service->GetScore(url1));
396 EXPECT_EQ(0, service->GetScore(url2));
397 EXPECT_TRUE(timer->IsRunning());
398 EXPECT_FALSE(CallbacksAdded(helper.get()));
399 timer->Fire();
400 }
401
402 // Click only.
403 {
404 base::RunLoop run_loop;
405 TestSiteEngagementHelper::Observer observer(helper.get(),
406 run_loop.QuitClosure());
407 helper->AddObserver(&observer);
408
409 EXPECT_FALSE(timer->IsRunning());
410 EXPECT_TRUE(CallbacksAdded(helper.get()));
411 content::SimulateMouseClick(web_contents, 0,
412 blink::WebMouseEvent::ButtonMiddle);
413 run_loop.Run();
414
415 EXPECT_DOUBLE_EQ(1.15, service->GetScore(url1));
416 EXPECT_EQ(0, service->GetScore(url2));
417 EXPECT_TRUE(timer->IsRunning());
418 EXPECT_FALSE(CallbacksAdded(helper.get()));
419 timer->Fire();
420 }
421
422 // Navigate and click.
423 {
424 base::RunLoop run_loop;
425 TestSiteEngagementHelper::Observer observer(helper.get(),
426 run_loop.QuitClosure());
427 helper->AddObserver(&observer);
428
429 EXPECT_FALSE(timer->IsRunning());
430 EXPECT_TRUE(CallbacksAdded(helper.get()));
431 ui_test_utils::NavigateToURL(browser(), url1);
432 EXPECT_DOUBLE_EQ(1.65, service->GetScore(url1));
433 EXPECT_EQ(0, service->GetScore(url2));
434 content::SimulateMouseClick(web_contents, 0,
435 blink::WebMouseEvent::ButtonRight);
436 run_loop.Run();
437
438 EXPECT_DOUBLE_EQ(1.7, service->GetScore(url1));
439 EXPECT_EQ(0, service->GetScore(url2));
440 EXPECT_TRUE(timer->IsRunning());
441 EXPECT_FALSE(CallbacksAdded(helper.get()));
442
443 // Simulate another event while the timer is running to make sure that this
444 // input is ignored.
445 content::SimulateMouseClick(web_contents, 0,
446 blink::WebMouseEvent::ButtonLeft);
447
448 EXPECT_DOUBLE_EQ(1.7, service->GetScore(url1));
449 EXPECT_EQ(0, service->GetScore(url2));
450 EXPECT_TRUE(timer->IsRunning());
451 EXPECT_FALSE(CallbacksAdded(helper.get()));
452 timer->Fire();
453 }
454 }
455
456 IN_PROC_BROWSER_TEST_F(SiteEngagementServiceBrowserTest,
457 ShowAndHide) {
458 GURL url1("https://www.google.com/");
459 GURL url2("http://www.google.com/");
460 content::WebContents* web_contents =
461 browser()->tab_strip_model()->GetActiveWebContents();
462
463 scoped_ptr<base::MockTimer> mock_timer(new base::MockTimer(true, false));
464 base::MockTimer* timer = mock_timer.get();
465 scoped_ptr<TestSiteEngagementHelper> helper(CreateHelper(web_contents, true));
466 SetHelperTimer(helper.get(), mock_timer.Pass());
467
468 SiteEngagementService* service =
469 SiteEngagementServiceFactory::GetForProfile(browser()->profile());
470 DCHECK(service);
471 EXPECT_FALSE(timer->IsRunning());
472
473 // Navigate and hide.
474 {
475 base::RunLoop run_loop;
476 TestSiteEngagementHelper::Observer observer(helper.get(),
477 run_loop.QuitClosure());
478 helper->AddObserver(&observer);
479
480 ui_test_utils::NavigateToURL(browser(), url1);
481 EXPECT_TRUE(CallbacksAdded(helper.get()));
482 content::SimulateMouseClick(web_contents, 0,
483 blink::WebMouseEvent::ButtonRight);
484 run_loop.Run();
485
486 // Timer runs after input is recorded.
487 EXPECT_TRUE(timer->IsRunning());
488 EXPECT_FALSE(CallbacksAdded(helper.get()));
489
490 ui_test_utils::NavigateToURLWithDisposition(
491 browser(), url2, NEW_FOREGROUND_TAB,
492 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
493
494 // Hiding the original tab should stop the timer.
495 EXPECT_FALSE(timer->IsRunning());
496 EXPECT_FALSE(CallbacksAdded(helper.get()));
497 EXPECT_EQ(2, browser()->tab_strip_model()->count());
498
499 // Timer should still be stopped on re-focus, but the input callbacks
500 // should now be added.
501 browser()->tab_strip_model()->ActivateTabAt(0, true);
502 EXPECT_FALSE(timer->IsRunning());
503 EXPECT_TRUE(CallbacksAdded(helper.get()));
504 }
505
506 // Click. Timer should be started.
507 {
508 base::RunLoop run_loop;
509 TestSiteEngagementHelper::Observer observer(helper.get(),
510 run_loop.QuitClosure());
511 helper->AddObserver(&observer);
512
513 content::SimulateMouseClick(web_contents, 0,
514 blink::WebMouseEvent::ButtonRight);
515 run_loop.Run();
516
517 // Timer runs after input is recorded, and after it fires the callbacks are
518 // added.
519 EXPECT_FALSE(CallbacksAdded(helper.get()));
520 EXPECT_TRUE(timer->IsRunning());
521 timer->Fire();
522 EXPECT_FALSE(timer->IsRunning());
523 EXPECT_TRUE(CallbacksAdded(helper.get()));
524 }
525 }
OLDNEW
« no previous file with comments | « chrome/browser/engagement/site_engagement_service.cc ('k') | chrome/browser/engagement/site_engagement_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698