1 // Copyright 2013 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/cancelable_callback.h" 6 #include "base/command_line.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/run_loop.h" 9 #include "base/strings/stringprintf.h" 10 #include "base/synchronization/waitable_event.h" 11 #include "base/test/simple_test_clock.h" 12 #include "base/test/test_timeouts.h" 13 #include "chrome/browser/extensions/activity_log/activity_log.h" 14 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" 15 #include "chrome/browser/extensions/extension_service.h" 16 #include "chrome/browser/extensions/test_extension_system.h" 17 #include "chrome/common/chrome_constants.h" 18 #include "chrome/common/chrome_switches.h" 19 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 20 #include "chrome/test/base/testing_profile.h" 21 #include "content/public/test/test_browser_thread_bundle.h" 22 #include "extensions/common/extension_builder.h" 23 #include "sql/statement.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 #if defined(OS_CHROMEOS) 27 #include "chrome/browser/chromeos/login/users/user_manager.h" 28 #include "chrome/browser/chromeos/settings/cros_settings.h" 29 #include "chrome/browser/chromeos/settings/device_settings_service.h" 30 #endif 31 32 using content::BrowserThread; 33 34 namespace extensions { 35 36 class FullStreamUIPolicyTest : public testing::Test { 37 public: 38 FullStreamUIPolicyTest() 39 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 40 saved_cmdline_(CommandLine::NO_PROGRAM) { 41 #if defined OS_CHROMEOS 42 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); 43 #endif 44 CommandLine command_line(CommandLine::NO_PROGRAM); 45 saved_cmdline_ = *CommandLine::ForCurrentProcess(); 46 profile_.reset(new TestingProfile()); 47 CommandLine::ForCurrentProcess()->AppendSwitch( 48 switches::kEnableExtensionActivityLogging); 49 CommandLine::ForCurrentProcess()->AppendSwitch( 50 switches::kEnableExtensionActivityLogTesting); 51 extension_service_ = static_cast<TestExtensionSystem*>( 52 ExtensionSystem::Get(profile_.get()))->CreateExtensionService 53 (&command_line, base::FilePath(), false); 54 } 55 56 virtual ~FullStreamUIPolicyTest() { 57 #if defined OS_CHROMEOS 58 test_user_manager_.reset(); 59 #endif 60 base::RunLoop().RunUntilIdle(); 61 profile_.reset(NULL); 62 base::RunLoop().RunUntilIdle(); 63 // Restore the original command line and undo the affects of SetUp(). 64 *CommandLine::ForCurrentProcess() = saved_cmdline_; 65 } 66 67 // A wrapper function for CheckReadFilteredData, so that we don't need to 68 // enter empty string values for parameters we don't care about. 69 void CheckReadData( 70 ActivityLogDatabasePolicy* policy, 71 const std::string& extension_id, 72 int day, 73 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { 74 CheckReadFilteredData( 75 policy, extension_id, Action::ACTION_ANY, "", "", "", day, checker); 76 } 77 78 // A helper function to call ReadFilteredData on a policy object and wait for 79 // the results to be processed. 80 void CheckReadFilteredData( 81 ActivityLogDatabasePolicy* policy, 82 const std::string& extension_id, 83 const Action::ActionType type, 84 const std::string& api_name, 85 const std::string& page_url, 86 const std::string& arg_url, 87 const int days_ago, 88 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { 89 // Submit a request to the policy to read back some data, and call the 90 // checker function when results are available. This will happen on the 91 // database thread. 92 policy->ReadFilteredData( 93 extension_id, 94 type, 95 api_name, 96 page_url, 97 arg_url, 98 days_ago, 99 base::Bind(&FullStreamUIPolicyTest::CheckWrapper, 100 checker, 101 base::MessageLoop::current()->QuitClosure())); 102 103 // Set up a timeout for receiving results; if we haven't received anything 104 // when the timeout triggers then assume that the test is broken. 105 base::CancelableClosure timeout( 106 base::Bind(&FullStreamUIPolicyTest::TimeoutCallback)); 107 base::MessageLoop::current()->PostDelayedTask( 108 FROM_HERE, timeout.callback(), TestTimeouts::action_timeout()); 109 110 // Wait for results; either the checker or the timeout callbacks should 111 // cause the main loop to exit. 112 base::MessageLoop::current()->Run(); 113 114 timeout.Cancel(); 115 } 116 117 static void CheckWrapper( 118 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker, 119 const base::Closure& done, 120 scoped_ptr<Action::ActionVector> results) { 121 checker.Run(results.Pass()); 122 done.Run(); 123 } 124 125 static void TimeoutCallback() { 126 base::MessageLoop::current()->QuitWhenIdle(); 127 FAIL() << "Policy test timed out waiting for results"; 128 } 129 130 static void RetrieveActions_LogAndFetchActions( 131 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { 132 ASSERT_EQ(2, static_cast<int>(i->size())); 133 } 134 135 static void RetrieveActions_FetchFilteredActions0( 136 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { 137 ASSERT_EQ(0, static_cast<int>(i->size())); 138 } 139 140 static void RetrieveActions_FetchFilteredActions1( 141 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { 142 ASSERT_EQ(1, static_cast<int>(i->size())); 143 } 144 145 static void RetrieveActions_FetchFilteredActions2( 146 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { 147 ASSERT_EQ(2, static_cast<int>(i->size())); 148 } 149 150 static void RetrieveActions_FetchFilteredActions300( 151 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { 152 ASSERT_EQ(300, static_cast<int>(i->size())); 153 } 154 155 static void Arguments_Present(scoped_ptr<Action::ActionVector> i) { 156 scoped_refptr<Action> last = i->front(); 157 CheckAction(*last, "odlameecjipmbmbejkplpemijjgpljce", 158 Action::ACTION_API_CALL, "extension.connect", 159 "[\"hello\",\"world\"]", "", "", ""); 160 } 161 162 static void Arguments_GetTodaysActions( 163 scoped_ptr<Action::ActionVector> actions) { 164 ASSERT_EQ(2, static_cast<int>(actions->size())); 165 CheckAction(*actions->at(0), "punky", Action::ACTION_DOM_ACCESS, "lets", 166 "[\"vamoose\"]", "http://www.google.com/", "Page Title", 167 "http://www.arg-url.com/"); 168 CheckAction(*actions->at(1), "punky", Action::ACTION_API_CALL, "brewster", 169 "[\"woof\"]", "", "Page Title", "http://www.arg-url.com/"); 170 } 171 172 static void Arguments_GetOlderActions( 173 scoped_ptr<Action::ActionVector> actions) { 174 ASSERT_EQ(2, static_cast<int>(actions->size())); 175 CheckAction(*actions->at(0), "punky", Action::ACTION_DOM_ACCESS, "lets", 176 "[\"vamoose\"]", "http://www.google.com/", "", ""); 177 CheckAction(*actions->at(1), "punky", Action::ACTION_API_CALL, "brewster", 178 "[\"woof\"]", "", "", ""); 179 } 180 181 static void AllURLsRemoved(scoped_ptr<Action::ActionVector> actions) { 182 ASSERT_EQ(2, static_cast<int>(actions->size())); 183 CheckAction(*actions->at(0), "punky", Action::ACTION_API_CALL, "lets", 184 "[\"vamoose\"]", "", "", ""); 185 CheckAction(*actions->at(1), "punky", Action::ACTION_DOM_ACCESS, "lets", 186 "[\"vamoose\"]", "", "", ""); 187 } 188 189 static void SomeURLsRemoved(scoped_ptr<Action::ActionVector> actions) { 190 // These will be in the vector in reverse time order. 191 ASSERT_EQ(5, static_cast<int>(actions->size())); 192 CheckAction(*actions->at(0), "punky", Action::ACTION_DOM_ACCESS, "lets", 193 "[\"vamoose\"]", "http://www.google.com/", "Google", 194 "http://www.args-url.com/"); 195 CheckAction(*actions->at(1), "punky", Action::ACTION_DOM_ACCESS, "lets", 196 "[\"vamoose\"]", "http://www.google.com/", "Google", ""); 197 CheckAction(*actions->at(2), "punky", Action::ACTION_DOM_ACCESS, "lets", 198 "[\"vamoose\"]", "", "", ""); 199 CheckAction(*actions->at(3), "punky", Action::ACTION_DOM_ACCESS, "lets", 200 "[\"vamoose\"]", "", "", "http://www.google.com/"); 201 CheckAction(*actions->at(4), "punky", Action::ACTION_DOM_ACCESS, "lets", 202 "[\"vamoose\"]", "", "", ""); 203 } 204 205 static void CheckAction(const Action& action, 206 const std::string& expected_id, 207 const Action::ActionType& expected_type, 208 const std::string& expected_api_name, 209 const std::string& expected_args_str, 210 const std::string& expected_page_url, 211 const std::string& expected_page_title, 212 const std::string& expected_arg_url) { 213 ASSERT_EQ(expected_id, action.extension_id()); 214 ASSERT_EQ(expected_type, action.action_type()); 215 ASSERT_EQ(expected_api_name, action.api_name()); 216 ASSERT_EQ(expected_args_str, 217 ActivityLogPolicy::Util::Serialize(action.args())); 218 ASSERT_EQ(expected_page_url, action.SerializePageUrl()); 219 ASSERT_EQ(expected_page_title, action.page_title()); 220 ASSERT_EQ(expected_arg_url, action.SerializeArgUrl()); 221 ASSERT_NE(-1, action.action_id()); 222 } 223 224 // A helper function initializes the policy with a number of actions, calls 225 // RemoveActions on a policy object and then checks the result of the 226 // deletion. 227 void CheckRemoveActions( 228 ActivityLogDatabasePolicy* policy, 229 const std::vector<int64>& action_ids, 230 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { 231 232 // Use a mock clock to ensure that events are not recorded on the wrong day 233 // when the test is run close to local midnight. 234 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 235 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 236 base::TimeDelta::FromHours(12)); 237 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 238 239 // Record some actions 240 scoped_refptr<Action> action = 241 new Action("punky1", 242 mock_clock->Now() - base::TimeDelta::FromMinutes(40), 243 Action::ACTION_DOM_ACCESS, 244 "lets1"); 245 action->mutable_args()->AppendString("vamoose1"); 246 action->set_page_url(GURL("http://www.google1.com")); 247 action->set_page_title("Google1"); 248 action->set_arg_url(GURL("http://www.args-url1.com")); 249 policy->ProcessAction(action); 250 // Record the same action twice, so there are multiple entries in the 251 // database. 252 policy->ProcessAction(action); 253 254 action = new Action("punky2", 255 mock_clock->Now() - base::TimeDelta::FromMinutes(30), 256 Action::ACTION_API_CALL, 257 "lets2"); 258 action->mutable_args()->AppendString("vamoose2"); 259 action->set_page_url(GURL("http://www.google2.com")); 260 action->set_page_title("Google2"); 261 action->set_arg_url(GURL("http://www.args-url2.com")); 262 policy->ProcessAction(action); 263 // Record the same action twice, so there are multiple entries in the 264 // database. 265 policy->ProcessAction(action); 266 267 // Submit a request to delete actions. 268 policy->RemoveActions(action_ids); 269 270 // Check the result of the deletion. The checker function gets all 271 // activities in the database. 272 CheckReadData(policy, "", -1, checker); 273 274 // Clean database. 275 policy->DeleteDatabase(); 276 } 277 278 static void AllActionsDeleted(scoped_ptr<Action::ActionVector> actions) { 279 ASSERT_EQ(0, static_cast<int>(actions->size())); 280 } 281 282 static void NoActionsDeleted(scoped_ptr<Action::ActionVector> actions) { 283 // These will be in the vector in reverse time order. 284 ASSERT_EQ(4, static_cast<int>(actions->size())); 285 CheckAction(*actions->at(0), 286 "punky2", 287 Action::ACTION_API_CALL, 288 "lets2", 289 "[\"vamoose2\"]", 290 "http://www.google2.com/", 291 "Google2", 292 "http://www.args-url2.com/"); 293 ASSERT_EQ(3, actions->at(0)->action_id()); 294 CheckAction(*actions->at(1), 295 "punky2", 296 Action::ACTION_API_CALL, 297 "lets2", 298 "[\"vamoose2\"]", 299 "http://www.google2.com/", 300 "Google2", 301 "http://www.args-url2.com/"); 302 ASSERT_EQ(4, actions->at(1)->action_id()); 303 CheckAction(*actions->at(2), 304 "punky1", 305 Action::ACTION_DOM_ACCESS, 306 "lets1", 307 "[\"vamoose1\"]", 308 "http://www.google1.com/", 309 "Google1", 310 "http://www.args-url1.com/"); 311 ASSERT_EQ(1, actions->at(2)->action_id()); 312 CheckAction(*actions->at(3), 313 "punky1", 314 Action::ACTION_DOM_ACCESS, 315 "lets1", 316 "[\"vamoose1\"]", 317 "http://www.google1.com/", 318 "Google1", 319 "http://www.args-url1.com/"); 320 ASSERT_EQ(2, actions->at(3)->action_id()); 321 } 322 323 static void Action1Deleted(scoped_ptr<Action::ActionVector> actions) { 324 // These will be in the vector in reverse time order. 325 ASSERT_EQ(2, static_cast<int>(actions->size())); 326 CheckAction(*actions->at(0), 327 "punky2", 328 Action::ACTION_API_CALL, 329 "lets2", 330 "[\"vamoose2\"]", 331 "http://www.google2.com/", 332 "Google2", 333 "http://www.args-url2.com/"); 334 ASSERT_EQ(3, actions->at(0)->action_id()); 335 CheckAction(*actions->at(1), 336 "punky2", 337 Action::ACTION_API_CALL, 338 "lets2", 339 "[\"vamoose2\"]", 340 "http://www.google2.com/", 341 "Google2", 342 "http://www.args-url2.com/"); 343 ASSERT_EQ(4, actions->at(1)->action_id()); 344 } 345 346 static void Action2Deleted(scoped_ptr<Action::ActionVector> actions) { 347 // These will be in the vector in reverse time order. 348 ASSERT_EQ(2, static_cast<int>(actions->size())); 349 CheckAction(*actions->at(0), 350 "punky1", 351 Action::ACTION_DOM_ACCESS, 352 "lets1", 353 "[\"vamoose1\"]", 354 "http://www.google1.com/", 355 "Google1", 356 "http://www.args-url1.com/"); 357 ASSERT_EQ(1, actions->at(0)->action_id()); 358 CheckAction(*actions->at(1), 359 "punky1", 360 Action::ACTION_DOM_ACCESS, 361 "lets1", 362 "[\"vamoose1\"]", 363 "http://www.google1.com/", 364 "Google1", 365 "http://www.args-url1.com/"); 366 ASSERT_EQ(2, actions->at(1)->action_id()); 367 } 368 369 protected: 370 ExtensionService* extension_service_; 371 scoped_ptr<TestingProfile> profile_; 372 content::TestBrowserThreadBundle thread_bundle_; 373 // Used to preserve a copy of the original command line. 374 // The test framework will do this itself as well. However, by then, 375 // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in 376 // TearDown(). 377 CommandLine saved_cmdline_; 378 379 #if defined OS_CHROMEOS 380 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 381 chromeos::ScopedTestCrosSettings test_cros_settings_; 382 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; 383 #endif 384 }; 385 386 TEST_F(FullStreamUIPolicyTest, Construct) { 387 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 388 policy->Init(); 389 scoped_refptr<const Extension> extension = 390 ExtensionBuilder() 391 .SetManifest(DictionaryBuilder() 392 .Set("name", "Test extension") 393 .Set("version", "1.0.0") 394 .Set("manifest_version", 2)) 395 .Build(); 396 extension_service_->AddExtension(extension.get()); 397 scoped_ptr<base::ListValue> args(new base::ListValue()); 398 scoped_refptr<Action> action = new Action(extension->id(), 399 base::Time::Now(), 400 Action::ACTION_API_CALL, 401 "tabs.testMethod"); 402 action->set_args(args.Pass()); 403 policy->ProcessAction(action); 404 policy->Close(); 405 } 406 407 TEST_F(FullStreamUIPolicyTest, LogAndFetchActions) { 408 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 409 policy->Init(); 410 scoped_refptr<const Extension> extension = 411 ExtensionBuilder() 412 .SetManifest(DictionaryBuilder() 413 .Set("name", "Test extension") 414 .Set("version", "1.0.0") 415 .Set("manifest_version", 2)) 416 .Build(); 417 extension_service_->AddExtension(extension.get()); 418 GURL gurl("http://www.google.com"); 419 420 // Write some API calls 421 scoped_refptr<Action> action_api = new Action(extension->id(), 422 base::Time::Now(), 423 Action::ACTION_API_CALL, 424 "tabs.testMethod"); 425 action_api->set_args(make_scoped_ptr(new base::ListValue())); 426 policy->ProcessAction(action_api); 427 428 scoped_refptr<Action> action_dom = new Action(extension->id(), 429 base::Time::Now(), 430 Action::ACTION_DOM_ACCESS, 431 "document.write"); 432 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 433 action_dom->set_page_url(gurl); 434 policy->ProcessAction(action_dom); 435 436 CheckReadData( 437 policy, 438 extension->id(), 439 0, 440 base::Bind(&FullStreamUIPolicyTest::RetrieveActions_LogAndFetchActions)); 441 442 policy->Close(); 443 } 444 445 TEST_F(FullStreamUIPolicyTest, LogAndFetchFilteredActions) { 446 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 447 policy->Init(); 448 scoped_refptr<const Extension> extension = 449 ExtensionBuilder() 450 .SetManifest(DictionaryBuilder() 451 .Set("name", "Test extension") 452 .Set("version", "1.0.0") 453 .Set("manifest_version", 2)) 454 .Build(); 455 extension_service_->AddExtension(extension.get()); 456 GURL gurl("http://www.google.com"); 457 458 // Write some API calls 459 scoped_refptr<Action> action_api = new Action(extension->id(), 460 base::Time::Now(), 461 Action::ACTION_API_CALL, 462 "tabs.testMethod"); 463 action_api->set_args(make_scoped_ptr(new base::ListValue())); 464 policy->ProcessAction(action_api); 465 466 scoped_refptr<Action> action_dom = new Action(extension->id(), 467 base::Time::Now(), 468 Action::ACTION_DOM_ACCESS, 469 "document.write"); 470 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 471 action_dom->set_page_url(gurl); 472 policy->ProcessAction(action_dom); 473 474 CheckReadFilteredData( 475 policy, 476 extension->id(), 477 Action::ACTION_API_CALL, 478 "tabs.testMethod", 479 "", 480 "", 481 -1, 482 base::Bind( 483 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 484 485 CheckReadFilteredData( 486 policy, 487 "", 488 Action::ACTION_DOM_ACCESS, 489 "", 490 "", 491 "", 492 -1, 493 base::Bind( 494 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 495 496 CheckReadFilteredData( 497 policy, 498 "", 499 Action::ACTION_DOM_ACCESS, 500 "", 501 "http://www.google.com/", 502 "", 503 -1, 504 base::Bind( 505 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 506 507 CheckReadFilteredData( 508 policy, 509 "", 510 Action::ACTION_DOM_ACCESS, 511 "", 512 "http://www.google.com", 513 "", 514 -1, 515 base::Bind( 516 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 517 518 CheckReadFilteredData( 519 policy, 520 "", 521 Action::ACTION_DOM_ACCESS, 522 "", 523 "http://www.goo", 524 "", 525 -1, 526 base::Bind( 527 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 528 529 CheckReadFilteredData( 530 policy, 531 extension->id(), 532 Action::ACTION_ANY, 533 "", 534 "", 535 "", 536 -1, 537 base::Bind( 538 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions2)); 539 540 policy->Close(); 541 } 542 543 TEST_F(FullStreamUIPolicyTest, LogWithArguments) { 544 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 545 policy->Init(); 546 scoped_refptr<const Extension> extension = 547 ExtensionBuilder() 548 .SetManifest(DictionaryBuilder() 549 .Set("name", "Test extension") 550 .Set("version", "1.0.0") 551 .Set("manifest_version", 2)) 552 .Build(); 553 extension_service_->AddExtension(extension.get()); 554 555 scoped_ptr<base::ListValue> args(new base::ListValue()); 556 args->Set(0, new base::StringValue("hello")); 557 args->Set(1, new base::StringValue("world")); 558 scoped_refptr<Action> action = new Action(extension->id(), 559 base::Time::Now(), 560 Action::ACTION_API_CALL, 561 "extension.connect"); 562 action->set_args(args.Pass()); 563 564 policy->ProcessAction(action); 565 CheckReadData(policy, 566 extension->id(), 567 0, 568 base::Bind(&FullStreamUIPolicyTest::Arguments_Present)); 569 policy->Close(); 570 } 571 572 TEST_F(FullStreamUIPolicyTest, GetTodaysActions) { 573 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 574 policy->Init(); 575 576 // Use a mock clock to ensure that events are not recorded on the wrong day 577 // when the test is run close to local midnight. Note: Ownership is passed 578 // to the policy, but we still keep a pointer locally. The policy will take 579 // care of destruction; this is safe since the policy outlives all our 580 // accesses to the mock clock. 581 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 582 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 583 base::TimeDelta::FromHours(12)); 584 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 585 586 // Record some actions 587 scoped_refptr<Action> action = 588 new Action("punky", 589 mock_clock->Now() - base::TimeDelta::FromMinutes(40), 590 Action::ACTION_API_CALL, 591 "brewster"); 592 action->mutable_args()->AppendString("woof"); 593 action->set_arg_url(GURL("http://www.arg-url.com")); 594 action->set_page_title("Page Title"); 595 policy->ProcessAction(action); 596 597 action = 598 new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 599 action->mutable_args()->AppendString("vamoose"); 600 action->set_page_url(GURL("http://www.google.com")); 601 action->set_arg_url(GURL("http://www.arg-url.com")); 602 action->set_page_title("Page Title"); 603 policy->ProcessAction(action); 604 605 action = new Action( 606 "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 607 action->mutable_args()->AppendString("vamoose"); 608 action->set_page_url(GURL("http://www.google.com")); 609 action->set_arg_url(GURL("http://www.arg-url.com")); 610 policy->ProcessAction(action); 611 612 CheckReadData( 613 policy, 614 "punky", 615 0, 616 base::Bind(&FullStreamUIPolicyTest::Arguments_GetTodaysActions)); 617 policy->Close(); 618 } 619 620 // Check that we can read back less recent actions in the db. 621 TEST_F(FullStreamUIPolicyTest, GetOlderActions) { 622 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 623 policy->Init(); 624 625 // Use a mock clock to ensure that events are not recorded on the wrong day 626 // when the test is run close to local midnight. 627 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 628 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 629 base::TimeDelta::FromHours(12)); 630 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 631 632 // Record some actions 633 scoped_refptr<Action> action = 634 new Action("punky", 635 mock_clock->Now() - base::TimeDelta::FromDays(3) - 636 base::TimeDelta::FromMinutes(40), 637 Action::ACTION_API_CALL, 638 "brewster"); 639 action->mutable_args()->AppendString("woof"); 640 policy->ProcessAction(action); 641 642 action = new Action("punky", 643 mock_clock->Now() - base::TimeDelta::FromDays(3), 644 Action::ACTION_DOM_ACCESS, 645 "lets"); 646 action->mutable_args()->AppendString("vamoose"); 647 action->set_page_url(GURL("http://www.google.com")); 648 policy->ProcessAction(action); 649 650 action = new Action("punky", 651 mock_clock->Now(), 652 Action::ACTION_DOM_ACCESS, 653 "lets"); 654 action->mutable_args()->AppendString("too new"); 655 action->set_page_url(GURL("http://www.google.com")); 656 policy->ProcessAction(action); 657 658 action = new Action("punky", 659 mock_clock->Now() - base::TimeDelta::FromDays(7), 660 Action::ACTION_DOM_ACCESS, 661 "lets"); 662 action->mutable_args()->AppendString("too old"); 663 action->set_page_url(GURL("http://www.google.com")); 664 policy->ProcessAction(action); 665 666 CheckReadData( 667 policy, 668 "punky", 669 3, 670 base::Bind(&FullStreamUIPolicyTest::Arguments_GetOlderActions)); 671 policy->Close(); 672 } 673 674 TEST_F(FullStreamUIPolicyTest, RemoveAllURLs) { 675 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 676 policy->Init(); 677 678 // Use a mock clock to ensure that events are not recorded on the wrong day 679 // when the test is run close to local midnight. 680 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 681 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 682 base::TimeDelta::FromHours(12)); 683 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 684 685 // Record some actions 686 scoped_refptr<Action> action = 687 new Action("punky", mock_clock->Now(), 688 Action::ACTION_DOM_ACCESS, "lets"); 689 action->mutable_args()->AppendString("vamoose"); 690 action->set_page_url(GURL("http://www.google.com")); 691 action->set_page_title("Google"); 692 action->set_arg_url(GURL("http://www.google.com")); 693 policy->ProcessAction(action); 694 695 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 696 action = new Action( 697 "punky", mock_clock->Now(), Action::ACTION_API_CALL, "lets"); 698 action->mutable_args()->AppendString("vamoose"); 699 action->set_page_url(GURL("http://www.google2.com")); 700 action->set_page_title("Google"); 701 // Deliberately no arg url set to make sure it still works when there is no 702 // arg url. 703 policy->ProcessAction(action); 704 705 // Clean all the URLs. 706 std::vector<GURL> no_url_restrictions; 707 policy->RemoveURLs(no_url_restrictions); 708 709 CheckReadData( 710 policy, 711 "punky", 712 0, 713 base::Bind(&FullStreamUIPolicyTest::AllURLsRemoved)); 714 policy->Close(); 715 } 716 717 TEST_F(FullStreamUIPolicyTest, RemoveSpecificURLs) { 718 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 719 policy->Init(); 720 721 // Use a mock clock to ensure that events are not recorded on the wrong day 722 // when the test is run close to local midnight. 723 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 724 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 725 base::TimeDelta::FromHours(12)); 726 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 727 728 // Record some actions 729 // This should have the page url and args url cleared. 730 scoped_refptr<Action> action = new Action("punky", mock_clock->Now(), 731 Action::ACTION_DOM_ACCESS, "lets"); 732 action->mutable_args()->AppendString("vamoose"); 733 action->set_page_url(GURL("http://www.google1.com")); 734 action->set_page_title("Google"); 735 action->set_arg_url(GURL("http://www.google1.com")); 736 policy->ProcessAction(action); 737 738 // This should have the page url cleared but not args url. 739 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 740 action = new Action( 741 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 742 action->mutable_args()->AppendString("vamoose"); 743 action->set_page_url(GURL("http://www.google1.com")); 744 action->set_page_title("Google"); 745 action->set_arg_url(GURL("http://www.google.com")); 746 policy->ProcessAction(action); 747 748 // This should have the page url cleared. The args url is deliberately not set 749 // to make sure this doesn't cause any issues. 750 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 751 action = new Action( 752 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 753 action->mutable_args()->AppendString("vamoose"); 754 action->set_page_url(GURL("http://www.google2.com")); 755 action->set_page_title("Google"); 756 policy->ProcessAction(action); 757 758 // This should have the args url cleared but not the page url or page title. 759 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 760 action = new Action( 761 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 762 action->mutable_args()->AppendString("vamoose"); 763 action->set_page_url(GURL("http://www.google.com")); 764 action->set_page_title("Google"); 765 action->set_arg_url(GURL("http://www.google1.com")); 766 policy->ProcessAction(action); 767 768 // This should have neither cleared. 769 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 770 action = new Action( 771 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 772 action->mutable_args()->AppendString("vamoose"); 773 action->set_page_url(GURL("http://www.google.com")); 774 action->set_page_title("Google"); 775 action->set_arg_url(GURL("http://www.args-url.com")); 776 policy->ProcessAction(action); 777 778 // Clean some URLs. 779 std::vector<GURL> urls; 780 urls.push_back(GURL("http://www.google1.com")); 781 urls.push_back(GURL("http://www.google2.com")); 782 urls.push_back(GURL("http://www.url_not_in_db.com")); 783 policy->RemoveURLs(urls); 784 785 CheckReadData( 786 policy, 787 "punky", 788 0, 789 base::Bind(&FullStreamUIPolicyTest::SomeURLsRemoved)); 790 policy->Close(); 791 } 792 793 TEST_F(FullStreamUIPolicyTest, RemoveExtensionData) { 794 FullStreamUIPolicy* policy = new FullStreamUIPolicy(profile_.get()); 795 policy->Init(); 796 797 // Use a mock clock to ensure that events are not recorded on the wrong day 798 // when the test is run close to local midnight. 799 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 800 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 801 base::TimeDelta::FromHours(12)); 802 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 803 804 // Record some actions 805 scoped_refptr<Action> action = new Action("deleteextensiondata", 806 mock_clock->Now(), 807 Action::ACTION_DOM_ACCESS, 808 "lets"); 809 action->mutable_args()->AppendString("vamoose"); 810 action->set_page_title("Google"); 811 action->set_arg_url(GURL("http://www.google.com")); 812 policy->ProcessAction(action); 813 policy->ProcessAction(action); 814 policy->ProcessAction(action); 815 816 scoped_refptr<Action> action2 = new Action("dontdelete", 817 mock_clock->Now(), 818 Action::ACTION_DOM_ACCESS, 819 "lets"); 820 action->mutable_args()->AppendString("vamoose"); 821 action->set_page_title("Google"); 822 action->set_arg_url(GURL("http://www.google.com")); 823 policy->ProcessAction(action2); 824 825 policy->Flush(); 826 policy->RemoveExtensionData("deleteextensiondata"); 827 828 CheckReadFilteredData( 829 policy, 830 "deleteextensiondata", 831 Action::ACTION_ANY, 832 "", 833 "", 834 "", 835 -1, 836 base::Bind( 837 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions0)); 838 839 CheckReadFilteredData( 840 policy, 841 "dontdelete", 842 Action::ACTION_ANY, 843 "", 844 "", 845 "", 846 -1, 847 base::Bind( 848 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 849 policy->Close(); 850 } 851 852 TEST_F(FullStreamUIPolicyTest, CapReturns) { 853 FullStreamUIPolicy* policy = new FullStreamUIPolicy(profile_.get()); 854 policy->Init(); 855 856 for (int i = 0; i < 305; i++) { 857 scoped_refptr<Action> action = 858 new Action("punky", 859 base::Time::Now(), 860 Action::ACTION_API_CALL, 861 base::StringPrintf("apicall_%d", i)); 862 policy->ProcessAction(action); 863 } 864 865 policy->Flush(); 866 BrowserThread::PostTaskAndReply( 867 BrowserThread::DB, 868 FROM_HERE, 869 base::Bind(&base::DoNothing), 870 base::MessageLoop::current()->QuitClosure()); 871 base::MessageLoop::current()->Run(); 872 873 CheckReadFilteredData( 874 policy, 875 "punky", 876 Action::ACTION_ANY, 877 "", 878 "", 879 "", 880 -1, 881 base::Bind( 882 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions300)); 883 policy->Close(); 884 } 885 886 TEST_F(FullStreamUIPolicyTest, DeleteDatabase) { 887 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 888 policy->Init(); 889 scoped_refptr<const Extension> extension = 890 ExtensionBuilder() 891 .SetManifest(DictionaryBuilder() 892 .Set("name", "Test extension") 893 .Set("version", "1.0.0") 894 .Set("manifest_version", 2)) 895 .Build(); 896 extension_service_->AddExtension(extension.get()); 897 GURL gurl("http://www.google.com"); 898 899 // Write some API calls. 900 scoped_refptr<Action> action_api = new Action(extension->id(), 901 base::Time::Now(), 902 Action::ACTION_API_CALL, 903 "tabs.testMethod"); 904 action_api->set_args(make_scoped_ptr(new base::ListValue())); 905 policy->ProcessAction(action_api); 906 907 scoped_refptr<Action> action_dom = new Action(extension->id(), 908 base::Time::Now(), 909 Action::ACTION_DOM_ACCESS, 910 "document.write"); 911 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 912 action_dom->set_page_url(gurl); 913 policy->ProcessAction(action_dom); 914 915 CheckReadData( 916 policy, 917 extension->id(), 918 0, 919 base::Bind(&FullStreamUIPolicyTest::RetrieveActions_LogAndFetchActions)); 920 921 // Now delete them. 922 policy->DeleteDatabase(); 923 924 CheckReadFilteredData( 925 policy, 926 "", 927 Action::ACTION_ANY, 928 "", 929 "", 930 "", 931 -1, 932 base::Bind( 933 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions0)); 934 935 policy->Close(); 936 } 937 938 TEST_F(FullStreamUIPolicyTest, RemoveActions) { 939 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 940 policy->Init(); 941 942 std::vector<int64> action_ids; 943 944 CheckRemoveActions(policy, 945 action_ids, 946 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 947 948 action_ids.push_back(-1); 949 action_ids.push_back(-10); 950 action_ids.push_back(0); 951 action_ids.push_back(5); 952 action_ids.push_back(10); 953 CheckRemoveActions(policy, 954 action_ids, 955 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 956 action_ids.clear(); 957 958 for (int i = 0; i < 50; i++) { 959 action_ids.push_back(i + 5); 960 } 961 CheckRemoveActions(policy, 962 action_ids, 963 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 964 action_ids.clear(); 965 966 // CheckRemoveActions pushes four actions to the Activity Log database with 967 // IDs 1, 2, 3, and 4. 968 action_ids.push_back(1); 969 action_ids.push_back(2); 970 action_ids.push_back(3); 971 action_ids.push_back(4); 972 CheckRemoveActions(policy, 973 action_ids, 974 base::Bind(&FullStreamUIPolicyTest::AllActionsDeleted)); 975 action_ids.clear(); 976 977 action_ids.push_back(1); 978 action_ids.push_back(2); 979 CheckRemoveActions( 980 policy, action_ids, base::Bind(&FullStreamUIPolicyTest::Action1Deleted)); 981 action_ids.clear(); 982 983 action_ids.push_back(3); 984 action_ids.push_back(4); 985 CheckRemoveActions( 986 policy, action_ids, base::Bind(&FullStreamUIPolicyTest::Action2Deleted)); 987 action_ids.clear(); 988 989 policy->Close(); 990 } 991 992 } // namespace extensions 993