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/scoped_test_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 32using content::BrowserThread; 33 34namespace extensions { 35 36class 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.get(), 158 "odlameecjipmbmbejkplpemijjgpljce", 159 Action::ACTION_API_CALL, 160 "extension.connect", 161 "[\"hello\",\"world\"]", 162 "", 163 "", 164 ""); 165 } 166 167 static void Arguments_GetTodaysActions( 168 scoped_ptr<Action::ActionVector> actions) { 169 ASSERT_EQ(2, static_cast<int>(actions->size())); 170 CheckAction(*actions->at(0).get(), 171 "punky", 172 Action::ACTION_DOM_ACCESS, 173 "lets", 174 "[\"vamoose\"]", 175 "http://www.google.com/", 176 "Page Title", 177 "http://www.arg-url.com/"); 178 CheckAction(*actions->at(1).get(), 179 "punky", 180 Action::ACTION_API_CALL, 181 "brewster", 182 "[\"woof\"]", 183 "", 184 "Page Title", 185 "http://www.arg-url.com/"); 186 } 187 188 static void Arguments_GetOlderActions( 189 scoped_ptr<Action::ActionVector> actions) { 190 ASSERT_EQ(2, static_cast<int>(actions->size())); 191 CheckAction(*actions->at(0).get(), 192 "punky", 193 Action::ACTION_DOM_ACCESS, 194 "lets", 195 "[\"vamoose\"]", 196 "http://www.google.com/", 197 "", 198 ""); 199 CheckAction(*actions->at(1).get(), 200 "punky", 201 Action::ACTION_API_CALL, 202 "brewster", 203 "[\"woof\"]", 204 "", 205 "", 206 ""); 207 } 208 209 static void AllURLsRemoved(scoped_ptr<Action::ActionVector> actions) { 210 ASSERT_EQ(2, static_cast<int>(actions->size())); 211 CheckAction(*actions->at(0).get(), 212 "punky", 213 Action::ACTION_API_CALL, 214 "lets", 215 "[\"vamoose\"]", 216 "", 217 "", 218 ""); 219 CheckAction(*actions->at(1).get(), 220 "punky", 221 Action::ACTION_DOM_ACCESS, 222 "lets", 223 "[\"vamoose\"]", 224 "", 225 "", 226 ""); 227 } 228 229 static void SomeURLsRemoved(scoped_ptr<Action::ActionVector> actions) { 230 // These will be in the vector in reverse time order. 231 ASSERT_EQ(5, static_cast<int>(actions->size())); 232 CheckAction(*actions->at(0).get(), 233 "punky", 234 Action::ACTION_DOM_ACCESS, 235 "lets", 236 "[\"vamoose\"]", 237 "http://www.google.com/", 238 "Google", 239 "http://www.args-url.com/"); 240 CheckAction(*actions->at(1).get(), 241 "punky", 242 Action::ACTION_DOM_ACCESS, 243 "lets", 244 "[\"vamoose\"]", 245 "http://www.google.com/", 246 "Google", 247 ""); 248 CheckAction(*actions->at(2).get(), 249 "punky", 250 Action::ACTION_DOM_ACCESS, 251 "lets", 252 "[\"vamoose\"]", 253 "", 254 "", 255 ""); 256 CheckAction(*actions->at(3).get(), 257 "punky", 258 Action::ACTION_DOM_ACCESS, 259 "lets", 260 "[\"vamoose\"]", 261 "", 262 "", 263 "http://www.google.com/"); 264 CheckAction(*actions->at(4).get(), 265 "punky", 266 Action::ACTION_DOM_ACCESS, 267 "lets", 268 "[\"vamoose\"]", 269 "", 270 "", 271 ""); 272 } 273 274 static void CheckAction(const Action& action, 275 const std::string& expected_id, 276 const Action::ActionType& expected_type, 277 const std::string& expected_api_name, 278 const std::string& expected_args_str, 279 const std::string& expected_page_url, 280 const std::string& expected_page_title, 281 const std::string& expected_arg_url) { 282 ASSERT_EQ(expected_id, action.extension_id()); 283 ASSERT_EQ(expected_type, action.action_type()); 284 ASSERT_EQ(expected_api_name, action.api_name()); 285 ASSERT_EQ(expected_args_str, 286 ActivityLogPolicy::Util::Serialize(action.args())); 287 ASSERT_EQ(expected_page_url, action.SerializePageUrl()); 288 ASSERT_EQ(expected_page_title, action.page_title()); 289 ASSERT_EQ(expected_arg_url, action.SerializeArgUrl()); 290 ASSERT_NE(-1, action.action_id()); 291 } 292 293 // A helper function initializes the policy with a number of actions, calls 294 // RemoveActions on a policy object and then checks the result of the 295 // deletion. 296 void CheckRemoveActions( 297 ActivityLogDatabasePolicy* policy, 298 const std::vector<int64>& action_ids, 299 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { 300 301 // Use a mock clock to ensure that events are not recorded on the wrong day 302 // when the test is run close to local midnight. 303 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 304 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 305 base::TimeDelta::FromHours(12)); 306 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 307 308 // Record some actions 309 scoped_refptr<Action> action = 310 new Action("punky1", 311 mock_clock->Now() - base::TimeDelta::FromMinutes(40), 312 Action::ACTION_DOM_ACCESS, 313 "lets1"); 314 action->mutable_args()->AppendString("vamoose1"); 315 action->set_page_url(GURL("http://www.google1.com")); 316 action->set_page_title("Google1"); 317 action->set_arg_url(GURL("http://www.args-url1.com")); 318 policy->ProcessAction(action); 319 // Record the same action twice, so there are multiple entries in the 320 // database. 321 policy->ProcessAction(action); 322 323 action = new Action("punky2", 324 mock_clock->Now() - base::TimeDelta::FromMinutes(30), 325 Action::ACTION_API_CALL, 326 "lets2"); 327 action->mutable_args()->AppendString("vamoose2"); 328 action->set_page_url(GURL("http://www.google2.com")); 329 action->set_page_title("Google2"); 330 action->set_arg_url(GURL("http://www.args-url2.com")); 331 policy->ProcessAction(action); 332 // Record the same action twice, so there are multiple entries in the 333 // database. 334 policy->ProcessAction(action); 335 336 // Submit a request to delete actions. 337 policy->RemoveActions(action_ids); 338 339 // Check the result of the deletion. The checker function gets all 340 // activities in the database. 341 CheckReadData(policy, "", -1, checker); 342 343 // Clean database. 344 policy->DeleteDatabase(); 345 } 346 347 static void AllActionsDeleted(scoped_ptr<Action::ActionVector> actions) { 348 ASSERT_EQ(0, static_cast<int>(actions->size())); 349 } 350 351 static void NoActionsDeleted(scoped_ptr<Action::ActionVector> actions) { 352 // These will be in the vector in reverse time order. 353 ASSERT_EQ(4, static_cast<int>(actions->size())); 354 CheckAction(*actions->at(0).get(), 355 "punky2", 356 Action::ACTION_API_CALL, 357 "lets2", 358 "[\"vamoose2\"]", 359 "http://www.google2.com/", 360 "Google2", 361 "http://www.args-url2.com/"); 362 ASSERT_EQ(3, actions->at(0)->action_id()); 363 CheckAction(*actions->at(1).get(), 364 "punky2", 365 Action::ACTION_API_CALL, 366 "lets2", 367 "[\"vamoose2\"]", 368 "http://www.google2.com/", 369 "Google2", 370 "http://www.args-url2.com/"); 371 ASSERT_EQ(4, actions->at(1)->action_id()); 372 CheckAction(*actions->at(2).get(), 373 "punky1", 374 Action::ACTION_DOM_ACCESS, 375 "lets1", 376 "[\"vamoose1\"]", 377 "http://www.google1.com/", 378 "Google1", 379 "http://www.args-url1.com/"); 380 ASSERT_EQ(1, actions->at(2)->action_id()); 381 CheckAction(*actions->at(3).get(), 382 "punky1", 383 Action::ACTION_DOM_ACCESS, 384 "lets1", 385 "[\"vamoose1\"]", 386 "http://www.google1.com/", 387 "Google1", 388 "http://www.args-url1.com/"); 389 ASSERT_EQ(2, actions->at(3)->action_id()); 390 } 391 392 static void Action1Deleted(scoped_ptr<Action::ActionVector> actions) { 393 // These will be in the vector in reverse time order. 394 ASSERT_EQ(2, static_cast<int>(actions->size())); 395 CheckAction(*actions->at(0).get(), 396 "punky2", 397 Action::ACTION_API_CALL, 398 "lets2", 399 "[\"vamoose2\"]", 400 "http://www.google2.com/", 401 "Google2", 402 "http://www.args-url2.com/"); 403 ASSERT_EQ(3, actions->at(0)->action_id()); 404 CheckAction(*actions->at(1).get(), 405 "punky2", 406 Action::ACTION_API_CALL, 407 "lets2", 408 "[\"vamoose2\"]", 409 "http://www.google2.com/", 410 "Google2", 411 "http://www.args-url2.com/"); 412 ASSERT_EQ(4, actions->at(1)->action_id()); 413 } 414 415 static void Action2Deleted(scoped_ptr<Action::ActionVector> actions) { 416 // These will be in the vector in reverse time order. 417 ASSERT_EQ(2, static_cast<int>(actions->size())); 418 CheckAction(*actions->at(0).get(), 419 "punky1", 420 Action::ACTION_DOM_ACCESS, 421 "lets1", 422 "[\"vamoose1\"]", 423 "http://www.google1.com/", 424 "Google1", 425 "http://www.args-url1.com/"); 426 ASSERT_EQ(1, actions->at(0)->action_id()); 427 CheckAction(*actions->at(1).get(), 428 "punky1", 429 Action::ACTION_DOM_ACCESS, 430 "lets1", 431 "[\"vamoose1\"]", 432 "http://www.google1.com/", 433 "Google1", 434 "http://www.args-url1.com/"); 435 ASSERT_EQ(2, actions->at(1)->action_id()); 436 } 437 438 protected: 439 ExtensionService* extension_service_; 440 scoped_ptr<TestingProfile> profile_; 441 content::TestBrowserThreadBundle thread_bundle_; 442 // Used to preserve a copy of the original command line. 443 // The test framework will do this itself as well. However, by then, 444 // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in 445 // TearDown(). 446 CommandLine saved_cmdline_; 447 448#if defined OS_CHROMEOS 449 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 450 chromeos::ScopedTestCrosSettings test_cros_settings_; 451 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; 452#endif 453}; 454 455TEST_F(FullStreamUIPolicyTest, Construct) { 456 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 457 policy->Init(); 458 scoped_refptr<const Extension> extension = 459 ExtensionBuilder() 460 .SetManifest(DictionaryBuilder() 461 .Set("name", "Test extension") 462 .Set("version", "1.0.0") 463 .Set("manifest_version", 2)) 464 .Build(); 465 extension_service_->AddExtension(extension.get()); 466 scoped_ptr<base::ListValue> args(new base::ListValue()); 467 scoped_refptr<Action> action = new Action(extension->id(), 468 base::Time::Now(), 469 Action::ACTION_API_CALL, 470 "tabs.testMethod"); 471 action->set_args(args.Pass()); 472 policy->ProcessAction(action); 473 policy->Close(); 474} 475 476TEST_F(FullStreamUIPolicyTest, LogAndFetchActions) { 477 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 478 policy->Init(); 479 scoped_refptr<const Extension> extension = 480 ExtensionBuilder() 481 .SetManifest(DictionaryBuilder() 482 .Set("name", "Test extension") 483 .Set("version", "1.0.0") 484 .Set("manifest_version", 2)) 485 .Build(); 486 extension_service_->AddExtension(extension.get()); 487 GURL gurl("http://www.google.com"); 488 489 // Write some API calls 490 scoped_refptr<Action> action_api = new Action(extension->id(), 491 base::Time::Now(), 492 Action::ACTION_API_CALL, 493 "tabs.testMethod"); 494 action_api->set_args(make_scoped_ptr(new base::ListValue())); 495 policy->ProcessAction(action_api); 496 497 scoped_refptr<Action> action_dom = new Action(extension->id(), 498 base::Time::Now(), 499 Action::ACTION_DOM_ACCESS, 500 "document.write"); 501 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 502 action_dom->set_page_url(gurl); 503 policy->ProcessAction(action_dom); 504 505 CheckReadData( 506 policy, 507 extension->id(), 508 0, 509 base::Bind(&FullStreamUIPolicyTest::RetrieveActions_LogAndFetchActions)); 510 511 policy->Close(); 512} 513 514TEST_F(FullStreamUIPolicyTest, LogAndFetchFilteredActions) { 515 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 516 policy->Init(); 517 scoped_refptr<const Extension> extension = 518 ExtensionBuilder() 519 .SetManifest(DictionaryBuilder() 520 .Set("name", "Test extension") 521 .Set("version", "1.0.0") 522 .Set("manifest_version", 2)) 523 .Build(); 524 extension_service_->AddExtension(extension.get()); 525 GURL gurl("http://www.google.com"); 526 527 // Write some API calls 528 scoped_refptr<Action> action_api = new Action(extension->id(), 529 base::Time::Now(), 530 Action::ACTION_API_CALL, 531 "tabs.testMethod"); 532 action_api->set_args(make_scoped_ptr(new base::ListValue())); 533 policy->ProcessAction(action_api); 534 535 scoped_refptr<Action> action_dom = new Action(extension->id(), 536 base::Time::Now(), 537 Action::ACTION_DOM_ACCESS, 538 "document.write"); 539 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 540 action_dom->set_page_url(gurl); 541 policy->ProcessAction(action_dom); 542 543 CheckReadFilteredData( 544 policy, 545 extension->id(), 546 Action::ACTION_API_CALL, 547 "tabs.testMethod", 548 "", 549 "", 550 -1, 551 base::Bind( 552 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 553 554 CheckReadFilteredData( 555 policy, 556 "", 557 Action::ACTION_DOM_ACCESS, 558 "", 559 "", 560 "", 561 -1, 562 base::Bind( 563 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 564 565 CheckReadFilteredData( 566 policy, 567 "", 568 Action::ACTION_DOM_ACCESS, 569 "", 570 "http://www.google.com/", 571 "", 572 -1, 573 base::Bind( 574 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 575 576 CheckReadFilteredData( 577 policy, 578 "", 579 Action::ACTION_DOM_ACCESS, 580 "", 581 "http://www.google.com", 582 "", 583 -1, 584 base::Bind( 585 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 586 587 CheckReadFilteredData( 588 policy, 589 "", 590 Action::ACTION_DOM_ACCESS, 591 "", 592 "http://www.goo", 593 "", 594 -1, 595 base::Bind( 596 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 597 598 CheckReadFilteredData( 599 policy, 600 extension->id(), 601 Action::ACTION_ANY, 602 "", 603 "", 604 "", 605 -1, 606 base::Bind( 607 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions2)); 608 609 policy->Close(); 610} 611 612TEST_F(FullStreamUIPolicyTest, LogWithArguments) { 613 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 614 policy->Init(); 615 scoped_refptr<const Extension> extension = 616 ExtensionBuilder() 617 .SetManifest(DictionaryBuilder() 618 .Set("name", "Test extension") 619 .Set("version", "1.0.0") 620 .Set("manifest_version", 2)) 621 .Build(); 622 extension_service_->AddExtension(extension.get()); 623 624 scoped_ptr<base::ListValue> args(new base::ListValue()); 625 args->Set(0, new base::StringValue("hello")); 626 args->Set(1, new base::StringValue("world")); 627 scoped_refptr<Action> action = new Action(extension->id(), 628 base::Time::Now(), 629 Action::ACTION_API_CALL, 630 "extension.connect"); 631 action->set_args(args.Pass()); 632 633 policy->ProcessAction(action); 634 CheckReadData(policy, 635 extension->id(), 636 0, 637 base::Bind(&FullStreamUIPolicyTest::Arguments_Present)); 638 policy->Close(); 639} 640 641TEST_F(FullStreamUIPolicyTest, GetTodaysActions) { 642 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 643 policy->Init(); 644 645 // Use a mock clock to ensure that events are not recorded on the wrong day 646 // when the test is run close to local midnight. Note: Ownership is passed 647 // to the policy, but we still keep a pointer locally. The policy will take 648 // care of destruction; this is safe since the policy outlives all our 649 // accesses to the mock clock. 650 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 651 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 652 base::TimeDelta::FromHours(12)); 653 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 654 655 // Record some actions 656 scoped_refptr<Action> action = 657 new Action("punky", 658 mock_clock->Now() - base::TimeDelta::FromMinutes(40), 659 Action::ACTION_API_CALL, 660 "brewster"); 661 action->mutable_args()->AppendString("woof"); 662 action->set_arg_url(GURL("http://www.arg-url.com")); 663 action->set_page_title("Page Title"); 664 policy->ProcessAction(action); 665 666 action = 667 new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 668 action->mutable_args()->AppendString("vamoose"); 669 action->set_page_url(GURL("http://www.google.com")); 670 action->set_arg_url(GURL("http://www.arg-url.com")); 671 action->set_page_title("Page Title"); 672 policy->ProcessAction(action); 673 674 action = new Action( 675 "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 676 action->mutable_args()->AppendString("vamoose"); 677 action->set_page_url(GURL("http://www.google.com")); 678 action->set_arg_url(GURL("http://www.arg-url.com")); 679 policy->ProcessAction(action); 680 681 CheckReadData( 682 policy, 683 "punky", 684 0, 685 base::Bind(&FullStreamUIPolicyTest::Arguments_GetTodaysActions)); 686 policy->Close(); 687} 688 689// Check that we can read back less recent actions in the db. 690TEST_F(FullStreamUIPolicyTest, GetOlderActions) { 691 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 692 policy->Init(); 693 694 // Use a mock clock to ensure that events are not recorded on the wrong day 695 // when the test is run close to local midnight. 696 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 697 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 698 base::TimeDelta::FromHours(12)); 699 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 700 701 // Record some actions 702 scoped_refptr<Action> action = 703 new Action("punky", 704 mock_clock->Now() - base::TimeDelta::FromDays(3) - 705 base::TimeDelta::FromMinutes(40), 706 Action::ACTION_API_CALL, 707 "brewster"); 708 action->mutable_args()->AppendString("woof"); 709 policy->ProcessAction(action); 710 711 action = new Action("punky", 712 mock_clock->Now() - base::TimeDelta::FromDays(3), 713 Action::ACTION_DOM_ACCESS, 714 "lets"); 715 action->mutable_args()->AppendString("vamoose"); 716 action->set_page_url(GURL("http://www.google.com")); 717 policy->ProcessAction(action); 718 719 action = new Action("punky", 720 mock_clock->Now(), 721 Action::ACTION_DOM_ACCESS, 722 "lets"); 723 action->mutable_args()->AppendString("too new"); 724 action->set_page_url(GURL("http://www.google.com")); 725 policy->ProcessAction(action); 726 727 action = new Action("punky", 728 mock_clock->Now() - base::TimeDelta::FromDays(7), 729 Action::ACTION_DOM_ACCESS, 730 "lets"); 731 action->mutable_args()->AppendString("too old"); 732 action->set_page_url(GURL("http://www.google.com")); 733 policy->ProcessAction(action); 734 735 CheckReadData( 736 policy, 737 "punky", 738 3, 739 base::Bind(&FullStreamUIPolicyTest::Arguments_GetOlderActions)); 740 policy->Close(); 741} 742 743TEST_F(FullStreamUIPolicyTest, RemoveAllURLs) { 744 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 745 policy->Init(); 746 747 // Use a mock clock to ensure that events are not recorded on the wrong day 748 // when the test is run close to local midnight. 749 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 750 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 751 base::TimeDelta::FromHours(12)); 752 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 753 754 // Record some actions 755 scoped_refptr<Action> action = 756 new Action("punky", mock_clock->Now(), 757 Action::ACTION_DOM_ACCESS, "lets"); 758 action->mutable_args()->AppendString("vamoose"); 759 action->set_page_url(GURL("http://www.google.com")); 760 action->set_page_title("Google"); 761 action->set_arg_url(GURL("http://www.google.com")); 762 policy->ProcessAction(action); 763 764 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 765 action = new Action( 766 "punky", mock_clock->Now(), Action::ACTION_API_CALL, "lets"); 767 action->mutable_args()->AppendString("vamoose"); 768 action->set_page_url(GURL("http://www.google2.com")); 769 action->set_page_title("Google"); 770 // Deliberately no arg url set to make sure it still works when there is no 771 // arg url. 772 policy->ProcessAction(action); 773 774 // Clean all the URLs. 775 std::vector<GURL> no_url_restrictions; 776 policy->RemoveURLs(no_url_restrictions); 777 778 CheckReadData( 779 policy, 780 "punky", 781 0, 782 base::Bind(&FullStreamUIPolicyTest::AllURLsRemoved)); 783 policy->Close(); 784} 785 786TEST_F(FullStreamUIPolicyTest, RemoveSpecificURLs) { 787 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 788 policy->Init(); 789 790 // Use a mock clock to ensure that events are not recorded on the wrong day 791 // when the test is run close to local midnight. 792 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 793 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 794 base::TimeDelta::FromHours(12)); 795 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 796 797 // Record some actions 798 // This should have the page url and args url cleared. 799 scoped_refptr<Action> action = new Action("punky", mock_clock->Now(), 800 Action::ACTION_DOM_ACCESS, "lets"); 801 action->mutable_args()->AppendString("vamoose"); 802 action->set_page_url(GURL("http://www.google1.com")); 803 action->set_page_title("Google"); 804 action->set_arg_url(GURL("http://www.google1.com")); 805 policy->ProcessAction(action); 806 807 // This should have the page url cleared but not args url. 808 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 809 action = new Action( 810 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 811 action->mutable_args()->AppendString("vamoose"); 812 action->set_page_url(GURL("http://www.google1.com")); 813 action->set_page_title("Google"); 814 action->set_arg_url(GURL("http://www.google.com")); 815 policy->ProcessAction(action); 816 817 // This should have the page url cleared. The args url is deliberately not set 818 // to make sure this doesn't cause any issues. 819 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 820 action = new Action( 821 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 822 action->mutable_args()->AppendString("vamoose"); 823 action->set_page_url(GURL("http://www.google2.com")); 824 action->set_page_title("Google"); 825 policy->ProcessAction(action); 826 827 // This should have the args url cleared but not the page url or page title. 828 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 829 action = new Action( 830 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 831 action->mutable_args()->AppendString("vamoose"); 832 action->set_page_url(GURL("http://www.google.com")); 833 action->set_page_title("Google"); 834 action->set_arg_url(GURL("http://www.google1.com")); 835 policy->ProcessAction(action); 836 837 // This should have neither cleared. 838 mock_clock->Advance(base::TimeDelta::FromSeconds(1)); 839 action = new Action( 840 "punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); 841 action->mutable_args()->AppendString("vamoose"); 842 action->set_page_url(GURL("http://www.google.com")); 843 action->set_page_title("Google"); 844 action->set_arg_url(GURL("http://www.args-url.com")); 845 policy->ProcessAction(action); 846 847 // Clean some URLs. 848 std::vector<GURL> urls; 849 urls.push_back(GURL("http://www.google1.com")); 850 urls.push_back(GURL("http://www.google2.com")); 851 urls.push_back(GURL("http://www.url_not_in_db.com")); 852 policy->RemoveURLs(urls); 853 854 CheckReadData( 855 policy, 856 "punky", 857 0, 858 base::Bind(&FullStreamUIPolicyTest::SomeURLsRemoved)); 859 policy->Close(); 860} 861 862TEST_F(FullStreamUIPolicyTest, RemoveExtensionData) { 863 FullStreamUIPolicy* policy = new FullStreamUIPolicy(profile_.get()); 864 policy->Init(); 865 866 // Use a mock clock to ensure that events are not recorded on the wrong day 867 // when the test is run close to local midnight. 868 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); 869 mock_clock->SetNow(base::Time::Now().LocalMidnight() + 870 base::TimeDelta::FromHours(12)); 871 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); 872 873 // Record some actions 874 scoped_refptr<Action> action = new Action("deleteextensiondata", 875 mock_clock->Now(), 876 Action::ACTION_DOM_ACCESS, 877 "lets"); 878 action->mutable_args()->AppendString("vamoose"); 879 action->set_page_title("Google"); 880 action->set_arg_url(GURL("http://www.google.com")); 881 policy->ProcessAction(action); 882 policy->ProcessAction(action); 883 policy->ProcessAction(action); 884 885 scoped_refptr<Action> action2 = new Action("dontdelete", 886 mock_clock->Now(), 887 Action::ACTION_DOM_ACCESS, 888 "lets"); 889 action->mutable_args()->AppendString("vamoose"); 890 action->set_page_title("Google"); 891 action->set_arg_url(GURL("http://www.google.com")); 892 policy->ProcessAction(action2); 893 894 policy->Flush(); 895 policy->RemoveExtensionData("deleteextensiondata"); 896 897 CheckReadFilteredData( 898 policy, 899 "deleteextensiondata", 900 Action::ACTION_ANY, 901 "", 902 "", 903 "", 904 -1, 905 base::Bind( 906 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions0)); 907 908 CheckReadFilteredData( 909 policy, 910 "dontdelete", 911 Action::ACTION_ANY, 912 "", 913 "", 914 "", 915 -1, 916 base::Bind( 917 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions1)); 918 policy->Close(); 919} 920 921TEST_F(FullStreamUIPolicyTest, CapReturns) { 922 FullStreamUIPolicy* policy = new FullStreamUIPolicy(profile_.get()); 923 policy->Init(); 924 925 for (int i = 0; i < 305; i++) { 926 scoped_refptr<Action> action = 927 new Action("punky", 928 base::Time::Now(), 929 Action::ACTION_API_CALL, 930 base::StringPrintf("apicall_%d", i)); 931 policy->ProcessAction(action); 932 } 933 934 policy->Flush(); 935 BrowserThread::PostTaskAndReply( 936 BrowserThread::DB, 937 FROM_HERE, 938 base::Bind(&base::DoNothing), 939 base::MessageLoop::current()->QuitClosure()); 940 base::MessageLoop::current()->Run(); 941 942 CheckReadFilteredData( 943 policy, 944 "punky", 945 Action::ACTION_ANY, 946 "", 947 "", 948 "", 949 -1, 950 base::Bind( 951 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions300)); 952 policy->Close(); 953} 954 955TEST_F(FullStreamUIPolicyTest, DeleteDatabase) { 956 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 957 policy->Init(); 958 scoped_refptr<const Extension> extension = 959 ExtensionBuilder() 960 .SetManifest(DictionaryBuilder() 961 .Set("name", "Test extension") 962 .Set("version", "1.0.0") 963 .Set("manifest_version", 2)) 964 .Build(); 965 extension_service_->AddExtension(extension.get()); 966 GURL gurl("http://www.google.com"); 967 968 // Write some API calls. 969 scoped_refptr<Action> action_api = new Action(extension->id(), 970 base::Time::Now(), 971 Action::ACTION_API_CALL, 972 "tabs.testMethod"); 973 action_api->set_args(make_scoped_ptr(new base::ListValue())); 974 policy->ProcessAction(action_api); 975 976 scoped_refptr<Action> action_dom = new Action(extension->id(), 977 base::Time::Now(), 978 Action::ACTION_DOM_ACCESS, 979 "document.write"); 980 action_dom->set_args(make_scoped_ptr(new base::ListValue())); 981 action_dom->set_page_url(gurl); 982 policy->ProcessAction(action_dom); 983 984 CheckReadData( 985 policy, 986 extension->id(), 987 0, 988 base::Bind(&FullStreamUIPolicyTest::RetrieveActions_LogAndFetchActions)); 989 990 // Now delete them. 991 policy->DeleteDatabase(); 992 993 CheckReadFilteredData( 994 policy, 995 "", 996 Action::ACTION_ANY, 997 "", 998 "", 999 "", 1000 -1, 1001 base::Bind( 1002 &FullStreamUIPolicyTest::RetrieveActions_FetchFilteredActions0)); 1003 1004 policy->Close(); 1005} 1006 1007TEST_F(FullStreamUIPolicyTest, RemoveActions) { 1008 ActivityLogDatabasePolicy* policy = new FullStreamUIPolicy(profile_.get()); 1009 policy->Init(); 1010 1011 std::vector<int64> action_ids; 1012 1013 CheckRemoveActions(policy, 1014 action_ids, 1015 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 1016 1017 action_ids.push_back(-1); 1018 action_ids.push_back(-10); 1019 action_ids.push_back(0); 1020 action_ids.push_back(5); 1021 action_ids.push_back(10); 1022 CheckRemoveActions(policy, 1023 action_ids, 1024 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 1025 action_ids.clear(); 1026 1027 for (int i = 0; i < 50; i++) { 1028 action_ids.push_back(i + 5); 1029 } 1030 CheckRemoveActions(policy, 1031 action_ids, 1032 base::Bind(&FullStreamUIPolicyTest::NoActionsDeleted)); 1033 action_ids.clear(); 1034 1035 // CheckRemoveActions pushes four actions to the Activity Log database with 1036 // IDs 1, 2, 3, and 4. 1037 action_ids.push_back(1); 1038 action_ids.push_back(2); 1039 action_ids.push_back(3); 1040 action_ids.push_back(4); 1041 CheckRemoveActions(policy, 1042 action_ids, 1043 base::Bind(&FullStreamUIPolicyTest::AllActionsDeleted)); 1044 action_ids.clear(); 1045 1046 action_ids.push_back(1); 1047 action_ids.push_back(2); 1048 CheckRemoveActions( 1049 policy, action_ids, base::Bind(&FullStreamUIPolicyTest::Action1Deleted)); 1050 action_ids.clear(); 1051 1052 action_ids.push_back(3); 1053 action_ids.push_back(4); 1054 CheckRemoveActions( 1055 policy, action_ids, base::Bind(&FullStreamUIPolicyTest::Action2Deleted)); 1056 action_ids.clear(); 1057 1058 policy->Close(); 1059} 1060 1061} // namespace extensions 1062