Home | History | Annotate | Download | only in activity_log
      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