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/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 
     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.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 
    455 TEST_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 
    476 TEST_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 
    514 TEST_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 
    612 TEST_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 
    641 TEST_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.
    690 TEST_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 
    743 TEST_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 
    786 TEST_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 
    862 TEST_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 
    921 TEST_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 
    955 TEST_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 
   1007 TEST_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